Shop OBEX P1 Docs P2 Docs Learn Events
I2C test code for MCP23017 16-Bit I/O Expander in FemtoBasic — Parallax Forums

I2C test code for MCP23017 16-Bit I/O Expander in FemtoBasic

Duane C. JohnsonDuane C. Johnson Posts: 955
edited 2011-03-15 12:25 in Propeller 1
I'm experimenting with I2C and tried it out on an MCP23017.
I wrote this program to see how it worked.
I found the sequence of commands is very complicated"
Especially with Sequenced and Non-Sequenced reads and writes.
This program loads setup bytes into the registers using sequenced writes.
Then changes to non-sequenced mode for reading and writing.

Have fun!
Duane
1    PRINT "MCP23017 16-Bit I/O Expander with I2C Serial Interface"
2    PRINT "PIN[17..16] SDA, SCL"
3    PRINT "Duane C. Johnson  2011/03/15"
4    PRINT "Red Rock Energy"
5    PRINT "SCL on PIN[17}  SDL on PIN[16]"
49   PRINT ""
50   REM A = I2C Address
51   REM B = Device Opcode
52   REM C = Register Address
53   REM D = R/W
54   REM V = VALUE
55   REM W = VALUE
56   REM E = IO BIT
57   REM T = FOR NEXT
58   REM F,G,X = SCRATCH
69   REM Z = TEST FLAG
70   REM Unused Variables HIJKLMNOPQRSUY
80   B=$20:A=0:X=INA[17]:X=INA[16]:Z=0
90   GOSUB 1000 : REM RESET
92   GOSUB 1200 : REM INIT CHIP O
94   GOSUB 1400 : REM INIT CHIP 1
100  REM
300  REM OUTPUT 1 BYTE AT A TIME NON-SEQUENTIAL
310  B=$20
320  INPUT "Reg 0-21, Chip 0-1, R/w 1/0 ? "; C,A,D
330  IF D=1 THEN GOTO 370
340  PRINT "        WRITE REGISTER ";C;" ";A;" ? ";:INPUT V
350  REM WRITE
351                 GOSUB 2160 :REM START   BIT
352  B=B:A=A:D=0   :GOSUB 2200 :REM OUTPUT  CONTROL BYTE
353  C=C           :GOSUB 2300 :REM OUTPUT  REGISTER ADDRESS
354  C=V           :GOSUB 2300 :REM OUTPUT  DATA BYTE
358                 GOSUB 2140 :REM STOP    BIT
369  GOTO 300
370  REM READ
371                 GOSUB 2160 :REM START   BIT
372  B=B:A=A:D=0   :GOSUB 2200 :REM OUTPUT  CONTROL BYTE
373  C=C           :GOSUB 2300 :REM OUTPUT  REGISTER ADDRESS
374                 GOSUB 2150 :REM RESTART BIT
375  B=B:A=A:D=1   :GOSUB 2200 :REM OUTPUT  CONTROL BYTE
376                 GOSUB 2400 :REM
377  V=G:PRINT "        READ  REGISTER ";C;" ";A;" = ";V :REM INPUT   DATA BYTE
378                 GOSUB 2140 :REM STOP    BIT
379  GOTO 300

390 RETURN

820  GOTO   100
910  END
1000 REM INITILIZATION
1110 OUTA[15]=0:X=INA[15]:PAUSE 500
1190 RETURN
1200 REM SETUP CONTROLL REGISTERS USING SEQUENTIAL MODE
1210               GOSUB 2160 :REM START   BIT
1220 B=$20:A=0:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1230       C=$00 : GOSUB 2300 :REM OUTPUT  REGISTER ADDRESS
1240               GOSUB 2150 :REM RESTART BIT
1310 B=$20:A=0:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1320       C=$FF : GOSUB 2300 :REM OUTPUT  IODIRA   0
1321       C=$FF : GOSUB 2300 :REM OUTPUT  IODIRB   1
1322       C=$00 : GOSUB 2300 :REM OUTPUT  IPOLA    2
1323       C=$00 : GOSUB 2300 :REM OUTPUT  IPOLB    3
1324       C=$00 : GOSUB 2300 :REM OUTPUT  GPINTENA 4
1325       C=$00 : GOSUB 2300 :REM OUTPUT  GPINTENB 5
1326       C=$00 : GOSUB 2300 :REM OUTPUT  DEFVALA  6
1327       C=$00 : GOSUB 2300 :REM OUTPUT  DEFVALB  7
1330       C=$00 : GOSUB 2300 :REM OUTPUT  INTCONA  8
1331       C=$00 : GOSUB 2300 :REM OUTPUT  INTCONB  9
1332       C=$00 : GOSUB 2300 :REM OUTPUT  IOCON   10
1333       C=$00 : GOSUB 2300 :REM OUTPUT  IOCON   11
1334       C=$00 : GOSUB 2300 :REM OUTPUT  GPPUA   12
1335       C=$00 : GOSUB 2300 :REM OUTPUT  GPPUB   13
1336       C=$00 : GOSUB 2300 :REM OUTPUT  INTFA   14
1337       C=$00 : GOSUB 2300 :REM OUTPUT  INTFB   15
1340       C=$00 : GOSUB 2300 :REM OUTPUT  NTCAPA  16
1341       C=$00 : GOSUB 2300 :REM OUTPUT  NTCAPB  17
1342       C=$FF : GOSUB 2300 :REM OUTPUT  GPIOA   18
1343       C=$FF : GOSUB 2300 :REM OUTPUT  GPIOB   19
1344       C=$FF : GOSUB 2300 :REM OUTPUT  OLATA   20
1345       C=$FF : GOSUB 2300 :REM OUTPUT  OLATB   21
1350               GOSUB 2140 :REM STOP    BIT

1360 REM FORCE NON-SEQUENTIAL MODE
1361               GOSUB 2160 :REM START   BIT
1362 B=$20:A=0:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1363       C=10  : GOSUB 2300 :REM OUTPUT  REGISTER ADDRESS
1364               GOSUB 2150 :REM RESTART BIT
1365 B=$20:A=0:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1366       C=$20 : GOSUB 2300 :REM OUTPUT  IOCON   10
1367               GOSUB 2140 :REM STOP    BIT
1371               GOSUB 2160 :REM START   BIT
1372 B=$20:A=0:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1373       C=11  : GOSUB 2300 :REM OUTPUT  REGISTER ADDRESS
1374               GOSUB 2150 :REM RESTART BIT
1375 B=$20:A=0:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1376       C=$20 : GOSUB 2300 :REM OUTPUT  IOCON   11
1377               GOSUB 2140 :REM STOP    BIT

1390 RETURN

1400 REM SETUP CONTROLL REGISTERS USING SEQUENTIAL MODE
1410               GOSUB 2160 :REM START   BIT
1420 B=$20:A=1:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1430       C=$00 : GOSUB 2300 :REM OUTPUT  REGISTER ADDRESS
1440               GOSUB 2150 :REM RESTART BIT
1510 B=$20:A=1:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE

1520       C=$FF : GOSUB 2300 :REM OUTPUT  IODIRA   0
1521       C=$FF : GOSUB 2300 :REM OUTPUT  IODIRB   1
1522       C=$00 : GOSUB 2300 :REM OUTPUT  IPOLA    2
1523       C=$00 : GOSUB 2300 :REM OUTPUT  IPOLB    3
1524       C=$00 : GOSUB 2300 :REM OUTPUT  GPINTENA 4
1525       C=$00 : GOSUB 2300 :REM OUTPUT  GPINTENB 5
1526       C=$00 : GOSUB 2300 :REM OUTPUT  DEFVALA  6
1527       C=$00 : GOSUB 2300 :REM OUTPUT  DEFVALB  7
1530       C=$00 : GOSUB 2300 :REM OUTPUT  INTCONA  8
1531       C=$00 : GOSUB 2300 :REM OUTPUT  INTCONB  9
1532       C=$00 : GOSUB 2300 :REM OUTPUT  IOCON   10
1533       C=$00 : GOSUB 2300 :REM OUTPUT  IOCON   11
1534       C=$00 : GOSUB 2300 :REM OUTPUT  GPPUA   12
1535       C=$00 : GOSUB 2300 :REM OUTPUT  GPPUB   13
1536       C=$00 : GOSUB 2300 :REM OUTPUT  INTFA   14
1537       C=$00 : GOSUB 2300 :REM OUTPUT  INTFB   15
1540       C=$00 : GOSUB 2300 :REM OUTPUT  NTCAPA  16
1541       C=$00 : GOSUB 2300 :REM OUTPUT  NTCAPB  17
1542       C=$FF : GOSUB 2300 :REM OUTPUT  GPIOA   18
1543       C=$FF : GOSUB 2300 :REM OUTPUT  GPIOB   19
1544       C=$FF : GOSUB 2300 :REM OUTPUT  OLATA   20
1545       C=$FF : GOSUB 2300 :REM OUTPUT  OLATB   21
1550               GOSUB 2140 :REM STOP    BIT

1560 REM FORCE NON-SEQUENTIAL MODE
1561               GOSUB 2160 :REM START   BIT
1562 B=$20:A=1:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1563       C=10  : GOSUB 2300 :REM OUTPUT  REGISTER ADDRESS
1564               GOSUB 2150 :REM RESTART BIT
1565 B=$20:A=1:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1566       C=$20 : GOSUB 2300 :REM OUTPUT  IOCON   10
1567               GOSUB 2140 :REM STOP    BIT
1571               GOSUB 2160 :REM START   BIT
1572 B=$20:A=1:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1573       C=11  : GOSUB 2300 :REM OUTPUT  REGISTER ADDRESS
1574               GOSUB 2150 :REM RESTART BIT
1575 B=$20:A=1:D=0:GOSUB 2200 :REM OUTPUT  CONTROL BYTE
1576       C=$20 : GOSUB 2300 :REM OUTPUT  IOCON   11
1577               GOSUB 2140 :REM STOP    BIT

1590 RETURN

1910 RETURN
2000 REM I2C DRIVERS

2100 OUTA[17]=0:IF INA[16]=0 THEN GOTO 2100:REM CHECK FOR CLOCK STRETCHING           
2101 OUTA[16]=0                     :RETURN:REM OUT 0 BIT

2110 X=INA[17] :IF INA[16]=0 THEN GOTO 2110:REM CHECK FOR CLOCK STRETCHING           
2111 OUTA[16]=0                     :RETURN:REM OUT 1 BIT

2120 X=INA[17] :IF INA[16]=0 THEN GOTO 2120:REM CHECK FOR CLOCK STRETCHING
2121 E=INA[17] :OUTA[16]=0          :RETURN:REM INPUT BIT

2130 X=INA[17] :IF INA[16]=0 THEN GOTO 2130:REM CHECK FOR CLOCK STRETCHING
2131 E=INA[17] :OUTA[16]=0:RETURN : REM INPUT ACK

2140 OUTA[17]=0:OUTA[16]=0      :REM MAKE BOTH LOW 
2141 IF INA[16]=0 THEN GOTO 2141:REM CHECK FOR CLOCK STRETCHING
2142 IF INA[17]=0 THEN GOTO 2142:REM WAIT FOR DATA TO GO HIGH                                :RETURN :REM STOP  BIT
2143                                 RETURN:REM STOP BIT

2150 OUTA[17]=0:OUTA[16]=0                 :REM MAKE BOTH LOW 
2151 IF INA[16]=0 THEN GOTO 2151:REM CHECK FOR CLOCK STRETCHING
2152 IF INA[17]=0 THEN GOTO 2152:REM WAIT FOR DATA TO GO HIGH                                :RETURN :REM STOP  BIT
2153 OUTA[16]=0                            :REM FORCE CLOCK LOW
2154 IF INA[16]=0 THEN GOTO 2154           :REM WAIT FOR CLOCK TO BE HIGH
2155 OUTA[17]=0:OUTA[16]=0          :RETURN:REM RESTART BIT

2150 OUTA[16]=0:OUTA[17]=0                 :REM MAKE BOTH LOW 
2151 IF INA[16]=0 THEN GOTO 2151:REM CHECK FOR CLOCK STRETCHING
2152 IF INA[17]=0 THEN GOTO 2152:REM WAIT FOR DATA TO GO HIGH                                :RETURN :REM STOP  BIT
2153 OUTA[16]=0                            :REM FORCE CLOCK LOW
2154 IF INA[16]=0 THEN GOTO 2154           :REM WAIT FOR CLOCK TO BE HIGH
2155 OUTA[17]=0:OUTA[16]=0          :RETURN:REM RESTART BIT

2160 IF INA[17]=0 THEN GOTO 2160:REM WAIT FOR DATA  TO BE HIGH
2161 IF INA[16]=0 THEN GOTO 2161:REM WAIT FOR CLOCK TO BE HIGH
2162 OUTA[17]=0:OUTA[16]=0          :RETURN:REM START BIT

2200 REM OUTPUT CONTROL BYTE
2210 G =((B+A) SHL 1 + D) REV 8
2211 IF Z=1 THEN PRINT "2200 ";((B+A) SHL 1 + D),
2220 FOR T = 0 TO 7
2221   IF Z=1 THEN PRINT G & 1;
2225   IF G & 1 = 0 THEN GOSUB 2100
2230   IF G & 1 = 1 THEN GOSUB 2110
2235   G = G SHR 1
2240 NEXT T
2245 GOSUB 2130 : REM TEST ACK
2250 IF H = 1 THEN Z=1:DISPLAY 7:IF Z=1 THEN PRINT " NACK ";:REM IO ERROR
2251 IF Z=1 THEN PRINT ""
2255 RETURN

2300 REM OUTPUT REGISTER ADDRESS, OR BYTE
2310 G = C REV 8
2311 IF Z=1 THEN PRINT "2300 ";C,
2320 FOR T = 0 TO 7
2321   IF Z=1 THEN PRINT G & 1;
2325   IF G & 1 = 0 THEN GOSUB 2100:REM OUT 0 BIT
2330   IF G & 1 = 1 THEN GOSUB 2110:REM OUT 1 BIT
2335   G = G SHR 1
2340 NEXT T
2345 GOSUB 2130 : REM TEST ACK
2350 IF E = 1 THEN Z=1:DISPLAY 7:IF Z=1 THEN PRINT " NACK ";:REM IO ERROR
2351 IF Z=1 THEN PRINT ""
2355 RETURN

2400 REM INPUT DATA BYTE
2410 G = 0
2411 IF Z=1 THEN PRINT "2400 ";
2420 FOR T = 0 TO 7
2425   GOSUB 2120
2430   G = (G SHL 1) + E
2431   IF Z=1 THEN PRINT G & 1;
2440 NEXT T
2445 GOSUB 2130 : REM TEST ACK
2450 IF H = 1 THEN Z=1:DISPLAY 7:IF Z=1 THEN PRINT " NACK ";:REM IO ERROR
2451 IF Z=1 THEN PRINT ""
2455 RETURN

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2011-03-15 12:01
    It's way much easier to write support code for the MCP23017 in Spin and add that to the Basic interpreter, particularly since there's already I2C support internally. Look at BoeBotBasic which uses a PCA9554 I2C I/O Expander to handle the HM55B compass.

    Still, it is impressive how much can be done with FemtoBasic as it stands. Good work.
  • Heater.Heater. Posts: 21,230
    edited 2011-03-15 12:25
    Wow, impressive.

    I haven't seen code like that since 1975:-)
Sign In or Register to comment.