5940 and Arduino Yun

185 views
Skip to first unread message

Lawrence McIntosh

unread,
Dec 20, 2013, 7:52:00 PM12/20/13
to tlc5940...@googlegroups.com
Hi 

Does anyone know if something special has to be done to have the library work with the Arduino Yun? Yun uses the ATmega32u4, which appears to be accounted for in chip_includes.h 

I have set the circuit up on a breadboard as per the diagram and I don't seem to get any response from the LEDs. Oddly enough if I happen to brush GSCLK with my finger then the LEDs light up, but I suspect this is unrelated.

Any help would be much appreciated

Thanks
Lawrence

clement...@gmail.com

unread,
Feb 1, 2014, 7:57:26 PM2/1/14
to tlc5940...@googlegroups.com
Hello,
the Yun is atmega32u4 based, so it is pretty similar to the Leonardo/Teensy, and is sort of handled by the lib.
If you use the ICSP connector for the SPI mode, it should work.

If you want to use the exact same pinouts as on a UNO (eg D13, D11, D10, D9, D3) you could use the bitbang mode. It isn't implemented yet, but you only have to add something along the line of:
/** SIN (Arduino digital pin D11: PB7 on the Yun) -> SIN (TLC pin 26) */
#define DEFAULT_BB_SIN_PIN PB7
#define DEFAULT_BB_SIN_PORT PORTB
#define DEFAULT_BB_SIN_DDR DDRB

/** SCLK (Arduino digital pin D13: PC7 on the Yun) -> SCLK (TLC pin 25) */
#define DEFAULT_BB_SCLK_PIN PC7
#define DEFAULT_BB_SCLK_PORT PORTC
#define DEFAULT_BB_SCLK_DDR DDRC

instead of the line:
#error "If you want bitbang mode, insert pin defs here"
in the file Teensy_xxU4.h
And of course, set the right mode (eg bitbang) in the tlc_config.h file ;)


I was having trouble with the GSCLK generation ; it looks like it is not handled correctly by the TLC_TIMER3_GSCLK option.

If you read the datasheet, it is said that the DDR register for the corresponding pin must be configured as output, so in the init function, you have to have:
GSCLK_ALT_DDR |= _BV(GSCLK_ALT_PIN); // D5 as output
with:
//D5 is PC6 ; it is the OC03A pin which is piloted by the TLC_TIMER3_GSCLK option
#define GSCLK_ALT_PIN PC6
#define GSCLK_ALT_PORT PORTD
#define GSCLK_ALT_DDR DDRD
It works on my leonardo, but using D5 instead of D3 for GSCLK.

The bad news is that D3 is on OC0A, so it cannot be directly driven by the timer/pwm mode, given the fact that timer0 is required for stdlib (time functions of the Arduino/wiring environment).
One option is to use an interrupt handler and toggle that damn D3 pin manually there.

In the Tlc5940.cpp file, replace this:
void Tlc5940::init(uint16_t initialValue)
{
/* Pin Setup */
XLAT_DDR |= _BV(XLAT_PIN);
BLANK_DDR |= _BV(BLANK_PIN);
GSCLK_DDR |= _BV(GSCLK_PIN);
#if VPRG_ENABLED
VPRG_DDR |= _BV(VPRG_PIN);
VPRG_PORT &= ~_BV(VPRG_PIN); // grayscale mode (VPRG low)
#endif
#if XERR_ENABLED
XERR_DDR &= ~_BV(XERR_PIN); // XERR as input
XERR_PORT |= _BV(XERR_PIN); // enable pull-up resistor
#endif
BLANK_PORT |= _BV(BLANK_PIN); // leave blank high (until the timers start)

tlc_shift8_init();

setAll(initialValue);
update();
disable_XLAT_pulses();
clear_XLAT_interrupt();
tlc_needXLAT = 0;
pulse_pin(XLAT_PORT, XLAT_PIN);


/* Timer Setup */

/* Timer 1 - BLANK / XLAT */
TCCR1A = _BV(COM1B1); // non inverting, output on OC1B, BLANK
TCCR1B = _BV(WGM13); // Phase/freq correct PWM, ICR1 top
OCR1A = 1; // duty factor on OC1A, XLAT is inside BLANK
OCR1B = 2; // duty factor on BLANK (larger than OCR1A (XLAT))
ICR1 = TLC_PWM_PERIOD; // see tlc_config.h

/* Timer 2 - GSCLK */
#if defined(TLC_ATMEGA_8_H)
TCCR2 = _BV(COM20) // set on BOTTOM, clear on OCR2A (non-inverting),
| _BV(WGM21); // output on OC2B, CTC mode with OCR2 top
OCR2 = TLC_GSCLK_PERIOD / 2; // see tlc_config.h
TCCR2 |= _BV(CS20); // no prescale, (start pwm output)
#elif defined(TLC_TIMER3_GSCLK)
TCCR3A = _BV(COM3A1) // set on BOTTOM, clear on OCR3A (non-inverting),
// output on OC3A
| _BV(WGM31); // Fast pwm with ICR3 top
OCR3A = 0; // duty factor (as short a pulse as possible)
ICR3 = TLC_GSCLK_PERIOD; // see tlc_config.h
TCCR3B = _BV(CS30) // no prescale, (start pwm output)
| _BV(WGM32) // Fast pwm with ICR3 top
| _BV(WGM33); // Fast pwm with ICR3 top
#elif defined(TLC_TIMER_GSCLK_PATCH)
/* use timer3 + interrupt to output GSCLK ctrl on D3 (OC0B) (4MHz pulses)
* - timer 0 cannot be used, because arduino std lib requires it for time functions (millis, etc)
* - timer 3 cannot drive pin OC0B/D3 (pin18 on 32U4) directly ; it can drive pin D5 this way tho
* - we'll use an interrupt to manually toggle the D3 pin
*/
TCCR3A = _BV(WGM31); // set on BOTTOM, clear on OCR3A (non-inverting),
// Fast pwm with ICR3 top
OCR3A = 0; // duty factor (as short a pulse as possible)
ICR3 = TLC_GSCLK_PERIOD; // see tlc_config.h
TCCR3B = _BV(CS30) // no prescale, (start pwm output)
| _BV(WGM32) // Fast pwm with ICR3 top
| _BV(WGM33); // Fast pwm with ICR3 top

set_GSCLK_interrupt(); //clear the interrupt flag, then enable the compare match A on timer 3
#else
TCCR2A = _BV(COM2B1) // set on BOTTOM, clear on OCR2A (non-inverting),
// output on OC2B
| _BV(WGM21) // Fast pwm with OCR2A top
| _BV(WGM20); // Fast pwm with OCR2A top
TCCR2B = _BV(WGM22); // Fast pwm with OCR2A top
OCR2B = 0; // duty factor (as short a pulse as possible)
OCR2A = TLC_GSCLK_PERIOD; // see tlc_config.h
TCCR2B |= _BV(CS20); // no prescale, (start pwm output)
#endif
TCCR1B |= _BV(CS10); // no prescale, (start pwm output)
update();
}

#if defined(TLC_TIMER_GSCLK_PATCH)
/** Interrupt to generate GSCLK pulses. */
ISR(TIMER3_COMPA_vect)
{
//pulse pin D3
pulse_pin(GSCLK_PORT, GSCLK_PIN);
}
#endif

You will need this macro in the Tlc5940.h file:
#define set_GSCLK_interrupt() TIFR3 |= _BV(OCF3A); TIMSK3 |= _BV(OCIE3A)


This will work in bitbang mode, with the standards pins.


Anyway, I guess I'll have to submit a proper patch for the whole Leonardo/Yun support with the lib.
C.
Reply all
Reply to author
Forward
0 new messages