Close

IO Expander from MBASIC

A project log for z80ctrl

AVR-based bootloader and IO card for RC2014 retrocomputer

jb-langstonJ.B. Langston 12/15/2018 at 21:172 Comments

I've recently pushed an update to the z80ctrl repo which makes my new IO expander board accessible to the Z80. 

To access these features, you'll need to pull the latest code from the Github repo, and then uncomment the IOX_BASE variables in the Makefile. After doing so, run 'make clean' and then 'make install' to rebuild and flash the new code.  You can change the IOX_BASE if desired, but you must modify any code that will access the ports accordingly.  

The board is exposed to the Z80 on 3 consecutive ports starting from IOX_BASE:

Here is a simple MBASIC program to flash an LED on the first GPIO port 10 times:

10 OUT 0, 1: REM select chip address 1
20 OUT 1, 0: REM select register IODIRA0 (0x00)
30 OUT 2, 0: REM set register value to 0 (all pins outputs)
40 OUT 1, &H12: REM select register GPIOA0 (0x12)
50 FOR I = 1 TO 10
60 OUT 2, 0: REM turn all pins on GPIOA off
70 FOR J = 1 TO 1000:NEXT
80 OUT 2, &HFF: REM turn all pins on GPIOA on
90 FOR J = 1 TO 1000:NEXT
100 NEXT

First, we select the IO direction register on the IO expander configured at address 1, and set all pins to outputs. Then we select the GPIO register.  Within a loop, we toggle all of the pins on and then off, pausing between each transition.

Here is an MBASIC program demonstrating how to read the time from the RTC:

10 REM CONVERT VALUES FROM BCD
20 DEF FNBCD(V)=(V AND &HF0)/16*10+(V AND &HF)
30 OUT 0,0: REM SELECT RTC CHIP
40 REM READ DATE/TIME FROM RTC REGISTERS
50 OUT 1,6: YR=FNBCD(INP(2))+2000
60 OUT 1,5: MO=FNBCD(INP(2))
70 OUT 1,4: DY=FNBCD(INP(2))
80 OUT 1,2: HR=INP(2)
90 OUT 1,1: MI=FNBCD(INP(2))
100 OUT 1,0: S=FNBCD(INP(2))
110 REM HANDLE AM/PM
120 AMPM$=""
130 IF (HR AND &H40)=0 THEN 160: REM SKIP IF 24-HR FORMAT
140 IF HR AND &H20 THEN AMPM$="PM" ELSE AMPM$="AM"
150 HR=HR AND &H1F: REM GET RID OF AM/PM AND 12-HR BITS
160 HR=FNBCD(HR)
170 PRINT USING "The time is ##:##:##& on ##/##/####"; HR, MI, S, AMPM$, MO, DY, YR

First, we select the RTC device, then read the year, month, day, hour, minute, and second from the corresponding register on the chip.  Next, we check to see if the 12 hour bit is set. If so, we check whether the time is currently AM or PM and then mask off those bits.  Now, we convert all the values from BCD (as they are returned by the RTC) into binary so that BASIC can print them properly.  Finally, we output the date and time in a standardized format. 

Discussions

villaromba wrote 12/31/2018 at 13:26 point

JB: I see you've added some interesting projects to the IO, viz LCD and LCD Clock.  What type of LCD are you using and do you have a simple hook up table and or schematic.

Thanks Colin

  Are you sure? yes | no

J.B. Langston wrote 12/31/2018 at 14:26 point

I will write up another blog article, but in case you want to get started sooner, I'm using this LCD: https://www.amazon.com/gp/product/B00GZ6GK7A. Almost every character LCD you can find will also use a standard interface, called HD44780 (datasheet: https://www.sparkfun.com/datasheets/LCD/HD44780.pdf).  

Pins 0-3 on the GPIO A connector are connected to DB4-7 on the LCD, and pins 4, 5, and 6 are connected to RS, R/W, and E on the LCD, respectively. Separate power hookups are needed for LCD and backlight, and you will need a 10K pot to supply a variable voltage to adjust the contrast.  There is a complete pinout for the LCD in one of the photo on Amazon.

  Are you sure? yes | no