ESP32-SBC-FabGL How to work with the expander module I2C from FabGL library and apps

ESP32-SBC-FabLG has CH32V003 expander which adds to it GPIO, I2C and SPI functionality.

In this post I will show you how you can work with the I2C from the PC Emulator application and read Nunchuk position and buttons QBASIC and TURBO PASCAL 7.0

You need to install our fork of FabGL library to your arduino and remove other FabGL libraries as they will interference (we have PR to original FabGL but it takes time to be merged), once/if our merge is accepted you will be able to do same with the original FabGL library, but right now this is not possible.

Compile and upload PCEmulator.ino from Examples-FabGL-VGA to ESP32-SBC-FabGL board.

Once the example is programmed and started you have to choose this setup:

you will have to connect to WiFi to may download the disk image for the first time.

Now you have to add the BASIC and TurboPascal code.

Download them then power off the ESP32-SBC-FabGL remove the SD card and add the files to it following this procedure:

  1. Put the SD-card in SD card reader and attach to PC
  2. Open the SD-card foler and in terminal execute: $ gnome-disk-image-mounter –writable hd20_DOSDEV.img
  3. You will see new disc mounted and you can write in it the files you download
  4. Unmount the disc
  5. Eject the SD card
  6. Put it back to ESP32-SBC-FabGL

I2C is configured and used through these ports:

0xF0 – if reads as zero there is no expander, if reads as non zero there is expander. To check the Major and Minor revision of CH32 firmware read 0xFF and 0xFE

0xF4 and 0xF5 – I2C init frequency in kHz. The valid frequencies are between 100 and 400 kHz.

0xF6 – I2C slave address 1-127. This is the address of the module you want to talk with.

0xF7 – I2C slave register address select 0..255

0xF8 – I2C slave register value 0..255

Here is the QBASIC code which read the Nunchuk and MOD-RTC:

REM QBASIC program to control CH32V003 I/O expander inside PC Emulator

DECLARE FUNCTION HexByte$ (i)
DECLARE FUNCTION INT$ (i, l)
DECLARE FUNCTION ch32Available ()
DECLARE FUNCTION ch32VersionMinor ()
DECLARE FUNCTION ch32VersionMajor ()
DECLARE SUB i2cInit (clock)
DECLARE SUB i2cSlave (slave)
DECLARE FUNCTION i2cReadReg (reg)
DECLARE SUB i2cWriteReg (reg, value)

CLS

REM check for I/O available
IF ch32Available = 0 THEN
  PRINT "CH32V003 expander not available on this board!"
  END
END IF

PRINT "CH32V003 expander firmware version "; INT$(ch32VersionMajor, 0); "."; INT$(ch32VersionMinor, 0); " found"

PRINT "Configure I2C clock to 300 KHz"
i2cInit (300)

PRINT "Configure I2C slave Nunchuk  "
CALL i2cSlave(&H52)
CALL i2cWriteReg(&HF0, &H55)

PRINT "Press any key to stop"

LOCATE 10, 1
PRINT "Move the joystick..."
WHILE LEN(INKEY$) = 0
  LOCATE 11, 1
  PRINT "X = "; INT$(i2cReadReg(0), 3)
  LOCATE 11, 10
  PRINT "Y = "; INT$(i2cReadReg(1), 3)
WEND

REM CLS

LOCATE 3, 1
PRINT "Configure I2C slave RTC      "
CALL i2cSlave(&H68)

WHILE LEN(INKEY$) = 0
  LOCATE 10, 1
  CALL i2cWriteReg(&HE, &H3C)
  PRINT "Time          "; HexByte$(i2cReadReg(2)); ":"; HexByte$(i2cReadReg(1)); ":"; HexByte$(i2cReadReg(0));
  LOCATE 11, 1
  PRINT "Temperature   "; INT$(i2cReadReg(17), 0); "."; INT$(i2cReadReg(18) / 256 * 100, 0); CHR$(248); "C    "
WEND

FUNCTION HexByte$ (i)
  HexByte$ = RIGHT$("00" + HEX$(i), 2)
END FUNCTION

FUNCTION INT$ (i, l)
  R$ = LTRIM$(STR$(i))
  IF l <> 0 THEN
    R$ = RIGHT$(STRING$(l, " ") + R$, l)
  END IF
  INT$ = R$
END FUNCTION

FUNCTION ch32Available
  ch32Available = (INP(&HF0) AND 1)
END FUNCTION

FUNCTION ch32VersionMinor
  ch32VersionMinor = INP(&HFE)
END FUNCTION

FUNCTION ch32VersionMajor
  ch32VersionMajor = INP(&HFF)
END FUNCTION

SUB i2cInit (clock)
  REM LSB
  OUT &HF4, (clock MOD 256)
  REM MSB
  OUT &HF5, (clock \ 256)
END SUB

SUB i2cSlave (slave)
  OUT &HF6, slave
END SUB

FUNCTION i2cReadReg (reg)
  OUT &HF7, reg
  i2cReadReg = INP(&HF8)
END FUNCTION

SUB i2cWriteReg (reg, value)
  OUT &HF7, reg
  OUT &HF8, value
END SUB

Here is Turbo Pascal 7.0 code for reading the Nunchuk:

program Nunchuk;
uses CRT;

procedure ch32I2Cinit( clock: integer);
begin
  port[$F4] := clock mod 256;
  port[$F5] := clock div 256;
end;

procedure ch32I2Cslave (slave: integer);
begin
  if slave <= 127 then
    port[$F6] := slave
  else
    begin
      writeln('Slave: ',slave,' address out of range');
      Halt(1);
    end;
end;

function ch32I2CreadReg (reg: integer): integer;
begin
  port[$F7] := reg;
  ch32I2CreadReg := port[$F8];
end;

procedure ch32I2CwriteReg (reg, value: integer);
begin
  port[$F7] := reg;
  port[$F8] := value;
end;


BEGIN
  ClrScr;

  writeln('Configure I2C clock to 300 KHz');
  ch32I2Cinit(300);

  writeln('Configure I2C slave Nunchuk  ');
  ch32I2Cslave($52);
  ch32I2CwriteReg($F0, $55);

  write('Identify Nunckuk: Nunchuk ');
  if (ch32I2Creadreg($FC) <> $A4) or (ch32I2CreadReg($FD) <> $20) then
    begin
    writeln('not found');
    Halt(2);
    end;
  writeln('found');

  writeln;
  writeln('Press any key to stop');

  gotoXY(1,10); writeln('Move the joystick...');
  while ( not KeyPressed) do
    begin
      gotoXY( 1,11); write('X = ',ch32I2CreadReg(0),'   ');
      gotoXY(15,11); write('Y = ',ch32I2CreadReg(1),'   ');
      gotoXY(30,11); write('Buttons: ');
      if (ch32I2CreadReg(5) and 1) = 0 then
        write('Z')
      else
        write(' ');
      if (ch32I2CreadReg(5) and 2) = 0 then
        write('C')
      else
        write(' ');
    end;
END.

Here is the result of the execution:

Python modules for access to GPIO, I2C and SPI to all OLinuXino boards and SOMs on GitHub

python-logo

We made modules which work same way on all our OLinuXino and SOM boards. The sources are on GitHub.

You can address the GPIOs in two ways – as connector pins and as processor ports.

connector.gpio1p5  means connector GPIO1 pin number 5, same signal can be addressed with port.PG0

New A20 Android 4.2.2 image now supports all A20-OLinuXino-MICRO hardware features

Image

We received A20-SDK2.0 from Allwinner few weeks ago and were working to generate image for A20-OLinuXino but our aim was to add support to all hardware features the board offers. The process was pretty slow as the compilation is very heavy and even small change requires hours of waiting the image generation to complete.

Now we are ready, the only two features left unsupported are the SATA and second SD-MMC card on the bottom but we think that we should give it a break for a while or our heads will explode 🙂

Two images are uploaded on Wiki: one for 7″LCD and one for 10″LCD, the good news is that the Android 4.2.2 with SDK2.0 now support higher resolution as previous SDK for ICS 4.0.3 had hardcoded 800×600 max resolution which made 10″LCD and HDMI useless.

The image have:

  • LCD and HDMI support at same time
  • Touchscreen support
  • GPIO support – we prepare Android application demo code which show how you can access and use GPIOs under Android
  • I2C1 and I2C2 support – we prepare Android application demo code which show how you can access and use I2C under Android
  • 100Mbit Ethernet
  • USB-Ethernet AX88772
  • USB WiFi RTL8188
  • microSD
  • Audio Out, Audio In
  • USB-OTG device and host with Low/Full/High speed
  • USB HOST upper and bottom with Low/Full/High speed
  • UART6 and UART7 support on UEXT connectors  – we prepare Android application demo code which show how you can access and use UART6,7 under Android
  • Buttons

Working with iMX233-OLinuXino and MOD-IO2

Image

UEXT connector allow many and different devices to be attached to it.

To may they all work together without collisions I2C protocol is used to address them.

The protocol is like this:

<OLMX> <DEV-ID> <DEV-#> <COMMANDs> <ARGUMENTS>

<OLMX> – this is the unique OLIMEX I2C address which is 0x48 this address is used to talk to all Olimex UEXT modules.

<DEV-ID> – this is the ID of every UEXT module TYPE which is attached to the I2C bus, for instance if we want to talk to MOD-IO2 this ID is 0x02

<DEV-#> – as we can have many MOD-IO2 connected on the I2C but this is the MOD-IO2 address number which we talk to, each MOD-IO2 by default have address 0xA0, this address can be re-programmed to other value so many MOD-IO2 to be connected together.

<COMMANDs> – allow specific command to be sent to the UEXT module like switch relays, read GPIOs, read AINx etc.

Set-relay command is 0x40, Set-new-address command is 0xB0, read AIN0 is 0x10 read AIN7 is 0x17 and so on.

if we use I2CTOOL we can talk easily to MOD-IO2 connected to iMX233-OLinuXino, for instance to switch both relays ON we can do:

$ ./i2c-tool -w 0 0x48 4 0x02 0xA0 0x40 0x03

where -w means I2C write, 0 – this is I2C channel we write to channel 0, 0x48 is OLIMEX I2C address, 4 is number of bytes to follow, 0x02 is MOD-IO2 ID, 0xA0 is default MOD-IO2 address, 0x40 is set-relay command, 0x03 is set both relays

other useful commands are:

1. CHANGE DEVICE ADDRESS, MOD-IO2 have jumper when you connect it the MOD-IO2 address switch from the default 0xA0 to the temporary 0xF0 (to not mess with the other devices on the I2C bus) and you can assign any address to it wih the command:

$ ./i2c-tool -w 0 0x48 4 0x02 0xF0 0xB0 <new-address>

2. SET TRIS REGISTERS
./i2c-tool -w 0 0x48 4 0x02 0xA0 0x01 <data>

3. SET LAT REGISTERS
./i2c-tool -w 0 0x48 4 0x02 0xA0 0x02 <data>

4. GET PORT REGISTER
./i2c-tool -w 0 0x48 3 0x02 0xA0 0x03
./i2c-tool -r 0 0x48 1

5 SET PULLUPS
./i2c-tool -w 0 0x48 4 0x02 0xA0 0x04 <data>

6. GET ANALOG INPUTS
./i2c-tool -w 0 0x48 3 0x02 0xA0 [0x10|0x11|0x12|0x13|0x17]
./i2c-tool -r 0 0x48 2

where 0x10 – analog input 0
0x11 – analog input 1
0x12 – analog input 2
0x13 – analog input 3
0x17 – analog input 7

iMX233-OLinuXino I2C tutorial – using MOD-MAG 3 axes magnetometer

Image

MAG3110 is interesting little device, it’s preciese 3 axis magnetometer which measure the magnetic field in range +- 1000 uT and have sensitivity of 0.1 uT.

MAG3110 is manufactured by Freescale and you can find the datasheets here.

MOD-MAG UEXT module contain MAG3110 and connects directly to all our boards with UEXT connector. MOD-MAG user manual is here.

Magnetometers are widely used by treasure hunters to scan geo magnetic field and make maps. Why? because metals in earth change the earths magnetic field and scanning the magnetic field you can see what is under the surface.

Typical magnetometer maps is like this you can see different magnetic levels colored in different colors.

MOD-MAG.c demo code is available on GitHub .

Before you use it make sure your board is with hardware I2C enabled as I explained in my previous post: https://olimex.wordpress.com/2012/09/25/imx233-olinuxino-i2c-tutorial-using-wii-nunchuk/

Once you download it you can compile and make executable:

$ cc MOD-MAG.c -o mod-mag
$ chmod +x mod-mag

then when you execute it you will see MAG3110 registers:

$ ./mod-mag

MOD-MAG DEMO PROGRAM
Register[0x00]: 0xFF
Register[0x01]: 0x0B
Register[0x02]: 0x59
Register[0x03]: 0xF5
Register[0x04]: 0xDC
Register[0x05]: 0x02
Register[0x06]: 0x85
Register[0x07]: 0xC4
Register[0x08]: 0x02

these 9 registers actually contain X,Y,Z values x2 bytes per axe

by approaching magnet to MOD-MAG you can see how these values are changing, now all you have to do is to scan some surface and find a good way to visualize the captured info 🙂

iMX233-OLinuXino I2C tutorial – using MOD-LCD1x9

Image

MOD-LCD1x9 is UEXT module which could connect to any of our boards with UEXT connector like Arduino, Maple, Pinguino, Energia and of course OLinuXino.

It’s interfaced by I2C and with this code from GitHub https://github.com/OLIMEX/OLINUXINO/tree/master/SOFTWARE/iMX233/I2C/MOD-LCD1x9 you can drive it via iMX233-OLinuXino.

To work with MOD-LCD1x9 you should make sure your iMX233-OLinuXino is setup for hardware I2C as explained in my previous tutorial: https://olimex.wordpress.com/2012/09/25/imx233-olinuxino-i2c-tutorial-using-wii-nunchuk/

Then you need to download the code and compile it:

$ cc main.c -o mod-lcd1x9

then make the compiled code executable:

$ chmod +x mod-lcd1x9

then if you execute this command you will see all segments on as on the picture above

$ ./mod-lcd1x9 -init

this command is necessary to be executed first to may initialize LCD registers properly, then you can display any text on the lcd with the command ./mod-lcd1x9 “text”, for instance:

$ ./mod-lcd1x9 hello

will display on the LCD:

Image

iMX233-OLinuXino I2C tutorial – using WII NUNCHUK

Image

In this post I will show you how you can access I2C devices with iMX233-OLinuXino and how to read WII-NUNCHUCK info.

WII is popular game console, the NUNCHUCK accessory contain two buttons, accelerometer and joystick combo, as it’s mass produced the price is incredible low. You can read more about it at Wikipedia http://en.wikipedia.org/wiki/Wii_Remote

Olimex offers MOD-WII-UEXT-NUNCHUCK which contains WII-NUNCHUCK coupled to UEXT connector, so you can directly connect it to any of our boards with UEXT connector like our Arduino, Pinguino, Maple, Energia etc boards and of course iMX233/A13-OLinuXino.

Before you start working with I2C you have to check if your iMX233-OLinuXino board is with UEXT connected to the hardware I2C ports.

Why? When we designed the iMX233 we wanted to keep the LCD port complete and the hardware I2C was multiplexed with the LCD ports.
So we put triple jumper on UEXT I2C signals which cold be soldered to software and hardware I2C ports. By default we made them to the software I2C.

Later we found that software defined I2C is bad idea on RTOS as on heavy load I2C may not timing correctly and that it’s recommended to use just the hardware I2C so from the beginning of September we soart producing iMX233-OLinuXino with jumpers wired to the hardware I2C.

As there are still many iMX233 on stock at our distributors we described in the user manual how one could do this himself.

So to work with the code below you should make sure your iMX233-OLinuXino have wired hardware I2C to UEXT.

Download the code from GitHub https://github.com/OLIMEX/OLINUXINO/blob/master/SOFTWARE/iMX233/I2C/MOD-Wii-UEXT-NUNCHUCK.c

and write it to the SD card by SSH or flash dongle.

then you need to compile it

$ cc MOD-Wii-UEXT-NUNCHUCK.c -o wii

$ chmod +x wii

$ ./wii

now on the console connected to terminal you should see picture like this:

Image

when you move the joystick, push the buttons or shake the Nunchuck you can see these numbers change.

Here is video of iMX233-OLinuXino running above code: http://www.youtube.com/watch?v=pSVG3LF7uqA