TLC5940

First for my RGB matrix project i tried using the TLC5940 to control LEDs but decided to not use it since LED strips are easier to assemble than individual LEDs.

I actually got it working at 30Mhz with my TM4C1294XL launchpad. This was when i just started using TivaWare so in the beginning i used only timers to do this which limited me at 400Khz since it need allot of interrupts and although i used an ARM at 120Mhz it was to much.

Using the Quad-SSI module was much beter.

I used a PWM signal from a timer for the GSCLK and the SSI CLK for the SCLK. Both working at 30Mhz. I made so that the data transfer would only start at the start of a new GSCLK cycle.

The code is attached into this page. It was made in Energia.

With this i had pretty good results, in this picture i have only 256 resolution to achieve higher refresh rate:

Here is the final result:

The code was made using Energia and here is the file when imported to CCS. It's for the TM4C1294 launchpad

#include "Energia.h"void setup();void loop();void PWMInit(uint32_t freq);void PWMStart();void TimerCaptureInit(uint16_t resolution);void BlankPWM();void DataUpdateInt();void SPIInit(uint32_t freq);void SendData(int values[]);#define PART_TM4C1294NCPDT#include <stdbool.h>#include <stdint.h>#include "inc/hw_memmap.h"#include "inc/hw_timer.h"#include "inc/hw_pwm.h"#include "driverlib/gpio.h"#include "driverlib/pin_map.h"#include "driverlib/ssi.h"#include "driverlib/sysctl.h"#include "driverlib/pwm.h"#include "driverlib/timer.h" uint32_t GSCLKfreq = 30000000; uint32_t SCLKfreq = 30000000;int resolution = 4095-13;volatile int updating =0;int values[16];int time = 10;int tick = 10;void setup(){ SPIInit(SCLKfreq); TimerCaptureInit(resolution); PWMInit(GSCLKfreq); PWMStart(); int valor = 0; for(int i=0; i < 16; i++){ values[i] = valor; } for(int i=0; i <= resolution+13; i+=tick){ values[1] = i; delay(time); } }void loop(){ for(int i=0; i <= resolution+13; i+=tick){ values[2] = i; delay(time); } for(int i=4095; i >= 0; i-=tick){ values[1] = i; delay(time); } for(int i=0; i <= resolution+13; i+=tick){ values[3] = i; delay(time); } for(int i=4095; i >= 0; i-=tick){ values[2] = i; delay(time); } for(int i=0; i <= resolution+13; i+=tick){ values[1] = i; delay(time); } for(int i=4095; i >= 0; i-=tick){ values[3] = i; delay(time); } }void PWMInit(uint32_t freq){ SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); SysCtlDelay(10); GPIOPinConfigure(GPIO_PF1_M0PWM1); GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1); PWMClockSet(PWM0_BASE, PWM_SYSCLK_DIV_1); PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); freq = 1.0/freq * F_CPU; PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, freq); PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, freq/2); PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, false); PWMGenEnable(PWM0_BASE, PWM_GEN_0); }void PWMStart(){ PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true); }void TimerCaptureInit(uint16_t resolution){ SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM); GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE , GPIO_PIN_3 |GPIO_PIN_2); GPIOPadConfigSet(GPIO_PORTM_BASE, GPIO_PIN_3|GPIO_PIN_2, GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD); HWREG(GPIO_PORTM_BASE + ((GPIO_PIN_2 << 2))) = 0; HWREG(GPIO_PORTM_BASE + ((GPIO_PIN_3 << 2))) = 0; // GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE , GPIO_PIN_2); // GPIOPadConfigSet(GPIO_PORTM_BASE, GPIO_PIN_2, GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD); GPIOPinConfigure(GPIO_PM4_T4CCP0); GPIOPinTypeTimer(GPIO_PORTM_BASE, GPIO_PIN_4); SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER4); TimerConfigure(TIMER4_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_CAP_COUNT); TimerLoadSet(TIMER4_BASE, TIMER_A, resolution); TimerMatchSet(TIMER4_BASE, TIMER_A, 0); // PWM TimerControlEvent(TIMER4_BASE, TIMER_A, TIMER_EVENT_POS_EDGE); // TimerIntRegister(TIMER4_BASE,TIMER_A,BlankPWM); TimerIntRegister(TIMER4_BASE,TIMER_A,DataUpdateInt); TimerIntClear(TIMER4_BASE,TIMER_CAPA_MATCH); TimerIntEnable(TIMER4_BASE,TIMER_CAPA_MATCH); TimerEnable(TIMER4_BASE,TIMER_A); }void BlankPWM(){ //PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, false); HWREG(PWM0_BASE + PWM_O_ENABLE) &= ~(PWM_OUT_1_BIT); //TimerIntClear(TIMER4_BASE,TIMER_CAPA_MATCH); HWREG(TIMER4_BASE + TIMER_O_ICR) = TIMER_CAPA_MATCH; //GPIOPinWrite(GPIO_PORTM_BASE,GPIO_PIN_3,GPIO_PIN_3); HWREG(GPIO_PORTM_BASE + ((GPIO_PIN_3 << 2))) = GPIO_PIN_3; //TimerEnable(TIMER4_BASE,TIMER_A); HWREG(TIMER4_BASE + TIMER_O_CTL) |= TIMER_A & (TIMER_CTL_TAEN | TIMER_CTL_TBEN); //GPIOPinWrite(GPIO_PORTM_BASE,GPIO_PIN_3,0); HWREG(GPIO_PORTM_BASE + ((GPIO_PIN_3 << 2))) = 0; //PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true); HWREG(PWM0_BASE + PWM_O_ENABLE) |= PWM_OUT_1_BIT;}void DataUpdateInt(){ //PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, false); HWREG(PWM0_BASE + PWM_O_ENABLE) &= ~(PWM_OUT_1_BIT); //GPIOPinWrite(GPIO_PORTM_BASE,GPIO_PIN_3,GPIO_PIN_3); HWREG(GPIO_PORTM_BASE + ((GPIO_PIN_3 << 2))) = GPIO_PIN_3; //GPIOPinWrite(GPIO_PORTM_BASE,GPIO_PIN_2,GPIO_PIN_2); HWREG(GPIO_PORTM_BASE + ((GPIO_PIN_2 << 2))) = GPIO_PIN_2; //TimerIntClear(TIMER4_BASE,TIMER_CAPA_MATCH); HWREG(TIMER4_BASE + TIMER_O_ICR) = TIMER_CAPA_MATCH; //TimerEnable(TIMER4_BASE,TIMER_A); HWREG(TIMER4_BASE + TIMER_O_CTL) |= TIMER_A & (TIMER_CTL_TAEN | TIMER_CTL_TBEN); //GPIOPinWrite(GPIO_PORTM_BASE,GPIO_PIN_2,0); HWREG(GPIO_PORTM_BASE + ((GPIO_PIN_2 << 2))) = 0; //GPIOPinWrite(GPIO_PORTM_BASE,GPIO_PIN_3,0); HWREG(GPIO_PORTM_BASE + ((GPIO_PIN_3 << 2))) = 0; //PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true); HWREG(PWM0_BASE + PWM_O_ENABLE) |= PWM_OUT_1_BIT; //updating = 0; SendData(values); // TimerIntRegister(TIMER4_BASE,TIMER_A,BlankPWM); }void SPIInit(uint32_t freq){ // put your setup code here, to run once: SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinConfigure(GPIO_PA2_SSI0CLK); GPIOPinConfigure(GPIO_PA4_SSI0XDAT0); GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_4 |GPIO_PIN_2); SSIConfigSetExpClk(SSI0_BASE, F_CPU, SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER, freq, 12); SSIEnable(SSI0_BASE);}void SendData(int values[]){ //while(updating == 1); // updating = 1; // TimerIntRegister(TIMER4_BASE,TIMER_A,DataUpdateInt); for(int i=15; i >= 0; i--) SSIDataPut(SSI0_BASE, values[i]); }