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:
- Put the SD-card in SD card reader and attach to PC
- Open the SD-card foler and in terminal execute: $ gnome-disk-image-mounter –writable hd20_DOSDEV.img
- You will see new disc mounted and you can write in it the files you download
- Unmount the disc
- Eject the SD card
- 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:
Recent Comments