Difference between revisions of "TLC59711"
From Steak Wiki
Jump to navigationJump to search (Created page with "The TLC59711 by Texas Instruments is a 16 bit 12 channel LED driver. It has a 224 bit stream required for each chip. The stream has 32 bits of configuration data (config + 21...") |
|||
Line 31: | Line 31: | ||
Example Code: | Example Code: | ||
+ | <pre> | ||
+ | // DEVCFG3 | ||
+ | // USERID = No Setting | ||
+ | #pragma config FMIIEN = OFF // Ethernet RMII/MII Enable (MII Enabled) | ||
+ | #pragma config FETHIO = OFF // Ethernet I/O Pin Select (Default Ethernet I/O) | ||
+ | #pragma config PGL1WAY = OFF // Permission Group Lock One Way Configuration (Allow only one reconfiguration) | ||
+ | #pragma config PMDL1WAY = ON // Peripheral Module Disable Configuration (Allow only one reconfiguration) | ||
+ | #pragma config IOL1WAY = ON // Peripheral Pin Select Configuration (Allow only one reconfiguration) | ||
+ | #pragma config FUSBIDIO = OFF // USB USBID Selection (Controlled by the USB Module) | ||
+ | #pragma config POSCMOD = HS | ||
+ | #pragma config FNOSC = SPLL | ||
+ | #pragma config FPLLICLK= PLL_POSC | ||
+ | #pragma config FPLLIDIV= DIV_2 // 6MHz | ||
+ | #pragma config FPLLRNG = RANGE_5_10_MHZ | ||
+ | #pragma config FPLLMULT= MUL_66 // 396MHz | ||
+ | #pragma config FPLLODIV= DIV_2 // 198MHz | ||
+ | #define SYSFREQ (198000000L) | ||
+ | #pragma config UPLLFSEL = FREQ_24MHZ // USB PLL Input Frequency Selection (USB PLL input is 24 MHz) | ||
+ | #pragma config UPLLEN = OFF | ||
+ | #pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value) | ||
+ | #pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576) | ||
+ | #pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming) | ||
+ | #pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode) | ||
+ | #pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Enabled) | ||
+ | #pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%) | ||
+ | #pragma config DMTCNT = DMT31 // Deadman Timer Count Selection (2^31 (2147483648)) | ||
+ | #pragma config FDMTEN = OFF // Deadman Timer Enable (Deadman Timer is enabled) | ||
+ | // DEVCFG0 | ||
+ | #pragma config DEBUG = OFF // Background Debugger Enable (Debugger is disabled) | ||
+ | #pragma config JTAGEN = OFF // JTAG Enable (JTAG Port Enabled) | ||
+ | #pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2) | ||
+ | #pragma config TRCEN = OFF // Trace Enable (Trace features in the CPU are enabled) | ||
+ | #pragma config BOOTISA = MIPS32 // Boot ISA Selection (Boot code and Exception code is MIPS32) | ||
+ | #pragma config FECCCON = OFF_UNLOCKED // Dynamic Flash ECC Configuration (ECC and Dynamic ECC are disabled (ECCCON bits are writable)) | ||
+ | #pragma config FSLEEP = OFF // Flash Sleep Mode (Flash is powered down when the device is in Sleep mode) | ||
+ | #pragma config DBGPER = PG_ALL // Debug Mode CPU Access Permission (Allow CPU access to all permission regions) | ||
+ | #pragma config EJTAGBEN = NORMAL // EJTAG Boot (Normal EJTAG functionality) | ||
+ | // DEVCP0 | ||
+ | #pragma config CP = OFF // Code Protect (Protection Disabled) | ||
+ | |||
+ | //TLC5971 | ||
+ | //0x25 b100101 | ||
+ | //0x16 b10110 | ||
+ | //17 x 3 bits high (brightness) | ||
+ | //16 x 3 bits colour | ||
+ | unsigned char __attribute__((coherent))testTI[28] = {0b10010110, //25, then half of 16 | ||
+ | 0b11011111, //some of 16 (3 bits), and start of brightness (5 bits for brightness) | ||
+ | 0xFF,0xFF,//end brightness | ||
+ | //for color, 16 bits each | ||
+ | 0,0,0,0,0,0,0,0, //color data for 12 channels | ||
+ | 0,0,0,0,0,0,0,0, // | ||
+ | 0,0,0,0,0,0,0xFF,0xFF};// channels 0 are here | ||
+ | //224 / 8 == 28. 4 bytes for config/brightness. 24 bytes for colour. | ||
+ | |||
+ | unsigned char __attribute__((coherent))testTI2[28] = {0b10010110, | ||
+ | 0b11011111, | ||
+ | 0xFF,0xFF, | ||
+ | 0,0,0,0,0,0,0,0, | ||
+ | 0,0,0,0,0,0,0,0, | ||
+ | 0,0,0xFF,0xFF,0,0,0,0}; | ||
+ | |||
+ | |||
+ | void configurePorts (void){ | ||
+ | AD1CON1 = 0; // disable ADC | ||
+ | |||
+ | //SPI Ports | ||
+ | //UEXT / RD15 SCK6, AN33, RPD15, RD15 | ||
+ | SPI6CONCLR = _SPI6CON_ON_MASK; | ||
+ | ANSELD = 0; | ||
+ | ANSELDCLR = _ANSELD_ANSD15_MASK; | ||
+ | TRISDbits.TRISD15 = 0; //output | ||
+ | RPD15Rbits.RPD15R = 0b0101; //assign SDO1 to RPD15 | ||
+ | //RPD15R; SPI6CON | ||
+ | } | ||
+ | void configureSPI(void){ | ||
+ | |||
+ | IEC3bits.SPI1EIE = 0; //disable interrupts | ||
+ | IEC3bits.SPI1RXIE = 0; | ||
+ | IEC3bits.SPI1TXIE = 0; | ||
+ | IEC3bits.SPI1EIE = 0; //enable general error flag (all three get flagged, in practice) | ||
+ | IEC3bits.SPI1RXIE = 0; | ||
+ | |||
+ | //SPI Priority for Interrupts | ||
+ | IPC27bits.SPI1TXIP = 6; //priority | ||
+ | IPC27bits.SPI1TXIS = 2; | ||
+ | IPC27bits.SPI1RXIP = 7; //priority | ||
+ | IPC27bits.SPI1RXIS = 3; | ||
+ | |||
+ | rData = SPI1BUF; | ||
+ | |||
+ | //enable SPI | ||
+ | SPI1CONbits.ON = 0; //stop & reset module | ||
+ | SPI1BUF = 0; //clear buffer (rx/tx) | ||
+ | |||
+ | SPI1STATbits.SPIROV = 0; //clear rx overflow | ||
+ | SPI1CONbits.MSTEN = 1; //master (not slave mode) | ||
+ | SPI1CONbits.ON = 1; //enable SPI | ||
+ | |||
+ | //Adafruit website (see led docs) remarks spi mode 3 needed so... | ||
+ | SPI1CONbits.CKP = 1; | ||
+ | SPI1CONbits.SMP = 1;//sample phase (clock "phase" to sample) | ||
+ | SPI1CONbits.CKE = 0; | ||
+ | //REQUIRED | ||
+ | |||
+ | } | ||
+ | //non dma spi | ||
+ | void SPITransmit(void){ | ||
+ | |||
+ | int receivebin[150]; | ||
+ | int number = 0; | ||
+ | |||
+ | while (number < 28){ | ||
+ | //transmit | ||
+ | SPI1BUF = testTI[number]; | ||
+ | //receive | ||
+ | while(SPI1STATbits.SPIRBE); //wait for buffer | ||
+ | receivebin[number] = SPI1BUF; // goes to /dev/null | ||
+ | number++; | ||
+ | } | ||
+ | }//SPI1STAT//SPI1BUF | ||
+ | |||
+ | //non dma spi | ||
+ | void SPITransmit2(void){ //Yes, I know this is a duplicate. Just testing. | ||
+ | |||
+ | int receivebin[150]; | ||
+ | int number = 0; | ||
+ | |||
+ | while (number < 28){ | ||
+ | //transmit | ||
+ | SPI1BUF = testTI2[number]; | ||
+ | //receive | ||
+ | while(SPI1STATbits.SPIRBE); //wait for buffer | ||
+ | receivebin[number] = SPI1BUF; // goes to /dev/null | ||
+ | number++; | ||
+ | } | ||
+ | }//SPI1STAT//SPI1BUF//SPI1CON | ||
+ | |||
+ | main(){ | ||
+ | configurePorts(); | ||
+ | configureSPI(); | ||
+ | int cat = 0; | ||
+ | while(1){ | ||
+ | SPITransmit(); | ||
+ | for(cat = 0;cat<400000;cat++){ | ||
+ | asm("nop"); | ||
+ | } | ||
+ | SPITransmit2(); | ||
+ | for(cat = 0;cat<400000;cat++){ | ||
+ | asm("nop"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </pre> | ||
+ | I also have prefetch disabled. See https://microchipdeveloper.com/32bit:mz-cache-disable | ||
+ | |||
+ | todo: test code | ||
==References== | ==References== |
Revision as of 15:37, 13 December 2019
The TLC59711 by Texas Instruments is a 16 bit 12 channel LED driver. It has a 224 bit stream required for each chip. The stream has 32 bits of configuration data (config + 21 brightness), and 192 bits for the LEDs.
Example Code
This code runs on an Olimex PIC32-HMZ144 development board. Note that SPI mode 3 must be used. The SPI mode refers to whether bits are
The SPI clock (SCK) polarity (parameter clock_idle) The SPI data out transmit edge (parameter edge)
The SPI "Modes" SPI knows 4 "standard" modes, reflecting the SCK's polarity (CPOL) and the SCK's phase (CPHA).
The definition is: SPI Mode CPOL CPHA 0 (or 0,0) 0 0 1 (or 0,1) 0 1 2 (or 1,0) 1 0 3 (or 1,1) 1 1
The meaning is:
CPOL: 0 = Clock Idle low level 1 = Clock Idle high level CPHA: 0 = SDO transmit edge (*) active to idle 1 = SDO transmit edge idle to active
(*): the transmit edge is the clock edge at which the SDO level changes
Ref: http://www.rosseeld.be/DRO/PIC/SPI_Timing.htm
Example Code:
// DEVCFG3 // USERID = No Setting #pragma config FMIIEN = OFF // Ethernet RMII/MII Enable (MII Enabled) #pragma config FETHIO = OFF // Ethernet I/O Pin Select (Default Ethernet I/O) #pragma config PGL1WAY = OFF // Permission Group Lock One Way Configuration (Allow only one reconfiguration) #pragma config PMDL1WAY = ON // Peripheral Module Disable Configuration (Allow only one reconfiguration) #pragma config IOL1WAY = ON // Peripheral Pin Select Configuration (Allow only one reconfiguration) #pragma config FUSBIDIO = OFF // USB USBID Selection (Controlled by the USB Module) #pragma config POSCMOD = HS #pragma config FNOSC = SPLL #pragma config FPLLICLK= PLL_POSC #pragma config FPLLIDIV= DIV_2 // 6MHz #pragma config FPLLRNG = RANGE_5_10_MHZ #pragma config FPLLMULT= MUL_66 // 396MHz #pragma config FPLLODIV= DIV_2 // 198MHz #define SYSFREQ (198000000L) #pragma config UPLLFSEL = FREQ_24MHZ // USB PLL Input Frequency Selection (USB PLL input is 24 MHz) #pragma config UPLLEN = OFF #pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value) #pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576) #pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming) #pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode) #pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Enabled) #pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%) #pragma config DMTCNT = DMT31 // Deadman Timer Count Selection (2^31 (2147483648)) #pragma config FDMTEN = OFF // Deadman Timer Enable (Deadman Timer is enabled) // DEVCFG0 #pragma config DEBUG = OFF // Background Debugger Enable (Debugger is disabled) #pragma config JTAGEN = OFF // JTAG Enable (JTAG Port Enabled) #pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2) #pragma config TRCEN = OFF // Trace Enable (Trace features in the CPU are enabled) #pragma config BOOTISA = MIPS32 // Boot ISA Selection (Boot code and Exception code is MIPS32) #pragma config FECCCON = OFF_UNLOCKED // Dynamic Flash ECC Configuration (ECC and Dynamic ECC are disabled (ECCCON bits are writable)) #pragma config FSLEEP = OFF // Flash Sleep Mode (Flash is powered down when the device is in Sleep mode) #pragma config DBGPER = PG_ALL // Debug Mode CPU Access Permission (Allow CPU access to all permission regions) #pragma config EJTAGBEN = NORMAL // EJTAG Boot (Normal EJTAG functionality) // DEVCP0 #pragma config CP = OFF // Code Protect (Protection Disabled) //TLC5971 //0x25 b100101 //0x16 b10110 //17 x 3 bits high (brightness) //16 x 3 bits colour unsigned char __attribute__((coherent))testTI[28] = {0b10010110, //25, then half of 16 0b11011111, //some of 16 (3 bits), and start of brightness (5 bits for brightness) 0xFF,0xFF,//end brightness //for color, 16 bits each 0,0,0,0,0,0,0,0, //color data for 12 channels 0,0,0,0,0,0,0,0, // 0,0,0,0,0,0,0xFF,0xFF};// channels 0 are here //224 / 8 == 28. 4 bytes for config/brightness. 24 bytes for colour. unsigned char __attribute__((coherent))testTI2[28] = {0b10010110, 0b11011111, 0xFF,0xFF, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0xFF,0xFF,0,0,0,0}; void configurePorts (void){ AD1CON1 = 0; // disable ADC //SPI Ports //UEXT / RD15 SCK6, AN33, RPD15, RD15 SPI6CONCLR = _SPI6CON_ON_MASK; ANSELD = 0; ANSELDCLR = _ANSELD_ANSD15_MASK; TRISDbits.TRISD15 = 0; //output RPD15Rbits.RPD15R = 0b0101; //assign SDO1 to RPD15 //RPD15R; SPI6CON } void configureSPI(void){ IEC3bits.SPI1EIE = 0; //disable interrupts IEC3bits.SPI1RXIE = 0; IEC3bits.SPI1TXIE = 0; IEC3bits.SPI1EIE = 0; //enable general error flag (all three get flagged, in practice) IEC3bits.SPI1RXIE = 0; //SPI Priority for Interrupts IPC27bits.SPI1TXIP = 6; //priority IPC27bits.SPI1TXIS = 2; IPC27bits.SPI1RXIP = 7; //priority IPC27bits.SPI1RXIS = 3; rData = SPI1BUF; //enable SPI SPI1CONbits.ON = 0; //stop & reset module SPI1BUF = 0; //clear buffer (rx/tx) SPI1STATbits.SPIROV = 0; //clear rx overflow SPI1CONbits.MSTEN = 1; //master (not slave mode) SPI1CONbits.ON = 1; //enable SPI //Adafruit website (see led docs) remarks spi mode 3 needed so... SPI1CONbits.CKP = 1; SPI1CONbits.SMP = 1;//sample phase (clock "phase" to sample) SPI1CONbits.CKE = 0; //REQUIRED } //non dma spi void SPITransmit(void){ int receivebin[150]; int number = 0; while (number < 28){ //transmit SPI1BUF = testTI[number]; //receive while(SPI1STATbits.SPIRBE); //wait for buffer receivebin[number] = SPI1BUF; // goes to /dev/null number++; } }//SPI1STAT//SPI1BUF //non dma spi void SPITransmit2(void){ //Yes, I know this is a duplicate. Just testing. int receivebin[150]; int number = 0; while (number < 28){ //transmit SPI1BUF = testTI2[number]; //receive while(SPI1STATbits.SPIRBE); //wait for buffer receivebin[number] = SPI1BUF; // goes to /dev/null number++; } }//SPI1STAT//SPI1BUF//SPI1CON main(){ configurePorts(); configureSPI(); int cat = 0; while(1){ SPITransmit(); for(cat = 0;cat<400000;cat++){ asm("nop"); } SPITransmit2(); for(cat = 0;cat<400000;cat++){ asm("nop"); } }
I also have prefetch disabled. See https://microchipdeveloper.com/32bit:mz-cache-disable
todo: test code