From 6325170d1c652670ad4cb12600d168933695292f Mon Sep 17 00:00:00 2001 From: Hans-Gert Dahmen Date: Wed, 21 Dec 2011 04:54:48 +0000 Subject: [PATCH] new hardware driver, still beta --- borg_hw/Makefile | 6 +- borg_hw/borg_hw_borg16_hgmod.c | 245 +++++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 borg_hw/borg_hw_borg16_hgmod.c diff --git a/borg_hw/Makefile b/borg_hw/Makefile index 748424f..3eaaa6d 100644 --- a/borg_hw/Makefile +++ b/borg_hw/Makefile @@ -1,7 +1,7 @@ TARGET = libborg_hw.a TOPDIR = .. -SRC_SIM := +SRC_SIM := include $(TOPDIR)/defaults.mk @@ -10,6 +10,10 @@ ifeq ($(BORG_HW),HW_BORG_16) SRC = borg_hw_borg16.c endif +ifeq ($(BORG_HW),HW_BORG_16_HGM) + SRC = borg_hw_borg16_hgmod.c +endif + ifeq ($(BORG_HW),HW_BORG_ANDRE) SRC = borg_hw_andreborg.c endif diff --git a/borg_hw/borg_hw_borg16_hgmod.c b/borg_hw/borg_hw_borg16_hgmod.c new file mode 100644 index 0000000..f9033e1 --- /dev/null +++ b/borg_hw/borg_hw_borg16_hgmod.c @@ -0,0 +1,245 @@ +#include "../config.h" +#include "../makros.h" + +#include +#include +#include +#include "borg_hw.h" + +/* + // those macros get defined via menuconfig, now +*/ + +#define TLC_PIN_SIN 0 +#define TLC_PIN_SCLK 1 +#define TLC_PIN_SOUT 5 +#define TLC_PIN_XLAT 2 +#define TLC_PIN_BLANK 3 +#define TLC_PIN_VPRG 7 +#define TLC_PIN_DCPRG 4 +#define TLC_PIN_XERR 6 + +#define COLDDR DDR(COLPORT) +#define ROWDDR DDR(ROWPORT) + +#define SCLK() { \ + COLPORT |= _BV(TLC_PIN_SCLK); \ + COLPORT &= ~_BV(TLC_PIN_SCLK); \ + } + +#define XLAT() { \ + COLPORT |= _BV(TLC_PIN_XLAT); \ + COLPORT &= ~_BV(TLC_PIN_XLAT); \ + } + +/* more ifdef magic :-( */ +#ifdef __AVR_ATmega644P__ + #define OCR0 OCR0A + #define SIG_OUTPUT_COMPARE0 SIG_OUTPUT_COMPARE0A +#endif + +// buffer which holds the currently shown frame +unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; + +// switch to next row +static void nextrow(uint8_t row) { + unsigned char i; + static unsigned char row = 0; + + //blank outputs of low-side (column) driver + COLPORT |= _BV(TLC_PIN_BLANK); + + //increment & wrap row counter + if (++row == NUM_ROWS) row = 0; + + // short delay loop, to ensure proper deactivation of the drivers + for (i = 0; i < 10; i++) asm volatile("nop"); + + // row 0: initialize first shift register + if (row == 0) + { + #ifndef INVERT_ROWS + ROWPORT &= ~(1 << PIN_MCLR); + ROWPORT |= (1 << PIN_MCLR); + ROWPORT |= (1 << PIN_DATA); + ROWPORT |= (1 << PIN_CLK); + ROWPORT &= ~(1 << PIN_CLK); + ROWPORT &= ~(1 << PIN_DATA); + #else + ROWPORT&= ~(1<>1) + ((row & 0x01)?8:0 ); + tmp = pixmap[plane][row][0]; + tmp1 = pixmap[plane][row][1]; + +#ifdef REVERSE_COLS + tmp = (tmp >> 4) | (tmp << 4); + tmp = ((tmp & 0xcc) >> 2) | ((tmp & 0x33)<< 2); //0xcc = 11001100, 0x33 = 00110011 + tmp = ((tmp & 0xaa) >> 1) | ((tmp & 0x55)<< 1); //0xaa = 10101010, 0x55 = 1010101 + COLPORT2 = tmp; + tmp = tmp1; + tmp = (tmp >> 4) | (tmp << 4); + tmp = ((tmp & 0xcc) >> 2) | ((tmp & 0x33) << 2); //0xcc = 11001100, 0x33 = 00110011 + tmp = ((tmp & 0xaa) >> 1) | ((tmp & 0x55) << 1); //0xaa = 10101010, 0x55 = 1010101 + COLPORT1 = tmp; +#else + COLPORT1 = tmp; + COLPORT2 = tmp1; +#endif +} +*/ + + +// depending on the plane this interrupt triggers at 50 kHz, 31.25 kHz or +// 12.5 kHz +SIGNAL(SIG_OUTPUT_COMPARE0) { + uint8_t i, x; + + // reset watchdog + wdt_reset(); + + // switch rows + nextrow(row); + + // output current row according to current plane + //rowshow(row, plane); + + //debug: load 100% duty cycle into column driver + for(i = 0; i < 16; i++) //16 x 12bit + { + //shift in 12 bit words + for(x = 0; x < 12; x++) + { + COLPORT &= ~_BV(TLC_PIN_SIN); + COLPORT |= ((uint8_t)((uint16_t)0xFFF >> x) & 1) << TLC_PIN_SIN; + SCLK(); + } + } + + //latch data and disable blanking + XLAT(); + COLPORT &= ~_BV(TLC_PIN_BLANK); +} + + +void timer0_off() { + cli(); + + COLPORT = 0; + ROWPORT = 0; + + #ifdef __AVR_ATmega644P__ + TCCR0A = 0x00; + TCCR0B = 0x00; + #else + TCCR0 = 0x00; + #endif + + sei(); +} + + +// initialize timer which triggers the interrupt +static void timer0_on() { + /* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 + * CS02 CS01 CS00 + * 0 0 0 stop + * 0 0 1 clk + * 0 1 0 clk/8 + * 0 1 1 clk/64 + * 1 0 0 clk/256 + * 1 0 1 clk/1024 + */ + + #ifdef __AVR_ATmega644P__ + TCCR0A = 0x02; // CTC Mode + TCCR0B = 0x04; // clk/256 + TCNT0 = 0; // reset timer + OCR0 = 20; // compare with this value + TIMSK0 = 0x02; // compare match Interrupt on + #else + TCCR0 = 0x0C; // CTC Mode, clk/256 + TCNT0 = 0; // reset timer + OCR0 = 20; // compare with this value + TIMSK = 0x02; // compare match Interrupt on + #endif +} + + +void tlc5940_init() +{ + uint8_t i; + + //init control port pins + COLDDR = 0x00; + COLDDR = _BV(TLC_PIN_SCLK) | _BV(TLC_PIN_SIN) + | _BV(TLC_PIN_XLAT) | _BV(TLC_PIN_BLANK) + | _BV(TLC_PIN_VPRG) | _BV(TLC_PIN_DCPRG); + + //switch off all outputs and pull-ups + //xerr is open-drain, enable PUP + //set blank flag (disable led-outputs) + //dcprog is high -> use values from dc register + //vprg is high -> dot correction mode mode + COLPORT = _BV(TLC_PIN_XERR) | _BV(TLC_PIN_BLANK) | _BV(TLC_PIN_DCPRG) | _BV(TLC_PIN_VPRG); + + //set max power (6bit * 16 LEDs) + COLPORT |= _BV(TLC_PIN_SIN); + for(i = 0; i < 96; i++) SCLK(); + XLAT(); + + //switch to grayscale mode + COLPORT &= ~_BV(TLC_PIN_VPRG); + + //flush input shift register (12bit * 16 LEDs) + COLPORT &= ~_BV(TLC_PIN_SIN); + for(i = 0; i < 192; i++) SCLK(); + XLAT(); + + //one extra clk pulse is needed after switching from dc mode + SCLK(); +} + + +void borg_hw_init() { + //init column driver + tlc5940_init(); + + // switch pins of the row port to output mode + ROWDDR = (1 << PIN_MCLR) | (1 << PIN_CLK) | (1 << PIN_DATA); + + // reset shift registers for the rows + ROWPORT = 0; + + //activate the activator + timer0_on(); + + // activate watchdog timer + wdt_reset(); + wdt_enable(0x00); // 17ms watchdog +}