Please check what I have got done.
TC
Posts: 1,019
Hello all, I am wondering if someone would be willing to take a look at my code, and tell me if there is something obvious that will not work? I am not done with it yet, nor have I tested it. I am trying to learn, but I also dont want to get too far and find out there is an obvious bug that I cannot see since I do not have that much experience.
Any feedback would be appreciated.
I have included the datasheet of what I am working on.
Thank You
Any feedback would be appreciated.
I have included the datasheet of what I am working on.
Thank You
{ Controling the MAX6957 requires sending a 16-bit word. The first byte, D15 through D8, is the command address, and the second byte, D7 through D0, is the data byte.} { " |=|<(bit) " sets bit " &=!|<(bit) " Clears bit } CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 ON = 1 OFF = 0 GLOBAL = 0 INDIVIDUAL = 1 read = 1 write = 0 { === PINS === } SCLK = 2 DIN = 1 CS = 0 DOUT = 4 { === Port Configuration ===} LED_ = $00 {"OUTPUT" LED Segment Driver} OUTPUT_ = $01 {"OUTPUT" GPIO Output} IN_WO = $10 {"INPUT" GPIO Input Without Pullup} IN_W = $11 {"INPUT" GPIO Input With Pullup} VAR byte Config_data {Configuration Register data.| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |         Transition Detection Control 0=Disabled, 1=Enabled ─┘ │ │ │ │ │ │ │ Global Current Control 0=Global, 1=Individual Segmants ──────┘ │ │ │ │ │ │ Don't care bit ───────────┘ │ │ │ │ │ Don't care bit ────────────────┘ │ │ │ │ Don't care bit ─────────────────────┘ │ │ │ Don't care bit ──────────────────────────┘ │ │ Don't care bit ───────────────────────────────┘ │ Shutdown Control 0=Shutdown, 1= Normal Operation ────────────────────────────────────┘ } byte IO_counter {Input/Output counter. used to keep track of what IO port is being configured} OBJ SPI : "SPI_Asm" PUB _TRANSITION (ON_OFF) if ON_OFF := ON Config_data|=|<7 else Config_data&=!|<7 _CONFIG PUB _CURRENT (GLOBAL_INDIVIDUAL) if GLOBAL_INDIVIDUAL := INDIVIDUAL Config_data|=|<6 else Config_data&=!|<6 _CONFIG PUB _SHUTDOWN (ON_OFF) if ON_OFF := ON Config_data|=|<0 else Config_data&=!|<0 _CONFIG PRI _CONFIG GPIO_write ($04, Config_data) PUB one_PORT (port, read_write, data) : Data_byte if read_write == read Data_byte := GPIO_read (port + $20) if read_write == write GPIO_write (port + 20, data) PUB four_PORT (read_write, data) : Data_byte if read_write == read Data_byte := GPIO_read ($40) if read_write == write GPIO_write ($40, data) PUB five_PORT (read_write, data) : Data_byte if read_write == read Data_byte := GPIO_read ($41) if read_write == write GPIO_write ($41, data) PUB six_PORT (read_write, data) : Data_byte if read_write == read Data_byte := GPIO_read ($42) if read_write == write GPIO_write ($42, data) PUB seven_PORT (read_write, data) : Data_byte if read_write == read Data_byte := GPIO_read ($43) if read_write == write GPIO_write ($43, data) PUB eight_PORT (port, read_write, data) : Data_byte if read_write == read Data_byte := GPIO_read (port + $40) if read_write == write GPIO_write (port + $40, data) PUB DISPLAY_TEST | TEST_VALUE { Display test mode turns on all ports configured as LED drivers by overriding, but not altering, all controls and port registers, except the port configuration register} { Every time "DISPLAY_TEST" is called, the display register will be inverted. } { Read the value on "test register" ($07)} TEST_VALUE := GPIO_read($07) { Invert the value from "test register", and load it back} GPIO_write($07, !TEST_VALUE) PUB GLOBAL_CURRENT (Adj) { Global current register, sets the current for all ports configured as LED segment drivers} { there are only 16-steps (4-bits) of current control} GPIO_write($02, Adj) PUB PORT_CONFIG (IO_D, IO_C, IO_B, IO_A) { The port configuration registers set the 28 ports, P4 to P31, individually as either LED drivers or GPIO. A pair of bits in registers 0x09 through 0x0F sets each port's configuration.} { To set a port's configuration, call "PORT_CONFIG" with corisponding port's configuration value. 4 port's must be configurated at A time. port's are ordered from highest to lowest, P7-P4, P11-P8, P15-P12, P19-P16, P23-P20, P27-P24, P31-P28. Ports P3-P0 are internal and cannot be used, or configured. The 36-pin version of the MAX6957 has 28 usable ports The 28-pin version of the MAX6957 has 20 usable ports Any ports NOT being used should be set to outputs, if this is not done the unused ports remain as floating inputs.} IF IO_counter < $09 { Is this the first time method is called?} IO_counter := $09 { set counter to first port configuration batch} { send port cofiguration address, and data} GPIO_write(IO_counter, IO_D<<6 | IO_C<<4 | IO_B<<2 | IO_A) { increment port configuration address} IO_counter += 1 PUB GPIO_write (Command_byte, Data_byte) { The MAX6957 contains a 16-bit shift register into which DIN data are clocked on the rising edge of SCLK, when CS is low. When CS is high, transitions on SCLK have no effect. When CS goes high, the 16 bits in the Shift register are parallel loaded into a 16-bit latch. The 16 bits in the latch are then decoded and executed. The MAX6957 is written to using the following sequence:} { 1) Take SCLK low } LOW(SCLK) { 2) Take CS low. This enables the internal 16-bit shift register. } LOW(CS) { 3) Clock 16 bits of data into DIN-D15 first, D0 last-observing the setup and hold times(bit D15 is low, indicating a write command). } SPI.start(1,0) SPI.SHIFTOUT (DIN, SCLK, SPI#MSBFIRST, 8, Command_Byte&=!|<7) { "&=!|<" sets bit 7 to 0 } SPI.SHIFTOUT (DIN, SCLK, SPI#MSBFIRST, 8, Data_byte) { 4) Take CS high (either while SCLK is still high after clocking in the last data bit, or after taking SCLK low). } HIGH(CS) SPI.stop { 5) Take SCLK low (if not alredy low).} LOW(SCLK) PUB GPIO_read (Command_byte): Data_byte { Any register data within the MAX6957 may be read by sending a logic high to bit D15. The sequence is:} { 1) Take SCLK low.} LOW(SCLK) { 2) Take CS low (this enables the internal 16-bit shift register).} LOW(CS) { 3) clock 16 bits of data into DIN-D15 first to D0 last. D15 is high, indicating a read command and bits D14 through D8 containing the address of the register to be read. Bits D&-D0 contain dummy data, which is discarded.} SPI.start(1,0) SPI.SHIFTOUT (DIN, SCLK, SPI#MSBFIRST, 8, Command_Byte|=|<7) { "|=|<" sets bit 7 to 1} SPI.SHIFTOUT (DIN, SCLK, SPI#MSBFIRST, 8, $00) { 4) Take CS high (either while SCLK is still high after clocking in the last data bit, or after taking SCLK low), positions D7 though D0 in the Shift register are now loaded with the register data addressed by bits D1 through D8.} HIGH(CS) { 5) Take SCLK low (if not already low).} LOW(SCLK) { 6) issue another read or write command (which can be a No-Op), and examine the bit stream at Dout; the second 8 bits are the contents of the register addressed by bits D1 through D8 in step 3.} LOW(CS) Data_byte := SPI.SHIFTIN (DOUT, SCLK, SPI#MSBPOST, 16) HIGH(CS) SPI.stop LOW(SCLK) PUB HIGH(Pin) dira[Pin]~~ outa[Pin]~~ PUB LOW(Pin) dira[Pin]~~ outa[Pin]~
pdf
532K
Comments
It could make a noticeable difference in speed but I wouldn't worry about it for now, if the way you're currently doing it, makes more sense to you than the way I suggested. Once you have your program running you can decide if you want to optimize it or not.
An alternative way of writing the _PORT methods (read == 1, write == 0):
Thank You. I will change it at a later time, but for right now I am going to leave it.
four_PORT, five_PORT, six_PORT, and seven_PORT are only for the 36-pin SSOP, and the 40-pin TQFN packages. They are there so more than 1 port, and less than 8 ports at a time can be controled. For the "20" in one_PORT, I seen that after I uploaded the file. Thank you for the code suggestion, it does make better sense.
I added comments with the methods. I do plan on making it more condensed; just right now I just wanted to get my mind back to using spin. The object works, I tried it out last night. Now to figure out what am I going to do with it. I don’t want to stop while I’m ahead.