trouble with POV display

MiniPOV4 and previous versions

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
fem4ya
 
Posts: 1
Joined: Thu Jun 27, 2013 3:18 am

trouble with POV display

Post by fem4ya »

I am having trouble completing this POV project. I bought all the pieces for the project. I assembled 10 LEDs (I am using RGB's common anode), 2 tlc5940, and a atmega328p. I connected everything together and used the code in the attachment
main.c
(5.42 KiB) Downloaded 549 times
. I am using the code from (Matthew T. Pandina, Demystifying the TLC5940). The code works but I am having trouble modifying his code into what I want. I am using winavr to code. I am going to have the POV spin in a clockwise direction. I have an idea of how it should work but I'm having difficulty programming.


#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>


#define GSCLK_DDR DDRB
#define GSCLK_PORT PORTB
#define GSCLK_PIN PB0

#define SIN_DDR DDRB
#define SIN_PORT PORTB
#define SIN_PIN PB3

#define SCLK_DDR DDRB
#define SCLK_PORT PORTB
#define SCLK_PIN PB5

#define BLANK_DDR DDRB
#define BLANK_PORT PORTB //defining the corresponding pins to Atmega328p
#define BLANK_PIN PB2

#define DCPRG_DDR DDRD
#define DCPRG_PORT PORTD
#define DCPRG_PIN PD4

#define VPRG_DDR DDRD
#define VPRG_PORT PORTD
#define VPRG_PIN PD7

#define XLAT_DDR DDRB
#define XLAT_PORT PORTB
#define XLAT_PIN PB1

#define TLC5940_N 2 //number of TLC5940's

#define setOutput(ddr, pin) ((ddr) |= (1 << (pin)))
#define setLow(port, pin) ((port) &= ~(1 << (pin))) //set pins High or Low / Pulse pins High then Low
#define setHigh(port, pin) ((port) |= (1 << (pin)))
#define pulse(port, pin) do {\
setHigh((port), (pin));\
setLow((port), (pin));\
} while (0)
#define outputState(port, pin) ((port) & (1 << (pin)))

#if (12 * TLC5940_N > 255)
#define dcData_t uint16_t
#else
#define dcData_t uint8_t
#endif

#if (24 * TLC5940_N > 255)
#define gsData_t uint16_t
#else
#define gsData_t uint8_t
#endif

#if (16 * TLC5940_N > 255)
#define channel_t uint16_t
#else
#define channel_t uint8_t
#endif

#define dcDataSize ((dcData_t)12 * TLC5940_N)
#define gsDataSize ((gsData_t)24 * TLC5940_N)
#define numChannels ((channel_t)16 * TLC5940_N)



uint8_t dcData[dcDataSize];
uint8_t gsData[gsDataSize];
volatile uint8_t gsUpdateFlag;



static inline void TLC5940_SetGSUpdateFlag(void) {
__asm__ volatile (" " ::: "memory");
gsUpdateFlag = 1;
}



void TLC5940_Init(void) {
setOutput(GSCLK_DDR, GSCLK_PIN);
setOutput(SCLK_DDR, SCLK_PIN);
setOutput(DCPRG_DDR, DCPRG_PIN);
setOutput(VPRG_DDR, VPRG_PIN);
setOutput(XLAT_DDR, XLAT_PIN);
setOutput(BLANK_DDR, BLANK_PIN);
setOutput(SIN_DDR, SIN_PIN);
// Intialize TLC5940 setting up pins State
setLow(GSCLK_PORT, GSCLK_PIN);
setLow(SCLK_PORT, SCLK_PIN);
setLow(DCPRG_PORT, DCPRG_PIN);
setHigh(VPRG_PORT, VPRG_PIN);
setLow(XLAT_PORT, XLAT_PIN);
setHigh(BLANK_PORT, BLANK_PIN);

SPCR = (1 << SPE) | (1 << MSTR);
SPSR = (1 << SPI2X);

//CTC with OCR0A as TOP
TCCR0A = (1 << WGM01);
// clk_io/1024 (From prescaler)
TCCR0B = ((1 << CS02) | (1 << CS00));
// Generate an interrupt every 4096 clock cycles
OCR0A = 3;
// Enables Timer/Counter0 Compare Match A interrupt
TIMSK0 |= (1 << OCIE0A);
}

void TLC5940_SetAllDC(uint8_t value) {
uint8_t tmp1 = (uint8_t) (value << 2);
uint8_t tmp2 = (uint8_t) (tmp1 << 2);
uint8_t tmp3 = (uint8_t) (tmp2 << 2);
tmp1 |= (value >> 4);
tmp2 |= (value >> 2);
tmp3 |= value;

dcData_t i = 0;
do {
dcData[i++] = tmp1;
dcData[i++] = tmp2;
dcData[i++] = tmp3;
} while (i < dcDataSize);
}

void TLC5940_SetDC(channel_t channel, uint8_t value) {
channel = numChannels - 1 - channel;
uint16_t i = (uint16_t)channel * 3 / 4;

switch (channel % 4) {
case 0:
dcData = (dcData & 0x03) | (uint8_t)(value << 2);
break;
case 1:
dcData = (dcData & 0xFC) | (value >> 4);
i++;
dcData = (dcData & 0x0F) | (uint8_t)(value << 4);
break;
case 2:
dcData = (dcData & 0xF0) | (value >> 2);
i++;
dcData = (dcData & 0x3F) | (uint8_t)(value << 6);
break;
default: //case 3:
dcData[i] = (dcData[i] & 0xC0) | (value);
break;
}
}

void TLC5940_ClockInDC(void) {
setHigh(DCPRG_PORT, DCPRG_PIN);
setHigh(VPRG_PORT, VPRG_PIN);

for (dcData_t i = 0; i < dcDataSize; i++) {
// Start transmission
SPDR = dcData[i];
// Wait for transmission complete
while (!(SPSR & (1 << SPIF)));
}
pulse(XLAT_PORT, XLAT_PIN);
}

void TLC5940_SetAllGS(uint16_t value) {
uint8_t tmp1 = (value >> 4);
uint8_t tmp2 = (uint8_t)(value << 4) | (tmp1 >>4);
gsData_t i = 0;
do {
gsData[i++] = tmp1;
gsData[i++] = tmp2;
gsData[i++] = (uint8_t) value;
} while (i < gsDataSize);
}

void TLC5940_SetGS(channel_t channel, uint16_t value) {
channel = numChannels - 1 - channel;
uint16_t i = (uint16_t)channel * 3 / 2;

switch (channel % 2) {
case 0:
gsData[i] = (value >> 4);
i++;
gsData[i] = (gsData[i] & 0x0F) | (uint8_t)(value << 4);
break;
default: // case 1:
gsData[i] = (gsData[i] & 0xF0) | (value >> 8);
i++;
gsData[i] = (uint8_t)value;
break;
}
}
ISR(TIMER0_COMPA_vect) {
static uint8_t xlatNeedsPulse = 0;

setHigh (BLANK_PORT, BLANK_PIN);

if (outputState(VPRG_PORT, VPRG_PIN)) {
setLow(VPRG_PORT, VPRG_PIN);
if (xlatNeedsPulse) {
pulse(XLAT_PORT, XLAT_PIN);
xlatNeedsPulse = 0;
}
pulse(SCLK_PORT, SCLK_PIN);
} else if (xlatNeedsPulse) {
pulse (XLAT_PORT, XLAT_PIN);
xlatNeedsPulse = 0;
}

setLow(BLANK_PORT, BLANK_PIN);

if (gsUpdateFlag) {
for (gsData_t i = 0; i < gsDataSize; i++) {
SPDR = gsData[i];
while (!(SPSR & (1 << SPIF)));
}

xlatNeedsPulse = 1;
gsUpdateFlag = 0;
}
}


int main(void) {

int point;
TLC5940_Init();

TLC5940_SetAllDC(63);
TLC5940_ClockInDC();

TLC5940_SetAllGS(0);

sei();

channel_t i = 0;

for(;;) {
while(gsUpdateFlag);
TLC5940_SetAllGS(0);
TLC5940_SetGS(i,4000);

TLC5940_SetGSUpdateFlag();
_delay_ms(10);
i = (i + 1) % numChannels;

}

return 0;
}

Locked
Please be positive and constructive with your questions and comments.

Return to “MiniPOV”