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