From 22f14abb32083c132b3cbeb99ac4bc40e3208aea Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Thu, 15 May 2014 11:13:35 +0200 Subject: [PATCH] first working driver for Diavolino/LoL Shield --- config.in | 1 + profiles/LoL-Shield | 123 ++++++++++++ src/borg_hw/Makefile | 4 + src/borg_hw/borg_hw_lolshield.c | 322 ++++++++++++++++++++++++++++++++ src/borg_hw/config.in | 5 + src/borg_hw/config_lolshield.in | 4 + src/joystick/Makefile | 3 + src/joystick/config.in | 5 + src/joystick/joystick.h | 8 + src/joystick/null_joystick.c | 2 + src/scrolltext/font_small6.c | 12 +- src/util.c | 2 +- 12 files changed, 484 insertions(+), 7 deletions(-) create mode 100644 profiles/LoL-Shield create mode 100644 src/borg_hw/borg_hw_lolshield.c create mode 100644 src/borg_hw/config_lolshield.in create mode 100644 src/joystick/null_joystick.c diff --git a/config.in b/config.in index 57cb324..809eada 100644 --- a/config.in +++ b/config.in @@ -9,6 +9,7 @@ comment "General Setup" "ATmega8 atmega8 \ ATmega32 atmega32 \ ATmega328 atmega328 \ + ATmega328p atmega328p \ ATmega644 atmega644 \ ATmega644p atmega644p \ ATmega1284 atmega1284 \ diff --git a/profiles/LoL-Shield b/profiles/LoL-Shield new file mode 100644 index 0000000..2f9ed83 --- /dev/null +++ b/profiles/LoL-Shield @@ -0,0 +1,123 @@ +# +# Automatically generated by make menuconfig: don't edit +# + +# +# General Setup +# +MCU=atmega328p +FREQ=16000000 + +# +# Borg Hardware +# +NUM_ROWS=9 +NUM_COLS=14 +NUMPLANE=3 +BORG_HW=HW_LOLSHIELD + +# +# lolshield setup +# + +# +# Features +# +RANDOM_SUPPORT=y +# LAP_TIME_EXTENSION is not set +SCROLLTEXT_SUPPORT=y +SCROLLTEXT_FONT=FONT_SMALL6 +SCROLLTEXT_BUFFER_SIZE=128 +SCROLL_X_SPEED=20 +SCROLL_Y_SPEED=20 +SCROLLTEXT_TEXT=" +#include +#include +#include +#include +#include "borg_hw.h" + +// buffer which holds the currently shown frame +unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; + +#define FRAMERATE 80UL +#define CUTOFF(scaler) ((128 * 12 - 6) * FRAMERATE * scaler) + +// BEWARE: only the Diavolino Kit is supported at the moment +// other platforms don't work, yet +const uint8_t +#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) || defined (__AVR_ATmega8__) +# if F_CPU < CUTOFF(8) + fastPrescaler = _BV(CS20), // 1 + slowPrescaler = _BV(CS21); // 8 +# define SLOWSCALERSHIFT 3 +# define FASTSCALERSHIFT 3 +# elif F_CPU < CUTOFF(32) + fastPrescaler = _BV(CS21), // 8 + slowPrescaler = _BV(CS21) | _BV(CS20); // 32 +# define SLOWSCALERSHIFT 5 +# define FASTSCALERSHIFT 2 +# elif F_CPU < CUTOFF(64) + fastPrescaler = _BV(CS21), // 8 + slowPrescaler = _BV(CS22); // 64 +# define SLOWSCALERSHIFT 6 +# define FASTSCALERSHIFT 3 +# elif F_CPU < CUTOFF(128) + fastPrescaler = _BV(CS21) | _BV(CS20), // 32 + slowPrescaler = _BV(CS22) | _BV(CS20); // 128 +# define SLOWSCALERSHIFT 7 +# define FASTSCALERSHIFT 2 +# elif F_CPU < CUTOFF(256) + fastPrescaler = _BV(CS21) | _BV(CS20), // 32 + slowPrescaler = _BV(CS22) | _BV(CS21); // 256 +# define SLOWSCALERSHIFT 8 +# define FASTSCALERSHIFT 3 +# elif F_CPU < CUTOFF(1024) + fastPrescaler = _BV(CS22) | _BV(CS20), // 128 + slowPrescaler = _BV(CS22) | _BV(CS21) | _BV(CS20); // 1024 +# define SLOWSCALERSHIFT 10 +# define FASTSCALERSHIFT 3 +# else +# error frame rate is too low +# endif +#else +# error no support for this chip +#endif + + +ISR(TIMER2_OVF_vect) { + // For each cycle, we have potential planes to display. Once every plane has + // been displayed, then we move on to the next cycle. + // NOTE: a "cycle" means a subset of LEDs + + // 12 Cycles of Matrix + static uint8_t cycle = 0; + + // planes to display + // NOTE: a "plane" in the Borgware is the same as a "page" in Jimmie's lib + static uint8_t plane = 0; + + // pointer to corresponding bitmap + uint8_t *p = &pixmap[plane][0][0]; + + // tune timer values (fiddle around with them to adjust brightness) + static uint8_t const prescaler[NUMPLANE + 1] = {3, 3, 3, 6}; + TCCR2B = prescaler[plane]; + static uint8_t const counts[NUMPLANE + 1] = {241, 198, 148, 255}; + TCNT2 = counts[plane]; + + // Set sink pin to Vcc/source, turning off current. + static uint8_t sink_b, sink_d = 0; + PIND = sink_d; + PINB = sink_b; + + // Set pins to input mode; Vcc/source become pullups. + DDRD = 0; + DDRB = 0; + + static uint8_t const sink_d_cycle[] = + {0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static uint8_t const sink_b_cycle[] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20}; + + uint8_t pins_d = sink_d = sink_d_cycle[cycle]; + uint8_t pins_b = sink_b = sink_b_cycle[cycle]; + + // convert Borgware-2D framebuffer to LoL Shield cycles + // (I could have done this with a lookup table, but that would be slower as + // non-constant bit shifts are quite expensive on AVR) + if (plane < NUMPLANE) { + switch(cycle) { + case 0: + pins_b |= (0x02u & p[ 0]) << 4; // x=12, y= 0, high=13 + pins_b |= (0x02u & p[ 2]) << 3; // x=12, y= 1, high=12 + pins_b |= (0x02u & p[ 4]) << 2; // x=12, y= 2, high=11 + pins_b |= (0x02u & p[ 6]) << 1; // x=12, y= 3, high=10 + pins_b |= (0x02u & p[ 8]); // x=12, y= 4, high= 9 + pins_b |= (0x02u & p[10]) >> 1; // x=12, y= 5, high= 8 + pins_d |= (0x02u & p[12]) << 6; // x=12, y= 6, high= 7 + pins_d |= (0x02u & p[14]) << 5; // x=12, y= 7, high= 6 + pins_d |= (0x02u & p[16]) << 4; // x=12, y= 8, high= 5 + break; + case 1: + pins_b |= (0x08u & p[ 0]) << 2; // x=10, y= 0, high=13 + pins_b |= (0x08u & p[ 2]) << 1; // x=10, y= 1, high=12 + pins_b |= (0x08u & p[ 4]); // x=10, y= 2, high=11 + pins_b |= (0x08u & p[ 6]) >> 1; // x=10, y= 3, high=10 + pins_b |= (0x08u & p[ 8]) >> 2; // x=10, y= 4, high= 9 + pins_b |= (0x08u & p[10]) >> 3; // x=10, y= 5, high= 8 + pins_d |= (0x08u & p[12]) << 4; // x=10, y= 6, high= 7 + pins_d |= (0x08u & p[14]) << 3; // x=10, y= 7, high= 6 + pins_d |= (0x08u & p[16]) << 2; // x=10, y= 8, high= 5 + break; + case 2: + pins_b |= (0x20u & p[ 0]); // x= 8, y= 0, high=13 + pins_b |= (0x20u & p[ 2]) >> 1; // x= 8, y= 1, high=12 + pins_b |= (0x20u & p[ 4]) >> 2; // x= 8, y= 2, high=11 + pins_b |= (0x20u & p[ 6]) >> 3; // x= 8, y= 3, high=10 + pins_b |= (0x20u & p[ 8]) >> 4; // x= 8, y= 4, high= 9 + pins_b |= (0x20u & p[10]) >> 5; // x= 8, y= 5, high= 8 + pins_d |= (0x20u & p[12]) << 2; // x= 8, y= 6, high= 7 + pins_d |= (0x20u & p[14]) << 1; // x= 8, y= 7, high= 6 + pins_d |= (0x20u & p[16]); // x= 8, y= 8, high= 5 + break; + case 3: + pins_b |= (0x20u & p[ 1]); // x= 0, y= 0, high=13 + pins_b |= (0x20u & p[ 3]) >> 1; // x= 0, y= 1, high=12 + pins_b |= (0x20u & p[ 5]) >> 2; // x= 0, y= 2, high=11 + pins_b |= (0x20u & p[ 7]) >> 3; // x= 0, y= 3, high=10 + pins_b |= (0x20u & p[ 9]) >> 4; // x= 0, y= 4, high= 9 + pins_b |= (0x20u & p[11]) >> 5; // x= 0, y= 5, high= 8 + pins_d |= (0x01u & p[16]) << 2; // x=13, y= 8, high= 2 + pins_d |= (0x04u & p[16]) << 1; // x=11, y= 8, high= 3 + pins_d |= (0x10u & p[16]); // x= 9, y= 8, high= 4 + pins_d |= (0x20u & p[13]) << 2; // x= 0, y= 6, high= 7 + pins_d |= (0x20u & p[15]) << 1; // x= 0, y= 7, high= 6 + break; + case 4: + pins_b |= (0x10u & p[ 1]) << 1; // x= 1, y= 0, high=13 + pins_b |= (0x10u & p[ 3]); // x= 1, y= 1, high=12 + pins_b |= (0x10u & p[ 5]) >> 1; // x= 1, y= 2, high=11 + pins_b |= (0x10u & p[ 7]) >> 2; // x= 1, y= 3, high=10 + pins_b |= (0x10u & p[ 9]) >> 3; // x= 1, y= 4, high= 9 + pins_b |= (0x10u & p[11]) >> 4; // x= 1, y= 5, high= 8 + pins_d |= (0x01u & p[14]) << 2; // x=13, y= 7, high= 2 + pins_d |= (0x04u & p[14]) << 1; // x=11, y= 7, high= 3 + pins_d |= (0x10u & p[13]) << 3; // x= 1, y= 6, high= 7 + pins_d |= (0x10u & p[14]); // x= 9, y= 7, high= 4 + pins_d |= (0x20u & p[17]); // x= 0, y= 8, high= 5 + break; + case 5: + pins_b |= (0x08u & p[ 1]) << 2; // x= 2, y= 0, high=13 + pins_b |= (0x08u & p[ 3]) << 1; // x= 2, y= 1, high=12 + pins_b |= (0x08u & p[ 5]); // x= 2, y= 2, high=11 + pins_b |= (0x08u & p[ 7]) >> 1; // x= 2, y= 3, high=10 + pins_b |= (0x08u & p[ 9]) >> 2; // x= 2, y= 4, high= 9 + pins_b |= (0x08u & p[11]) >> 3; // x= 2, y= 5, high= 8 + pins_d |= (0x01u & p[12]) << 2; // x=13, y= 6, high= 2 + pins_d |= (0x04u & p[12]) << 1; // x=11, y= 6, high= 3 + pins_d |= (0x10u & p[12]); // x= 9, y= 6, high= 4 + pins_d |= (0x10u & p[15]) << 2; // x= 1, y= 7, high= 6 + pins_d |= (0x10u & p[17]) << 1; // x= 1, y= 8, high= 5 + break; + case 6: + pins_b |= (0x04u & p[ 1]) << 3; // x= 3, y= 0, high=13 + pins_b |= (0x04u & p[ 3]) << 2; // x= 3, y= 1, high=12 + pins_b |= (0x04u & p[ 5]) << 1; // x= 3, y= 2, high=11 + pins_b |= (0x04u & p[ 7]); // x= 3, y= 3, high=10 + pins_b |= (0x04u & p[ 9]) >> 1; // x= 3, y= 4, high= 9 + pins_d |= (0x01u & p[10]) << 2; // x=13, y= 5, high= 2 + pins_d |= (0x04u & p[10]) << 1; // x=11, y= 5, high= 3 + pins_d |= (0x08u & p[13]) << 4; // x= 2, y= 6, high= 7 + pins_d |= (0x08u & p[15]) << 3; // x= 2, y= 7, high= 6 + pins_d |= (0x08u & p[17]) << 2; // x= 2, y= 8, high= 5 + pins_d |= (0x10u & p[10]); // x= 9, y= 5, high= 4 + break; + case 7: + pins_b |= (0x02u & p[ 1]) << 4; // x= 4, y= 0, high=13 + pins_b |= (0x02u & p[ 3]) << 3; // x= 4, y= 1, high=12 + pins_b |= (0x02u & p[ 5]) << 2; // x= 4, y= 2, high=11 + pins_b |= (0x02u & p[ 7]) << 1; // x= 4, y= 3, high=10 + pins_b |= (0x04u & p[11]) >> 2; // x= 3, y= 5, high= 8 + pins_d |= (0x01u & p[ 8]) << 2; // x=13, y= 4, high= 2 + pins_d |= (0x04u & p[ 8]) << 1; // x=11, y= 4, high= 3 + pins_d |= (0x04u & p[13]) << 5; // x= 3, y= 6, high= 7 + pins_d |= (0x04u & p[15]) << 4; // x= 3, y= 7, high= 6 + pins_d |= (0x04u & p[17]) << 3; // x= 3, y= 8, high= 5 + pins_d |= (0x10u & p[ 8]); // x= 9, y= 4, high= 4 + break; + case 8: + pins_b |= (0x01u & p[ 1]) << 5; // x= 5, y= 0, high=13 + pins_b |= (0x01u & p[ 3]) << 4; // x= 5, y= 1, high=12 + pins_b |= (0x01u & p[ 5]) << 3; // x= 5, y= 2, high=11 + pins_b |= (0x02u & p[ 9]); // x= 4, y= 4, high= 9 + pins_b |= (0x02u & p[11]) >> 1; // x= 4, y= 5, high= 8 + pins_d |= (0x01u & p[ 6]) << 2; // x=13, y= 3, high= 2 + pins_d |= (0x02u & p[13]) << 6; // x= 4, y= 6, high= 7 + pins_d |= (0x02u & p[15]) << 5; // x= 4, y= 7, high= 6 + pins_d |= (0x02u & p[17]) << 4; // x= 4, y= 8, high= 5 + pins_d |= (0x04u & p[ 6]) << 1; // x=11, y= 3, high= 3 + pins_d |= (0x10u & p[ 6]); // x= 9, y= 3, high= 4 + break; + case 9: + pins_b |= (0x01u & p[ 7]) << 2; // x= 5, y= 3, high=10 + pins_b |= (0x01u & p[ 9]) << 1; // x= 5, y= 4, high= 9 + pins_b |= (0x01u & p[11]); // x= 5, y= 5, high= 8 + pins_b |= (0x80u & p[ 0]) >> 2; // x= 6, y= 0, high=13 + pins_b |= (0x80u & p[ 2]) >> 3; // x= 6, y= 1, high=12 + pins_d |= (0x01u & p[ 4]) << 2; // x=13, y= 2, high= 2 + pins_d |= (0x01u & p[13]) << 7; // x= 5, y= 6, high= 7 + pins_d |= (0x01u & p[15]) << 6; // x= 5, y= 7, high= 6 + pins_d |= (0x01u & p[17]) << 5; // x= 5, y= 8, high= 5 + pins_d |= (0x04u & p[ 4]) << 1; // x=11, y= 2, high= 3 + pins_d |= (0x10u & p[ 4]); // x= 9, y= 2, high= 4 + break; + case 10: + pins_b |= (0x40u & p[ 0]) >> 1; // x= 7, y= 0, high=13 + pins_b |= (0x80u & p[ 4]) >> 4; // x= 6, y= 2, high=11 + pins_b |= (0x80u & p[ 6]) >> 5; // x= 6, y= 3, high=10 + pins_b |= (0x80u & p[ 8]) >> 6; // x= 6, y= 4, high= 9 + pins_b |= (0x80u & p[10]) >> 7; // x= 6, y= 5, high= 8 + pins_d |= (0x01u & p[ 2]) << 2; // x=13, y= 1, high= 2 + pins_d |= (0x04u & p[ 2]) << 1; // x=11, y= 1, high= 3 + pins_d |= (0x10u & p[ 2]); // x= 9, y= 1, high= 4 + pins_d |= (0x80u & p[12]); // x= 6, y= 6, high= 7 + pins_d |= (0x80u & p[14]) >> 1; // x= 6, y= 7, high= 6 + pins_d |= (0x80u & p[16]) >> 2; // x= 6, y= 8, high= 5 + break; + case 11: + pins_b |= (0x40u & p[ 2]) >> 2; // x= 7, y= 1, high=12 + pins_b |= (0x40u & p[ 4]) >> 3; // x= 7, y= 2, high=11 + pins_b |= (0x40u & p[ 6]) >> 4; // x= 7, y= 3, high=10 + pins_b |= (0x40u & p[ 8]) >> 5; // x= 7, y= 4, high= 9 + pins_b |= (0x40u & p[10]) >> 6; // x= 7, y= 5, high= 8 + pins_d |= (0x01u & p[ 0]) << 2; // x=13, y= 0, high= 2 + pins_d |= (0x04u & p[ 0]) << 1; // x=11, y= 0, high= 3 + pins_d |= (0x10u & p[ 0]); // x= 9, y= 0, high= 4 + pins_d |= (0x40u & p[12]) << 1; // x= 7, y= 6, high= 7 + pins_d |= (0x40u & p[14]); // x= 7, y= 7, high= 6 + pins_d |= (0x40u & p[16]) >> 1; // x= 7, y= 8, high= 5 + break; + } + } + + // Enable pullups on new output pins. + PORTD = pins_d; + PORTB = pins_b; + // Set pins to output mode; pullups become Vcc/source. + DDRD = pins_d; + DDRB = pins_b; + // Set sink pin to GND/sink, turning on current. + PIND = sink_d; + PINB = sink_b; + + plane++; + + if (plane >= (NUMPLANE + 1)) { + plane = 0; + cycle++; + if (cycle >= 12) { + cycle = 0; + } + } + wdt_reset(); +} + +void borg_hw_init() { + // prepare Timer2 + TIMSK2 &= ~(_BV(TOIE2) | _BV(OCIE2A)); + TCCR2A &= ~(_BV(WGM21) | _BV(WGM20)); + TCCR2B &= ~_BV(WGM22); + ASSR &= ~_BV(AS2); + + // Then start the display + TIMSK2 |= _BV(TOIE2); + TCCR2B = fastPrescaler; + + // interrupt ASAP + TCNT2 = 0xff; + + // activate watchdog timer + wdt_reset(); + wdt_enable(0x00); // 17ms watchdog +} diff --git a/src/borg_hw/config.in b/src/borg_hw/config.in index d494ec3..9aabae5 100644 --- a/src/borg_hw/config.in +++ b/src/borg_hw/config.in @@ -14,6 +14,7 @@ choice 'Hardware Driver' \ Andre-Borg HW_BORG_ANDRE \ Laufschrift-Borg HW_BORG_LS \ Laufschrift-Borg-MH HW_BORG_MH \ + LoL-Shield/Diavolino HW_LOLSHIELD \ FFM-Jochen HW_BORG_LSJO \ FFM-LedBrett HW_LEDBRETT \ Borg-Mini HW_BORG_MINI \ @@ -45,6 +46,10 @@ if [ "$BORG_HW" == "HW_BORG_MH" ] ; then source src/borg_hw/config_borg_mh.in fi +if [ "$BORG_HW" == "HW_LOLSHIELD" ] ; then + source src/borg_hw/config_lolshield.in +fi + if [ "$BORG_HW" == "HW_BORG_LSJO" ] ; then source src/borg_hw/config_borg_lsjo.in fi diff --git a/src/borg_hw/config_lolshield.in b/src/borg_hw/config_lolshield.in new file mode 100644 index 0000000..4695361 --- /dev/null +++ b/src/borg_hw/config_lolshield.in @@ -0,0 +1,4 @@ +mainmenu_option next_comment +comment "lolshield setup" + +endmenu diff --git a/src/joystick/Makefile b/src/joystick/Makefile index ff1c5f7..bbbb411 100644 --- a/src/joystick/Makefile +++ b/src/joystick/Makefile @@ -18,6 +18,9 @@ endif ifeq ($(HC165_JOYSTICK_SUPPORT), y) SRC = hc165_joystick.c endif +ifeq ($(NULL_JOYSTICK_SUPPORT), y) + SRC = null_joystick.c +endif include $(MAKETOPDIR)/rules.mk diff --git a/src/joystick/config.in b/src/joystick/config.in index da6fff2..b68b099 100644 --- a/src/joystick/config.in +++ b/src/joystick/config.in @@ -193,6 +193,11 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then endmenu ############################################################################### +###################### null joystick menu #################################### + dep_bool "null joystick support" NULL_JOYSTICK_SUPPORT y +############################################################################### + + fi endmenu diff --git a/src/joystick/joystick.h b/src/joystick/joystick.h index 04d3840..0c606f4 100644 --- a/src/joystick/joystick.h +++ b/src/joystick/joystick.h @@ -41,6 +41,14 @@ void joy_init(); # define JOYISFIRE (! ((1<<4) & hc165_joystick_val)) +# elif defined(NULL_JOYSTICK_SUPPORT) + +# define JOYISUP (0) +# define JOYISDOWN (0) +# define JOYISLEFT (0) +# define JOYISRIGHT (0) +# define JOYISFIRE (0) + # else # define JOYISUP (!(JOYSTICK_PIN_UP & (1<