Saturday, October 19, 2024

Linux Mint tutorial part 3 - Overview and customization

Now that Linux Mint is successfully installed (hopefully), is time to make it look like you want to and get familiar with some of its features.

 

Contents

 

Welcome screen

Linux Mint customization 01 - Default theme

The Welcome screen app presents the user the most common apps used to set up your system and can be disabled by unchecking the "Show this dialog at startup". This apps can also be found by launching the System Settings from the Start menu or by searching the app in the Start menu.

Linux Mint customization 02 - Settings icon

Linux Mint customization 03 - System settings
 

Linux Mint Theme

Linux Mint customization 04 - Theme

Here you can choose a light, dark or a mixed theme. Changing the Style will also change how Icons look, so try something that you like. I keep the file explorer open during this to have a better idea how the design will be affected. If you want more control over default styles, switch to Advanced settings.

Tuesday, October 15, 2024

Linux Mint dual boot tutorial part 2 - How to install Linux Mint (My Linux experience)

This is part 2 on Linux Mint tutorials. For a list of chapters visit: My Linux experience part 1

If you plan on dual booting, I suggest installing Windows first then Linux. I'm not sure if this makes a difference but this is how it was in my case and didn't have any problems booting.

Once you have Windows installed, the first step is to create a new partition for Linux. Until Linux is installed we have to modify and format partitions and that can lead to data loss. Make sure you have a backup. In case you have multiple data storage devices connected, it is preferred to disconnect them so you don't get confused which one needs formatting.

Contents

Saturday, October 12, 2024

Linux Mint dual boot tutorial - My Linux experience, Introduction

I have been using Linux Mint for a few months now and so i have decided to make a series of tutorials describing my experience with Linux and showing you step-by-step tutorials on how to use it, configure it and solve most common issues.

The decision to move permanently to Linux was when Microsoft decided to make Windows the most privacy invasive software on the planet by including that feature named... well i can't recall the name right now. Even Windows 10 has so much telemetry that anything you click or do generates traffic to Microsoft that is a waste of resources at best.

There are many Linux distributions out there such as Ubuntu, Arch, Manjaro, Zorin OS, Fedora, Debian, but I decided to use Mint which is based on Ubuntu since is often chosen for its stability, user-friendly interface, and ease of use, making it a great option for those transitioning from Windows like myself. It's also low on memory usage.

You shouldn't be a programmer to use an OS like Linux 

I'm not a Linux expert, so it will be easier for someone else to understand what I'm explaining in this tutorials. Most tutorials make use of the terminal too much and regular users get overwhelmed considering Linux something to complicated to use so if there's a GUI way, that's what i will use here.

Is Linux a pain in the kernel?

Yes and no. For a beginner it can be. It took me a while to figure out how to make things work the way I wanted, there were issues but in the end I solved them and kept notes in case I need to reinstall Linux. But once you know what to do is easy.

Why dual boot?

I haven't logged into Windows for a while now, and I'm wondering the same thing. But I recommend installing Linux alongside Windows just to see if you like it. Personally I sometimes forget I'm on Linux since Mint has many graphical elements similar to Windows.

Another reason and the most important for dual boot is apps and games. You probably got used to a group of apps and a certain workflow on Windows and you wonder if that can be moved to Linux. That depends on what apps you want to use. Some apps work on both Windows and Linux such as Gimp, Audacity, some have alternatives and some can be run using Wine.

Wine is a free and open-source compatibility layer that allows Windows applications to run on Linux and stands for "Wine Is Not an Emulator," which means that it doesn't emulate the Windows operating system, but instead translates Windows API calls into POSIX calls that can be executed on Linux. This allows users to run Windows applications on Linux without the need for a virtual machine or dual-boot setup.

I've seen people saying they had problems with dual booting. I believe them but up until now I didn't have any. But if you don't want to install Windows just Linux, you can still follow this tutorial.

See you in the next part where we install the Linux Mint operating system.

List of tutorials so far


Saturday, July 6, 2024

Custom RDM6300 firmware RFID reader/writter for EM4100, T5577 ICs

So I bought an RDM6300 RFID card/tag reader and realized that it cannot write tags. Thus, I have decided to add writing capability and to include support for other RFID chips. Original firmware supports only chips that uses the EM4100 protocol but by replacing it with a custom firmware, new protocols can be added.

RDM6300 v2 uses the C8051F330 microcontroller from Silabs which is quite old and has only ~7.5kB of program memory that limits how much the functionality can be expanded. If there is interest, I might make a custom board with a more modern microcontroller and also include a PCB coil to reduce the cost of the RFID module.

Features

RFID frequency: 125kHz
RFID mode: read/write
Supported ICs:
  • EM4100
  • T55xx (e.g. T5577, Blue Trinket tags)
Bit rates: RF/16, RF/32, RF/64
Supported encoding: Manchester
Supported Sequence Terminators (ST):
  • Default (ST bit=0)
  • ST bit=1 and X-Mode=0
  • ST bit=1 and X-Mode=1: not supported as it didn't provide reliable results
 Interface: UART, 115200, 8-bit
 

RDM6300 pinout and schematic 

This, I believe, is the version 2 of the RDM6300 module.

RDM6300 pinout
  • 5V and GND: DC power supply with at least 50mA current capability. The input is protected from reverse voltage by the diode D1. A 3V3 voltage regulator will use this supply to power the C8051F330 micro-controller which is a 3V3 type.
  • 3V3 and GND: the micro-controller can be powered directly using a 3.3V source but I think this is mostly for factory programming. Can be left unconnected.
  • C2CK and C2D: C2 interface used to program the micro-controller. C2CK is the clock pin and C2D is the data pin.
  • RX and TX: UART serial interface used to interact with the firmware. Commands can be sent to RX pin using a serial terminal or another micro-controller, and data is output to the TX pin.
  • Coil 1 and Coil 2: external coil. Polarity is not important.
  • LED: - blink a LED when a tag is detected. The pin will be pulled to ground to turn on the LED so the LED must have the other pin pulled to VCC through a resistor (~1k). At the moment this is not implemented in the custom firmware.
  • GND and Ush pin near the LED: not sure what these are for but you can see them in the schematic. Can be left unconnected.
RDM6300 v2 schematic
RDM6300 v2 schematic (click to enlarge)

Programming RDM6300 with a custom firmware

The firmware can be replaced using a commercial programmer from Silicon Labs or a custom made one. To make a custom C2 programmer you only need an AVR328PB with an USB to serial converter. I have made an in depth tutorial here: https://www.programming-electronics-diy.xyz/2024/03/c2-programmer.html.

The custom programming interface can also be used to interact with the RDM6300 and read data from it, by selecting the Serial mode. Works on Linux and Windows.

C2 programmer interface

Backing up the original firmware

If for some reason you want to use the module with the original firmware, you can do so by uploading the original firmware from the download section.

Flashing the micro-controller

To flash the micro-controller with the custom code use a programmer of your choice and the compiled hex file in the download section. In case you want to modify the code you will need the Simplicity Studio IDE. It's free. To compile the code you will need to sign up for a Keil license which is also free. If you don't know how to use Simplicity Studio, you can find some on this blog.

RDM-6300 API (Application Interface)

When a tag is successfully read, the module will automatically output the default frame.

Default frame format

Default frame consists of two field types, separated by ',' and terminated by a null character '\n'. The frame is repeated according to the corresponding setting (default 4).

Field type 1: integer representing the tag type

  • 1: EM4100
  • 2: T55xxCOMP - T55xx ICs that are set to be compatible with EM4100 readers
  • 3: T55xx

Field type 2: tag data that depends on the tag type

  • EM4100 and T55xxCOMP: 8-bit version/client ID, 32-bit tag number
  • T55xx: 32-bit block. The number of blocks depends on the tag configuration. Most often is 2.

Examples:

03 - T55xx tag type, FFFB0000 - block 1, 00356244 - block 2 in hex format

03,FFFB0000,00356244

01 - EM4100 tag type,  00 - client ID, 79178B56 - tag number in hex format

01,00,79178B56


API data type

 

Output data

All numerical values are returned in HEX format. The reason for this is the space constraint. Since the UART is 8-bit, sending a larger value requires converting the integer to an ASCII string to represent the number and that function takes a lot more flash memory space than converting the integer to ASCII string but in hex format.

Input data

The API expects all input numbers to be an ASCII string since this is again a much more cost effective way regarding memory space.

Serial Commands

A command frame consists of a command number in an ASCII string format, followed by arguments. The command and arguments are separated by ':'. Arguments are separated by ','. End of frame is represented by the null character '\n'.

Command list

These should be copied from rdm.h to ensure they are up to date.

#define CMD_READ_TAG			"0"
#define CMD_READ_INFO			"1"
#define CMD_READ_PAGE			"2"
#define CMD_READ_BLOCK			"3"
#define CMD_READ_BLOCK_PWD		"4"
#define CMD_WRITE_BLOCK			"5"
#define CMD_WRITE_BLOCK_PWD		"6"
#define CMD_RESET			"7"
#define CMD_AOR				"8"
#define CMD_READ_CONF			"9"
#define CMD_READ_CONF_PWD		"10"
#define CMD_W_CONF_MASTER_KEY		"11"
#define CMD_W_CONF_BIT_RATE		"12"
#define CMD_W_CONF_XMODE		"13"
#define CMD_W_CONF_MODULATION		"14"
#define CMD_W_CONF_PSK			"15"
#define CMD_W_CONF_AOR			"16"
#define CMD_W_CONF_OTP			"17"
#define CMD_W_CONF_MAX_BLOCK		"18"
#define CMD_W_CONF_PWD			"19"
#define CMD_W_CONF_MARKER		"20"
#define CMD_W_CONF_FAST_WRITE		"21"
#define CMD_W_CONF_INVERSE_DATA		"22"
#define CMD_W_CONF_POR_DELAY		"23"
#define CMD_READ_DESCRIPTION		"24"
 

Read Tag (CMD_READ_TAG)

Read tag ID.

Usage:

UART_sendInt(0); // send command 0

 

Read traceability data (CMD_READ_INFO)

The two 32-bit blocks are formatted and returned as follows:

  • ACL (8-bits)
  • MFC (8-bits)
  • ICR - IC revision (8-bits)
  • ICR - customer ID (8-bits) 
  • LotID (32-bits)
  • DPW - wafer number (8-bits)
  • DPW - die on wafer number (32-bits)

Example of returned data: E0,39,00,00,000D0D25,19,00005B03

Usage:

UART_sendInt(1); // send command 1

 

Read page (CMD_READ_PAGE)

Arguments:

  1. page number

Return:

Returns block data within a page. Number of blocks are defined by the IC configuration register (default 2).

Usage:

2:1 // send command 2 to read page 1

 

Read block (CMD_READ_BLOCK, CMD_READ_BLOCK_PWD)

Direct reading a block within a page. If the password is active use the CMD_READ_BLOCK_PWD command.

Arguments:

  1. page number
  2. block number
  3. password (only when CMD_READ_BLOCK_PWD is used)

Return:

Returns data from the requested block.

Usage:

3:0,2 // send command 3 to read block 2 from page 0 
4:0,2,1234 // send command 4 to read block 2 from page 0 using the secure password 1234

Write block (CMD_WRITE_BLOCK, CMD_WRITE_BLOCK_PWD)

Write a block within a page. When the password is active, use the CMD_WRITE_BLOCK_PWD command.

Arguments:

  1. page number
  2. block number
  3. lock bit: 0 or 1. If 1, the block will be read-only.
  4. data (32-bit): what to write.
  5. lock bit again: same lock bit but sent twice to avoid user error that could lock the tag.
  6. password (only when CMD_WRITE_BLOCK_PWD is used)

Usage:

5:0,1,0,5577,0 // send command 5 to write 5577 on block 1 from page 0 
6:0,1,0,5577,0,1234 // send command 5 to write 5577 on block 1 from page 0 using the most secure password 1234


Reset (CMD_RESET)

Sends the reset command to the tag.


AOR (CMD_AOR)

When AOR (Answer On Request) mode is active, use this command to activate the tag, by sending the given password.

Arguments:

  1. password

Usage:

8:1234 // send command 8 and the 1234 password to activate the tag


Read configuration register (CMD_READ_CONF, CMD_READ_CONF_PWD)

Register data is formatted and returned in the following format. Each field is maximum 8 bits and separated by ','

  • Master key
  • Data bit rate
  • Extended bit
  • Modulation
  • PSK-CF
  • AOR
  • OTP
  • Max block
  • PWD
  • ST (Sequence Terminator)
  • Fast write bit
  • Inverse data bit
  • POR delay

Note: due to limited space, the function is commented out. A workaround is to read the block 0 directly then use the code inside the rdm_t55xx_parseConfig function to parse the 32-bit value configuration register.


Read tag description (CMD_READ_DESCRIPTION)

Returns more info about the tag. Might be expanded in the future.

Return:

Returns human readable info.

  • "RF/xx": Data bit rate, such as RF/16, RF/32, RF/64. This value is calculated based on the pulse duration an it can be off by 1 or 2. For example instead of 64 might be 65 or 63. This is useful when the configuration register cannot be read initially when the password is active, since the password in not known by the module.
  • "ST:n": ST (Sequence Terminator) bit where n can be 0 or 1.

Write configuration register

The configuration register can be written using the block write command, however, unless you have some pre-calculated values this method leaves room for user error. Using this function, each setting can be modified individually by first reading the register, modifying the desired field value and writing the modified register back to the tag.

Available commands:

  • CMD_W_CONF_MASTER_KEY
  • CMD_W_CONF_BIT_RATE
  • CMD_W_CONF_XMODE
  • CMD_W_CONF_MODULATION
  • CMD_W_CONF_PSK
  • CMD_W_CONF_AOR
  • CMD_W_CONF_OTP
  • CMD_W_CONF_MAX_BLOCK
  • CMD_W_CONF_PWD
  • CMD_W_CONF_MARKER
  • CMD_W_CONF_FAST_WRITE
  • CMD_W_CONF_INVERSE_DATA
  • CMD_W_CONF_POR_DELAY

There are no equivalent commands for when the password is active. If the password is active, set the password argument with a value other than 0.

Note that when setting the Bit Rate, the configuration data value argument must be according to the register shown in the datasheet and not the actual bit rate. For example, for RF/32 the value would be 2 and not 32, for RF/64 the value is 5 not 64, etc.

Arguments:

  1. lock bit
  2. configuration data: maximum 8 bits
  3. password: if the password is not active, set this argument to 0
  4. lock bit again

Usage:

19:0,1,0,0 // send command 19 to set the PWD (password) bit to 1. Lock bit and password are 0.

12:0,2,0,0 // send command 12 to set the bit rate 32. Lock bit and password are 0.

Download

Changelog and license can be found at the beginning of the header files

RDM6300 code Folder including:
- Original firmware (HEX)
- Custom compiled firmware (HEX)
- Source code
Changelog
v1.0 06-07-2024:
- public release

Monday, April 22, 2024

How to use Kodi with SMB on Windows 10 (and wireless printer on wired PC)

With latest versions of Kodi, SMB protocol is not as easy to set up as once was. I spent a day trying to figure out how to make sharing over SMB work with Kodi. I have seen advises saying that the SMB version should be changed to SMB v1 in settings but that was not necessary in my case - default settings works. There are many reasons that could prevent file sharing over SMB and I'm no expert, but I will show the steps I took in order to make things work.

Following steps are also useful for when a wireless printer is not accessible by a wired computer. 


Contents

 

Router AP Isolation

If you have a NAS or simply use a Windows PC to share files using SMB, you first need to make sure that the wired devices can communicate with wireless ones. AP isolation is a feature that prevents your wireless devices from connecting to other networks. It can protect your network from other wireless networks and also protect it from infected devices. This can be disabled in the router settings. In my case I have an ONT router type so I had to contact the ISP and ask them to disable this separation.

Weird router behavior

With my ONT Fiberhome router provided by my ISP Digi there is one more thing to keep in mind. After the router is rebooted, the AP isolation is re-activated. What I have to do then is, turn off the router, unplug the fiber optic cable, turn on the router, wait for the red led to blink and then with the router on, plug the cable back on. Perhaps this setting is removed from memory and when the above steps are made, the setting is reloaded from ISP server.

Check if AP Isolation is off

I use two methods to verify if devices can see each other. First, make sure that the wireless device used is using the local wireless AP to access the internet and not the mobile data.

#1 - Wireless printer: if you have a wireless printer that works on wireless devices, turn it on and get its IP from router LAN - DHCP clients list. With my Brother printer I can connect to it using the IP address in a browser. If the wireless printer web page can be accessed from a wireless device, the printer works. If cannot be accessed from wired device such as a PC, the AP isolation is on.

#2 - Using Snapdrop: if you don't have a wireless printer you can use Snapdrop. Open the link in  browser on a wireless device and on a wired one. Say on a phone and a PC. If you can send a text message between them then AP Isolation is off.

Sharing files in Windows 10

To share a folder in Windows, simply right click on it and open the Properties window. In the Sharing tab click Share... In the share section you can add another account or just write Everyone then click Add.

To remove a shared folder use Advanced Sharing and uncheck Share this folder.

Sharing files in Windows 10 - 01

Next click on Network and Sharing Center and for Private network Turn on network discovery and check Turn on automatic setup of network connected devices.

Sharing files in Windows 10 - 02

Finally in All Networks there are the following settings:

- Public folder sharing (optional)

- Media streaming: I have not used this

- Password protected sharing: if on you must provide the account password when using SMB sharing. I turned of the password here.

Sharing files in Windows 10 - 03

Viewing shared folders in Network Explorer

Before checking the shared folders in Kodi, we need to make sure they appear in Windows Explorer under Network.

Sharing files in Windows 10 - 04

There should be something like this. If not click refresh and wait around 20 seconds to see if the computer name appears. If not press windows key, type Services and open it from the results. There look for Function Discovery Provider Host and Function Discovery Resource Publication. Make sure both are running and set to Automatic. 

Sharing files in Windows 10 - 05

If they are running select Function Discovery Resource Publication and in the left-hand side click on Restart. Now the computer name should appear in the Network Explorer. If not you can try other troubleshooting methods mentioned here: https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/cannot-access-shared-folder-file-explorer.

Using the Private Network profile

This next step is to ensure that you are using a Private network profile by right clicking on the Network icon in the right-hand corner and selecting Open Network and Internet Settings.

Sharing files in Windows 10 - 06

There should say Ethernet - Private network.

Sharing files in Windows 10 - 07

Otherwise switch to a private profile using the Ethernet menu, then click on Network and in the Network page select Private profile.

Sharing files in Windows 10 - 08

Third-party app SMB confirmation

An easy way to check if SMB sharing works is by using an app on Android phone called File Manager by Lufick. There, in the top left corner open the menu and under the Network section open Lan (SMB 2.0). In the bottom right corner tap on the 3 dots then on Start Scan. If everything is set up properly, the computer name and local IP should appear.

Assigning a Static IP

For the final step to work, the PC must have a static IP address on the LAN. For example, my router address is 192.168.1.1 in the Local Area Network so for my PC I have allocated the address 192.168.1.100 because it's easier to remember. This step is router dependent so I cannot show a step-by-step guide. The idea is that you need to find your MAC address of your PC and on the router you associate this MAC address with the desired static IP.

The computer MAC address can be found in Windows Settings - Network & Internet - Ethernet - Network - Properties - Physical address (MAC).

On the router look for DHCP Static Leases or if your router is different search online on where is this feature located.

Accessing shared folders over SMB in Kodi

Using Kodi is out of the scope of this tutorial, so I will not go in to too many details about the interface. That being said, let's add the shared folder in Kodi by browsing for the video source.

SMB and Kodi 01

SMB and Kodi 02

In my case, using Windows network (SMB) didn't show up the shared computer name so i had to use Add network location option. Windows network (SMB) option only worked when Kodi was installed on the same computer.

SMB and Kodi 03

In the Add network location window put your IP address of the server/PC, the username that has access to the shared folders (in my case is Everyone) and the password associated with the user name account. If the account has no password or the password sharing is off, you still need to write something in the password field. I put 1234. It can be anything. After clicking OK, the source should now be ready to use.

SMB and Kodi 04

After selecting it, you can give it a name.

SMB and Kodi 05

To add source to library, open the source and right click on the shared folder to bring up the context menu where you can use Scan to library.

SMB and Kodi 06

SMB and Kodi 07

Configuring TV remote to work with Kodi on Android TV

Initially on my TV, the remote controller didn't work with Kodi which was asking to configure it but I couldn't since it didn't work thus, to configure the remote I used an USB mouse.

To attach a controller in Kodi, go to Settings - System - Input - Configure attached controllers.

Kodi controller configuration 01

Kodi controller configuration 02

As a controller profile I have used Kodi for the TV remote. There is a profile named TV Remote using the Get more... button but it didn't have all the functions I needed. Here is how I mapped the Kodi profile to buttons on the TV remote:

  • A - center button (the one surrounded by arrows on remote)
  • B - back button
  • X - menu (used to access contextual menu on Kodi)
  • Up, Down, Left, Right - to same buttons on the remote

That's it. Share if you found this helpful.

Sunday, March 31, 2024

Simplicity Studio and Keil 8051 compiler issues and tutorial

Working with Simplicity Studio and Keil compiler can be frustrating sometimes. Most of the issues encountered were difficult to solve because the error messages given by the Keil compiler were very confusing. Thus, I will post here the most common issues that I've came across in the hope it will help others and perhaps me in the future.

Contents

 

Keil Error Messages

A list of Keil error codes and their description can be found here: https://developer.arm.com/documentation/101655/0961/Cx51-User-s-Guide/Error-Messages/Errors-and-Warnings/Reference. However, below are scenarios in which the error message and the cause are not related. For example when actually missing a ';' the error message is: syntax error near 'token', expected ';' but when something is not defined because an include file is missing, the error message is: missing ';' before.


missing ';' before

One might think this is obvious - you missed an ';' somewhere. But this is not always the case.

Scenario: error line appears when including a header file.

Solution #1: include SFR declarations in the header file according to the type of the device.

#include <SI_C8051F330_Register_Enums.h>

Solution #2: include stdint.h that defines integer types.

#include <stdint.h>

Solution #3: include stdbool.h.

#include <stdbool.h>

It appears that Keil shows the same error message when a data type is not defined.

 

left side of asn-op not an lvalue

Scenario:

uint64_t test_var = 0;
test_var = 1;

Cause:

Looking at the uint64_t definition in stdint.h reveals the problem:

typedef uint32_t uint64_t[2];

uint64_t is defined as an array of two uint32_t elements so test_var in the example should be used as an array: test_var[0] and test_var[1]

 

syntax error near 'data type', expected '__asm'

Solution: all variables must be defined before any other code.


syntax error near '=', expected '<id>'

Scenario:

uint16_t data = 0;

Solution: i believe data is a reserved keyword. Replacing the variable name with data_x solves the issue. The message 'data is a reserved keyword' should have been used. 

 

Keil no error issues

There are times when you might want the compiler to raise an error message or a warning but it doesn't.

Case #1

 
uint32_t data_x = 0;
data_x = (1 << 31);

This will not make the MSB a one. The 1 should be typecast  (uint32_t)1 << 32. 

 

Simplicity Studio Shortcuts

Here is a list of tips & tricks that can help improve productivity in Simplicity Studio.

  1. Delete a line: CTRL + D
  2. Duplicate a line: CTRL + ALT + DOWN 
  3. Highlight all occurrences of a variable: double click it
  4. Go to last edited line: CTRL + Q
  5. Switch between .h and .c files: CTRL + TAB
  6. Next annotation: CTRL + .
  7. Previous annotation: CTRL + ,
  8. Navigate to previous line history: ALT + LEFT and ALT + RIGHT
  9. Go to where is declared or defined: place cursor on a variable or function name then F3.
  10. Comment/Uncomment: toggle comment selected line(s) using CTRL + /
  11. Block Comment/Uncomment using: toggle comment selected line(s) using CTRL + SHIFT + /
  12. Zoom Out text: CTRL + -
  13. Zoom In text: CTRL + SHIFT + +
  14. Renaming: SHIFT + ALT + R. Sometimes doesn't rename all occurrences. In that case undo, and try again. Saving all files first, might help.
  15. Quick Utility: not sure how it's called but by pressing ALT + SPACE you can invoke some plugins. For example starting the expression with = you can do math.
  16. Content Assist: CTRL + SPACE. Autocompletes or offers a list of suggestions while typing. So if you don't know the name of a function or variable but you remember first characters this can help finding it faster. 
  17. Correct Indentation: CTRL + I
 

    Simplicity Studio 5 Tutorial

    Adding a product (device)

    Press on the Welcome or Launcher button then in My Products section use the + button to add a new product.

    Simplicity Studio v5 - Add Product 01

    On the next window you can search for Kits, Boards and Parts. In this example I use the C8051F330 microcontroller so I have added it in the right side.

    Simplicity Studio v5 - Add Product 02

    At the end, by selecting the added product you can find in the right side, code examples, documentation and compatible tools. Configuration wizard under the compatible tools is worth checking out.

    Creating a new project

    Under File  New select Silicon Labs Project Wizard

    Simplicity Studio v5 - New Project 01

    Next you can search for a board or if you are using a custom board search for target device - the microcontroller. In my case the device is C8051F330. The SDK and Toolchain should also be installed and selected.

    Simplicity Studio v5 - New Project 02

    In the next step you can use an example project or create an empty C project. The Configurator Project can be used to generate code using a graphical interface but is not available for all microcontrollers. Trying to create a configurator project for C8051F330 will result in an error. I did use it with EFM8 and worked very well.

    Simplicity Studio v5 - New Project 03

    Finally chose the project name and location. I recommend changing only the project name and leaving the rest as defaults.

    Simplicity Studio v5 - New Project 04

    Adding Keyboard Shortcuts - Key Binding in Simplicity Studio v5

    In this example lets add a keyboard shortcut for building the selected project. This can be done in Windows  Preferences  General  Keys.

    Adding Shortcuts - Key Binding in Simplicity Studio v5

    First search for the desired command, for example 'build' then select 'Build Project' from the search results. In the Binding input press the key or key combination. If the binding is already used elsewhere, it will appear in the Conflicts box.

    Adding external files in Simplicity Studio

    Linking to external files is useful when you need a library for example and if you update it you don't have to remember to update all files copied in other projects. Including external files can be done in two steps.

    First drag-and-drop the files in the src folder located inside the project folder.

    Simplicity Studio v5 - Adding External Files 00

    Then in the following dialog select 'Link to files'.

    Simplicity Studio v5 - Adding External Files 01

    Last step is to add the include paths in Project Properties  C/C++ Build  Settings  Tool Settings tab  Keil 8051 Compiler  Includes. Here press the + green button then on File system to select the folder where the files included by drag-and-drop are located.

    Simplicity Studio v5 - Adding External Files 02

    In this example I have included the folder containing the uart library files and the folder where utils files are that are included by uart library. 

    Annotations in Simplicity Studio

    An annotation in Simplicity Studio can be a part of many categories such as: bookmarks, breakpoints, info, errors, etc. They can be navigated using the shortcuts CTRL + , and CTRL + . or by using the up and down arrows on the toolbar. They are also highlighted with different colors on the right side bar near the scrollbar. Contrast and colors can be changed by right clicking on the same bar.

    You can enable or disable what is included in annotations category while navigating them. Simply click on the down arrow near any of the annotation buttons on the toolbar to select only what you are interested in.

    Simplicity Studio - Annotations 01

    In case the buttons don't appear, right click on the toolbar and select Restore Hidden Toolbar Entries, then Lock the Toolbars then Unlock the Toolbars. Now the buttons should be visible.

    Simplicity Studio - Annotations 00

    You can add your own annotations such as a bookmark or a task by right clicking on line numbers in the left side bar.

    Simplicity Studio - Annotations 02

    To remove them, right click an annotation and select Remove bookmark or task.


    Friday, March 15, 2024

    Delay functions for Silicon Labs microcontrollers

    Sometimes you need to delay the program execution, for example when waiting for another device to startup or respond and the software cannot continue. An interrupt driven delay is better in most cases but not in all cases. For this purpose I made two functions one for milliseconds and one for microseconds, that uses NOPs to delay the program execution for a certain amount of time. The milliseconds delay is quite accurate, the microseconds one, not so much.

    For this to work, the SYSCLK must be defined first. It is recommended to be defined in the project settings. You can find a short tutorial here on how to add a global define in Simplicity Studio: https://www.programming-electronics-diy.xyz/2024/03/defining-sysclk-or-fcpu-in-simplicity.html

    Tested on:

    - C8051F330

    For other microcontrollers the following SFR declarations include file should be replaced accordingly:

    #include <SI_C8051F330_Register_Enums.h>


    Library usage

     

    Milliseconds delay

     
    _delay_ms(uint32_t ms)
    
     

    Microseconds delay

     
    _delay_us(uint32_t us)
    

    I couldn't figure a way to make millis delay more accurate since the code used to create the delay, adds delay and cannot be easily subtracted because it depends of the delay time. I think it should be implemented using assembly but i don't know the language. If you need just a certain delay time, you could tweak the function for that particular delay, using a logic analyzer.

    Download

    delay
    v1.0 delay Contains delay.h and delay.c

    UART library for Silicon Labs microcontrollers using interrupts

    This UART library is made for Silicon Labs microcontrollers that can be used for serial communications.

    UART is a type of serial interface, as opposed to a parallel interface. A parallel interface can work at higher speeds but the disadvantage is that it needs multiple input/output lines. Other examples of serial interfaces are SPI and I2C. 

    UART library for Silicon Labs microcontrollers using interrupts

    Supported Devices

    At the moment only following devices are supported. I might add more in the feature. It might work for other similar devices not listed below.

    • C8051F330

     

    Contents

     

    UART Characteristics

    Frame format

    A serial frame is composed of a character of data bits with synchronization bits (start and stop bits). 8-Bit UART mode uses a total of 10 bits per data byte: one start bit, eight data bits (LSB first), and one stop bit.

    A frame starts with the start bit, followed by 8 data bits (LSB first). When a complete frame is transmitted, it can be directly followed by a new frame, or the communication line can be set to an idle (high) state. The figure below illustrates the frame format:

    UART frame format 8-bit
    IDLE: No transfers on the communication line (Rx or Tx). An IDLE line must be high.

    Start Bit: always low.

    (D): Data bits (0 to 7).

    Stop Bit: always high.

    The Stop bit can be followed by a Start bit (low) for another frame, or Idle (high). All devices connected to the UART bus must use the same frame format and baud rate.

    Baud Rate

    The baud rate specifies how fast data is sent over a serial line. It's usually expressed in units of bits-per-second (bps). Most commonly used baud rates are 9600 and 115200 bps.

    "The UART0 baud rate is generated by Timer 1 in 8-bit auto-reload mode. The TX clock is generated by TL1; the RX clock is generated by a copy of TL1 (shown as RX Timer in Figure 16.2), which is not user- accessible. Both TX and RX Timer overflows are divided by two to generate the TX and RX baud rates. The RX Timer runs when Timer 1 is enabled, and uses the same reload value (TH1). However, an RX Timer reload is forced when a START condition is detected on the RX pin. This allows a receive to begin any time a START is detected, independent of the TX Timer state." from C8051F330 datasheet chapter 16.

    Wiring

    Lets say you want to interface UART 0 with a device that has this pins: RX and TX. Then you connect RXD0 to TX and TXD0 to RX. Also they must share a common ground.

    For most Silicon Labs microcontrollers the TX/RX pins are as follows:

    TX0 on P0.4, RX on P0.5

    Check the datasheet for your specific device to ensure the pins are correct.

    Library Structure

    The file uart.h defines some user settings that can be modified accordingly.

    TX and RX buffers

    Transmitted and Received data are buffered in two circular arrays that by default have a size of 16 bytes each. The size can be from 1 to 255 bytes. Having a larger array can be a bit faster. When using higher baud rates it is recommended a bigger buffer to avoid loosing incoming data and to give more time for the microcontroller to process the data.

    #define UART_TX_BUFFER_SIZE	16
    #define UART_RX_BUFFER_SIZE	16

    CPU clock frequency - SYSCLK

     
    #define SYSCLK    24500000UL

    SYSCLK defines the processor clock frequency in Hertz and is used to calculate the timeout in some functions. 

    SYSCLK is best to be defined inside project properties in Simplicity Studio (or your particular IDE) or a Makefile if custom Makefiles are used. See https://www.programming-electronics-diy.xyz/2024/03/defining-sysclk-or-fcpu-in-simplicity.html.

    Using UART library

    Initialization function

    Sets TX, RX pins and the crossbar. Configures UART and Timer 1. Sets the baud rate, enables UART interrupts and global interrupts.

    void UART_init(int32_t sysclk, int32_t baudrate)
    

    Parameters

    sysclk

    System clock in Hertz, SYSCLK also known as F_CPU.

    baudrate

    Desired baud rate. Some standard values are: 9600, 14400, 19200, 38400, 57600, 115200, 128000 and 256000.

    Usage:

    UART_init(SYSCLK, 115200);
    
     

    Send a byte

    Puts a byte of data in the transmit buffer and enables the transmit interrupt.

    uint8_t UART_send(uint8_t data)
    

    Parameters

     
    data

    The data byte.

    Return: 0 on success, 1 on failure.

    Usage:

    // Send 'A' ASCII character
    UART_send('A');
    
    // Send '3' ASCII symbol
    UART_send('3');
    
    // Send number of the '3' ASCII symbol
    UART_send(51);
    

    Send a string

    Send a null terminated string.

    uint8_t UART_sendString(char* s)
    

    Parameters

     
    char* s

    A string of characters.

    Return: 0 on success, 1 on failure.

    Usage:

    UART_sendString("Sent from UART0");
    // Or using the '\n' character to start a new line in a serial terminal.
    UART_sendString("Sent from UART0\n");
    

    Send bytes

    Send a series of bytes in a buffer.

    uint8_t UART_sendBytes(uint8_t* buff, uint8_t length)
    

    Parameters


    uint8_t* buff

    Pointer to a byte array.

    uint8_t length

    Length of the array.

    Return: 0 on success, 1 on failure.

    Usage:

    const uint8_t bufferSize = 20;
    uint8_t buff[bufferSize];
    
    // bufferSize argument can be smaller to
    // send only first few bytes
    UART_sendBytes(buff, bufferSize);
    

    Send integer number

    Convert an integer number into a string array and send it over UART.

    void UART_sendInt(INT_SIZE number)
    

    Parameters


    INT_SIZE number

    INT_SIZE is defined in the "utils.h" file, and can be int32_t or int64_t


    Send float number

    Convert a float number into a string array and send it over UART.

    void UART_sendFloat(float number, uint8_t decimals)
    

    Parameters


    float number

    A float number.

    uint8_t decimals

    Number of digits after the dot.


    Send hex numbers

    Convert a 1- 2- or 4-byte integer number into hexadecimal value and send it over UART.

    void UART_sendHex8(uint8_t value)
    void UART_sendHex16(uint16_t value)
    void UART_sendHex32(uint32_t value)
    


    Check for new received data

    Returns true if new data is available and false otherwise.

    bool UART_available(void)
    


    Wait for transmission complete

    Waits in a while loop until all bytes in the buffer have been transmitted. Can be used before putting the microcontroller to sleep to ensure all data has been transmitted. Baud rate and SYSCLK are used to calculate the time it takes for the last byte to be transmitted after the interrupt is disabled but the last byte is still transmitted.

    void UART_isSending(float sysclk, float baudrate)
    
     

    Parameters

    sysclk

    CPU clock frequency in Hertz.

    baudrate

    UART baudrate used in initialization function.


    Read a byte

    Returns the next received byte or 0 if no new data is available. Should be used only if UART_available() returns true.

    uint8_t UART_read(void)
    


    Read bytes

    Read received bytes into the provided buffer. The function terminates if the specified length has been read, or it times out (around 0.5s).

    uint8_t UART_readBytes(uint8_t* buff, uint8_t length)
    

    Parameters


    uint8_t* buff

    An array buffer where to put incoming data.

    uint8_t length

    Length of the array.

    Return: the number of characters read.

    Usage:

    const uint8_t bufferSizeRX = 20;
    uint8_t buff[bufferSizeRX];
    
    if(UART_available()){
        // Read serial data
        UART_readBytes(buff, bufferSizeRX);
        // Now 'buff' contains received data
    }
    

    Read bytes until

    Read received bytes into the provided buffer. The function terminates if the specified length has been read, the termination character has been found or it times out (around 0.5s). The termination character is not included in the buffer.

    uint8_t UART_readBytesUntil(char character, uint8_t* buff, uint8_t length)
    

    Parameters


    char character

    The termination character. When this character is encountered, the function terminates.

    uint8_t* buff

    An array buffer where to put incoming data.

    uint8_t length

    Length of the array.

    Return: the number of characters read.


    Disable UART

    Disable UART transmitter, receiver and interrupts.

    void UART_end(void)
    

    Flush

    Resets buffers to 0.

    void UART_flush(void)
    

    Redirect received data

    Redirects received data to a user defined function.

    void UART_setRXhandler(void (*rx_func)(uint8_t c))
    

    Usage:

    void rxHandler(uint8_t c){
    	// This function is called inside the RX interrupt
    	// and it should not take long time.
    	// 'c' is the received byte.
    }
    
    UART_setRXhandler(&rxHandler);
    


    Code example

    #include "uart.h"
    #include "delay.h"
     
    int main(void){
        const uint8_t bufferSize = 20;
        char_size_t buff[bufferSize];
        uint8_t bytes_read = 0;
    	
        UART_init(SYSCLK, 115200);
        UART_sendString("I'm UART 0\r");
    	
        UART_sendString("Hi there!\r");
        _delay_ms(2000);
        UART_sendString("Is this thing working?\r");
    
        while(1){
            if(UART_available()){
    	    // Read serial data in the 'buff' array
    	    bytes_read = UART_readBytes(buff, bufferSize);
                UART_sendString("Received "); 
                UART_sendInt(bytes_read);
    	    UART_sendString(" bytes\r");
    			
    	    if(bytes_read == bufferSize){
    	        // Print received data to a serial terminal
    		UART_sendBytes(buff, bytes_read);
    		UART_send('\r');
    	    }
    			
    	} // end if UART_available()
        }
    }
    

    Download

    uart v1.0

    uart Contains uart.h and uart.c
    utils v1.0

    utils Used by sendInt() and sendFloat()
    External Links

    Termite terminal Nice serial terminal
    Changelog
    v1.0 14, March, 2024:
    - released