From 0546f195efead281dbd0601acc5fcfcb82cc88f9 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Thu, 15 May 2014 11:11:56 +0200 Subject: [PATCH 01/28] fixed mapping bug in moire.c --- src/animations/moire.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/animations/moire.c b/src/animations/moire.c index ce35b30..16b0ef8 100644 --- a/src/animations/moire.c +++ b/src/animations/moire.c @@ -45,25 +45,25 @@ void moire(void) // walk around the border; do that by mapping a linear increasing value // to appropriate screen coordinates - // first pixel is between top right and top left corner - if (pos < NUM_COLS) + // pixel is between top right and top left corner + if (pos < (NUM_COLS - 1)) { - p1.x = pos; + p1.x = pos + 1; } - // first pixel is between top left and bottom left corner - else if (pos < (NUM_COLS + NUM_ROWS - 1)) + // pixel is between top left and bottom left corner + else if (pos < (NUM_COLS + NUM_ROWS - 2)) { - p1.y = pos - (NUM_COLS - 1); + p1.y = pos - (NUM_COLS - 2); } - // first pixel is between bottom left and bottom right corner - else if (pos < (2 * NUM_COLS + NUM_ROWS - 2)) + // pixel is between bottom left and bottom right corner + else if (pos < (2 * NUM_COLS + NUM_ROWS - 3)) { - p1.x = 2 * NUM_COLS + NUM_ROWS - 3 - pos; + p1.x = 2 * NUM_COLS + NUM_ROWS - 4 - pos; } - // first pixel is between bottom right and top left corner + // pixel is between bottom right and top left corner else { - p1.y = 3 * NUM_COLS + NUM_ROWS - 4 - pos; + p1.y = 2 * NUM_COLS + 2 * NUM_ROWS - 5 - pos; } // second pixel in opposite direction From 22f14abb32083c132b3cbeb99ac4bc40e3208aea Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Thu, 15 May 2014 11:13:35 +0200 Subject: [PATCH 02/28] 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< Date: Thu, 15 May 2014 19:28:25 +0200 Subject: [PATCH 03/28] =?UTF-8?q?fixed=20langton=20ant=20for=20resoltuions?= =?UTF-8?q?=20with=20width!=3Dheight=20(my=20fault),=20also=20removed=20th?= =?UTF-8?q?ose=20annoying=2045=C2=B0=20vectors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/animations/ltn_ant.c | 46 ++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/src/animations/ltn_ant.c b/src/animations/ltn_ant.c index 049f4cc..12c8fa0 100644 --- a/src/animations/ltn_ant.c +++ b/src/animations/ltn_ant.c @@ -35,27 +35,20 @@ #define NX (UNUM_COLS - 1u) #define NY (UNUM_ROWS - 1u) -#if UNUM_ROWS == UNUM_COLS - static coord_t const dcomp[] = {0, P, NX}; - #define xdcomp dcomp - #define ydcomp dcomp -#else - static coord_t const xdcomp[] = {0, P, NX}; - static coord_t const ydcomp[] = {0, P, NY}; -#endif - +static coord_t const xdcomp[] = {0, P, 0, NX}; +static coord_t const ydcomp[] = {P, 0, NY, 0}; +typedef struct ant_s { + coord_t x, y; + coord_t ox, oy; /* Used to set old pixels to brightness 2 */ + unsigned char vector_index; +} ant_t; void ltn_ant() { clear_screen(0); - struct { - coord_t x, y; - coord_t ox, oy; /* Used to set old pixels to brightness 2 */ - coord_t dx, dy; /* Vector can only be (0,1),(1,0),(0,-1),(-1,0) */ - } ant; - - unsigned char temp; + ant_t ant; + unsigned int cycles = 500; /* Random start position and direction */ @@ -63,10 +56,7 @@ void ltn_ant() { ant.y = random8() % UNUM_ROWS; /* Make sure we do have a valid vector */ - ant.dx = xdcomp[random8() % 3]; - do { - ant.dy = ydcomp[random8() % 3]; - } while(ant.dx == ant.dy); + ant.vector_index = random8() % 4u; ant.ox = ant.x; ant.oy = ant.y; @@ -76,9 +66,8 @@ void ltn_ant() { if(get_pixel((pixel) {ant.x, ant.y}) == 0) { setpixel((pixel) {ant.x, ant.y}, 3); - temp = ant.dx; - ant.dx = ant.dy; - ant.dy = -temp; /* Turn 90 degrees to the right */ + // turn right + ant.vector_index = (ant.vector_index + 1u) % 8u; /* Lets the last pixel be darker than the latest */ if((ant.ox != ant.x) || (ant.oy != ant.y)) @@ -86,20 +75,17 @@ void ltn_ant() { ant.ox = ant.x; ant.oy = ant.y; - } else { setpixel((pixel) {ant.x, ant.y}, 0); - - temp = ant.dy; - ant.dy = ant.dx; - ant.dx = -temp; /* Turn 90 degrees to the left */ + // turn left + ant.vector_index = (ant.vector_index + 3u) % 8u; } wait(100); /* Playing field is modeled after a torus */ - ant.x = (coord_t)(ant.x + ant.dx) % UNUM_COLS; - ant.y = (coord_t)(ant.y + ant.dy) % UNUM_ROWS; + ant.x = (coord_t)(ant.x + xdcomp[ant.vector_index]) % UNUM_COLS; + ant.y = (coord_t)(ant.y + ydcomp[ant.vector_index]) % UNUM_ROWS; cycles--; } From 56a267bada11906198b182a8dab072dd9672078b Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Thu, 15 May 2014 21:20:39 +0200 Subject: [PATCH 04/28] switch to Timer0 for wait() on LoL Shield platform --- profiles/LoL-Shield | 3 ++- src/borg_hw/config_lolshield.in | 2 ++ src/util.c | 40 ++++++++++++++++++--------------- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/profiles/LoL-Shield b/profiles/LoL-Shield index 2f9ed83..343e9a9 100644 --- a/profiles/LoL-Shield +++ b/profiles/LoL-Shield @@ -19,6 +19,7 @@ BORG_HW=HW_LOLSHIELD # # lolshield setup # +USER_TIMER0_FOR_WAIT=1 # # Features @@ -26,7 +27,7 @@ BORG_HW=HW_LOLSHIELD RANDOM_SUPPORT=y # LAP_TIME_EXTENSION is not set SCROLLTEXT_SUPPORT=y -SCROLLTEXT_FONT=FONT_SMALL6 +SCROLLTEXT_FONT=FONT_C64 SCROLLTEXT_BUFFER_SIZE=128 SCROLL_X_SPEED=20 SCROLL_Y_SPEED=20 diff --git a/src/borg_hw/config_lolshield.in b/src/borg_hw/config_lolshield.in index 4695361..ceaf309 100644 --- a/src/borg_hw/config_lolshield.in +++ b/src/borg_hw/config_lolshield.in @@ -1,4 +1,6 @@ mainmenu_option next_comment comment "lolshield setup" +define_int USER_TIMER0_FOR_WAIT 1 + endmenu diff --git a/src/util.c b/src/util.c index 436cbda..bdd2a29 100644 --- a/src/util.c +++ b/src/util.c @@ -22,22 +22,19 @@ extern jmp_buf newmode_jmpbuf; void wait(int ms){ -/* TCCR2: FOC2 WGM20 COM21 COM20 WGM21 CS22 CS21 CS20 - CS22 CS21 CS20 - 0 0 0 stop - 0 0 1 clk - 0 1 0 clk/8 - 0 1 1 clk/32 - 1 0 0 clk/64 - 1 0 1 clk/128 - 1 1 0 clk/256 - 1 1 1 clk/1024 -*/ - //TCCR2 = 0x0D; //CTC Mode, clk/128 - //OCR2 = (F_CPU/128000); //1000Hz - - TCCR1B = (1<0;ms--){ @@ -61,8 +58,15 @@ void wait(int ms){ #endif #if defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__) - while(!(TIFR1&(1< Date: Sat, 17 May 2014 16:08:40 +0200 Subject: [PATCH 05/28] tuned moire pattern for LoL Shield --- src/animations/moire.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/animations/moire.c b/src/animations/moire.c index 16b0ef8..5d47cd6 100644 --- a/src/animations/moire.c +++ b/src/animations/moire.c @@ -25,8 +25,12 @@ void moire(void) { // add rotating color map -#if NUMPLANE == 3 +#if NUMPLANE == 3 && NUM_COLS == 16 && NUM_ROWS == 16 static unsigned char const gradient[] = {0, 1, 2, 3, 2, 1}; +# define WRAP 6u +#elif NUMPLANE == 3 && NUM_COLS == 14 && NUM_ROWS == 9 + static unsigned char const gradient[] = {0, 1, 1, 2, 2, 3, 3, 2, 2, 1, 1}; +# define WRAP 11u #else static unsigned char gradient[NUMPLANE * 2u] = {0}; for (unsigned char i = 1; i <= NUMPLANE; ++i) @@ -34,6 +38,7 @@ void moire(void) gradient[i] = i; gradient[(NUMPLANE * 2) - i] = i; } +# define WRAP (2u * NUMPLANE) #endif unsigned int cycles = 30000; @@ -81,7 +86,7 @@ void moire(void) wait(40); } // ensure the color index keeps within bounds - color_index %= (2u * NUMPLANE); + color_index %= WRAP; } } From 4fd59d8edf8be17978678987e9510d5c773e5317 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sat, 17 May 2014 18:08:43 +0200 Subject: [PATCH 06/28] NUM_COLS and NUM_ROWS were mixed up at some places --- src/games/breakout/playfield.c | 10 +++++----- src/games/breakout/rebound.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/games/breakout/playfield.c b/src/games/breakout/playfield.c index eeac23d..df24d32 100644 --- a/src/games/breakout/playfield.c +++ b/src/games/breakout/playfield.c @@ -67,7 +67,7 @@ static void brick_damage (int8_t in_x, int8_t in_y) void playfield_set (uint8_t in_x, uint8_t in_y, game_field_t in_field) { - if (in_x >= NUM_ROWS || in_y >= NUM_COLS) + if (in_x >= NUM_COLS || in_y >= NUM_ROWS) { return; } @@ -78,10 +78,10 @@ int8_t check_bounce (int8_t in_x, int8_t in_y) { int8_t ov = 0; /* overflow check */ - if (in_x >= NUM_ROWS || in_x < 0) + if (in_x >= NUM_COLS || in_x < 0) ov |= BOUNCE_X; - if (in_y >= NUM_COLS || in_y < 0) + if (in_y >= NUM_ROWS || in_y < 0) ov |= BOUNCE_Y; if (ov) @@ -119,9 +119,9 @@ void playfield_draw () { uint8_t x,y; - for (x=0;x Date: Sat, 17 May 2014 19:28:57 +0200 Subject: [PATCH 07/28] ltnant.c: forgot to adjust index cut off, also refined the code a bit --- src/animations/ltn_ant.c | 54 +++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/src/animations/ltn_ant.c b/src/animations/ltn_ant.c index 12c8fa0..0cf3d8f 100644 --- a/src/animations/ltn_ant.c +++ b/src/animations/ltn_ant.c @@ -35,13 +35,13 @@ #define NX (UNUM_COLS - 1u) #define NY (UNUM_ROWS - 1u) -static coord_t const xdcomp[] = {0, P, 0, NX}; -static coord_t const ydcomp[] = {P, 0, NY, 0}; +static coord_t const xdcomp[] = {0, NX, 0, P}; +static coord_t const ydcomp[] = {P, 0, NY, 0}; typedef struct ant_s { - coord_t x, y; - coord_t ox, oy; /* Used to set old pixels to brightness 2 */ - unsigned char vector_index; + coord_t x, y; /* current postion */ + coord_t ox, oy; /* previous position, used to dim out old pixels */ + unsigned char vector_index; /* index to one of (0,1),(1,0),(0,-1),(-1,0) */ } ant_t; void ltn_ant() { @@ -51,43 +51,35 @@ void ltn_ant() { unsigned int cycles = 500; - /* Random start position and direction */ - ant.x = random8() % UNUM_COLS; - ant.y = random8() % UNUM_ROWS; + /* random start position and direction */ + ant.x = ant.ox = random8() % UNUM_COLS; + ant.y = ant.oy = random8() % UNUM_ROWS; - /* Make sure we do have a valid vector */ + /* make sure we have a valid vector */ ant.vector_index = random8() % 4u; - ant.ox = ant.x; - ant.oy = ant.y; - - while(cycles != 0) { - /* If the pixel is not set turn it on */ + while(cycles--) { + /* if the pixel is turned off turn it on */ if(get_pixel((pixel) {ant.x, ant.y}) == 0) { - setpixel((pixel) {ant.x, ant.y}, 3); - - // turn right - ant.vector_index = (ant.vector_index + 1u) % 8u; - - /* Lets the last pixel be darker than the latest */ - if((ant.ox != ant.x) || (ant.oy != ant.y)) - setpixel((pixel) {ant.ox, ant.oy}, 2); + setpixel((pixel) {ant.x, ant.y}, NUMPLANE); + ant.vector_index = (ant.vector_index + 3u) % 4u; // turn left + /* dim the previous pixel */ + setpixel((pixel){ant.ox, ant.oy}, NUMPLANE - 1); + + /* memorize this position */ ant.ox = ant.x; ant.oy = ant.y; + /* if the pixel is turned on turn it off */ } else { setpixel((pixel) {ant.x, ant.y}, 0); - // turn left - ant.vector_index = (ant.vector_index + 3u) % 8u; + ant.vector_index = (ant.vector_index + 1u) % 4u; // turn right } + /* move to next pixel, playing field is modeled after a torus */ + ant.x = (ant.x + xdcomp[ant.vector_index]) % UNUM_COLS; + ant.y = (ant.y + ydcomp[ant.vector_index]) % UNUM_ROWS; + wait(100); - - /* Playing field is modeled after a torus */ - ant.x = (coord_t)(ant.x + xdcomp[ant.vector_index]) % UNUM_COLS; - ant.y = (coord_t)(ant.y + ydcomp[ant.vector_index]) % UNUM_ROWS; - - cycles--; } - wait(300); } From 8a3ecd882e2984485c2a1bc75886a9b8666753c3 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sat, 17 May 2014 19:47:41 +0200 Subject: [PATCH 08/28] blackhole.c: make animation resolution aware --- src/animations/blackhole.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/animations/blackhole.c b/src/animations/blackhole.c index 436a808..32cc5d1 100644 --- a/src/animations/blackhole.c +++ b/src/animations/blackhole.c @@ -54,7 +54,8 @@ static signed char cos_i(unsigned char const angle) { #define NUM_CIRCLE 7 - +#define W (NUM_COLS * 4) +#define H (NUM_ROWS * 4) /** * Draws a black hole like pattern (viewed from different perspectives). @@ -71,8 +72,8 @@ void blackhole(void) { for (signed char j = 0; j < 64; j += 8) { signed char a = (j & 0x08) ? 0 : 4; pixel p; - p.x = (64 + cos_i(angle + j + a) * helpRadius / 64) >> 3; - p.y = (64 + sin_i(angle + add + j + a) * helpRadius / 64) >> 3; + p.x = (W + cos_i(angle + j + a) * helpRadius / W) / 8u; + p.y = (H + sin_i(angle + add + j + a) * helpRadius / H) / 8u; if ((p.x < NUM_COLS) && (p.y < NUM_ROWS)) { setpixel(p, 3); } From 020efc3fd1464f57f4ed29d8b837b348c1e4cf96 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sat, 17 May 2014 22:20:52 +0200 Subject: [PATCH 09/28] improved spiral(...) and random_bright(...) for non-square displays --- src/animations/program.c | 76 +++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/src/animations/program.c b/src/animations/program.c index 7d0265d..56496d8 100644 --- a/src/animations/program.c +++ b/src/animations/program.c @@ -47,45 +47,32 @@ void test_palette2(){ #ifdef ANIMATION_SPIRAL -static void walk(cursor_t* cur, unsigned char steps, int delay){ - unsigned char x; - for(x=steps;x--;){ - set_cursor(cur, next_pixel(cur->pos, cur->dir)); - wait(delay); - } -} - -void spiral(int delay){ +void spiral(int delay) { clear_screen(0); + static signed char const PROGMEM delta[5] = { 0, -1, 0, 1, 0 }; + unsigned char length[2] = { NUM_ROWS, NUM_COLS - 1 }; + unsigned char x = NUM_COLS - 1, y = NUM_ROWS, i = 0; - cursor_t cur; - cur.dir = right; - cur.mode = set; - set_cursor (&cur, (pixel){NUM_COLS-1,0}); - - unsigned char clearbit=0; - while(clearbit == 0){ - - clearbit = 1; - while (!get_next_pixel(cur.pos, cur.dir)){ - clearbit = 0; - walk(&cur, 1, delay); + while (length[i & 0x01]) { + for (unsigned char j = 0; j < length[i & 0x01]; ++j) { + x += pgm_read_byte(&delta[i]); + y += pgm_read_byte(&delta[i + 1]); + setpixel((pixel){x, y}, NUMPLANE); + wait(delay); } - cur.dir = direction_r(cur.dir); + length[i++ & 0x01]--; + i %= 4; } - - cur.mode = clear; - set_cursor(&cur, (pixel){(NUM_COLS/2)-1,(NUM_ROWS/2)-1}); - - for(clearbit=0;clearbit==0;){ - if( get_next_pixel(cur.pos, direction_r(cur.dir)) ){ - cur.dir = direction_r(cur.dir); - } - if( get_next_pixel(cur.pos, cur.dir) == 1 ){ - walk(&cur , 1, delay); - }else{ - clearbit = 1; + i = (i + 2u) % 4u; + while (length[0] <= NUM_ROWS && length[1] < NUM_COLS) { + for (unsigned char j = 0; j < length[i & 0x01]; ++j) { + setpixel((pixel){x, y}, 0); + x += pgm_read_byte(&delta[i]); + y += pgm_read_byte(&delta[i + 1]); + wait(delay); } + length[(i += 3) & 0x01]++; + i %= 4; } } #endif @@ -179,17 +166,18 @@ void fire() * void random_bright(void) * by Daniel Otte */ -void random_bright(unsigned cycles){ - uint8_t t,x,y; - while(cycles--){ - for(y=0; y>0)); - setpixel((pixel){x*4+1, y}, 0x3&(t>>2)); - setpixel((pixel){x*4+2, y}, 0x3&(t>>4)); - setpixel((pixel){x*4+3, y}, 0x3&(t>>6)); +void random_bright(unsigned int cycles) { + while (cycles--) { + for (unsigned char p = NUMPLANE; p--;) { + for (unsigned char y = NUM_ROWS; y--;) { + for (unsigned char x = LINEBYTES; x--;) { + if (p < (NUMPLANE - 1)) { + pixmap[p][y][x] |= pixmap[p - 1][y][x]; + } + pixmap[p][y][x] = random8(); + } } + } wait(200); } } From 5fc8326ce61e5502a55a7b0da6b044f3b6613ec5 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sun, 18 May 2014 01:05:46 +0200 Subject: [PATCH 10/28] mherweg.c: adjustments for LoL Shield resolution --- src/animations/mherweg.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/animations/mherweg.c b/src/animations/mherweg.c index 6f56575..3e98609 100644 --- a/src/animations/mherweg.c +++ b/src/animations/mherweg.c @@ -126,21 +126,29 @@ static void movinglines() */ static void rectangle1() { + // define a sane maximum expansion +#if NUM_COLS < NUM_ROWS +# define RECT_SIZE NUM_COLS +#else +# define RECT_SIZE NUM_ROWS +#endif + // we want a centered square - unsigned char const xcenter = NUM_COLS / 2, ycenter = NUM_ROWS / 2; - // it should be as big as the borg's height - unsigned char size = NUM_ROWS; +#define RECT_OFFSET_X ((UNUM_COLS - RECT_SIZE) / 2u) +#define RECT_OFFSET_Y ((UNUM_ROWS - RECT_SIZE) / 2u) + + unsigned char size = RECT_SIZE; // darkest color as a starting point for the gradient - unsigned char color = 0; + unsigned char color = 1; // wait about 500 ms between each frame int const delay = 500; // create a gradient by drawing shrinking rectangles on top of each other clear_screen(0); - for (unsigned char x = 8; x > 0; x--) + for (unsigned char pos = 0; pos < (RECT_SIZE / 2); ++pos) { // draw the rectangle and wait for a moment - filled_rectangle((pixel){(xcenter - x), (ycenter - x)}, + filled_rectangle((pixel){pos + RECT_OFFSET_X, pos + RECT_OFFSET_Y}, size, size, color); wait(delay); From e05adbfb296af24d59baffeafafb8be193574d83 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sun, 18 May 2014 01:13:01 +0200 Subject: [PATCH 11/28] extended LoL Shield profile --- profiles/LoL-Shield | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/profiles/LoL-Shield b/profiles/LoL-Shield index 343e9a9..ee35113 100644 --- a/profiles/LoL-Shield +++ b/profiles/LoL-Shield @@ -45,7 +45,7 @@ NULL_JOYSTICK_SUPPORT=y # # Games # -# GAME_TETRIS_CORE is not set +GAME_TETRIS_CORE=y # GAME_TETRIS is not set # GAME_BASTET is not set # GAME_TETRIS_FP is not set @@ -77,7 +77,7 @@ MATRIX_STREAMER_NUM=30 MATRIX_CYCLES=500 MATRIX_DELAY=60 ANIMATION_RANDOM_BRIGHT=y -# ANIMATION_STONEFLY is not set +ANIMATION_STONEFLY=y ANIMATION_FLYINGDOTS=y ANIMATION_GAMEOFLIFE=y GOL_DELAY=100 From f65ab6eeba1593d00f2fd569aee2e1a72a86b926 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sun, 18 May 2014 02:10:07 +0200 Subject: [PATCH 12/28] First Person Tetris: trigger compile time error on non-square displays --- src/games/tetris/variant_fp.c | 3 +++ src/games/tetris/view.c | 19 ++----------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/games/tetris/variant_fp.c b/src/games/tetris/variant_fp.c index 1410485..16ea462 100644 --- a/src/games/tetris/variant_fp.c +++ b/src/games/tetris/variant_fp.c @@ -32,6 +32,9 @@ #include "variant_std.h" #include "variant_fp.h" +#if (NUM_ROWS != NUM_COLS) + #error "First Person Tetris does not support non-square displays!" +#endif /*************** * entry point * diff --git a/src/games/tetris/view.c b/src/games/tetris/view.c index 71340b9..ba542d6 100644 --- a/src/games/tetris/view.c +++ b/src/games/tetris/view.c @@ -52,23 +52,8 @@ /** color of line counter */ #define TETRIS_VIEW_COLORCOUNTER 2 - -#ifdef GAME_TETRIS_FP - #if NUM_ROWS < NUM_COLS - #define VIEWCOLS NUM_ROWS - #define VIEWROWS NUM_ROWS - #elif NUM_ROWS > NUM_COLS - #define VIEWCOLS NUM_COLS - #define VIEWROWS NUM_COLS - #else - #define VIEWCOLS NUM_COLS - #define VIEWROWS NUM_ROWS - #endif -#else - #define VIEWCOLS NUM_COLS - #define VIEWROWS NUM_ROWS -#endif - +#define VIEWCOLS NUM_COLS +#define VIEWROWS NUM_ROWS #if VIEWROWS >= 20 #define TETRIS_VIEW_YOFFSET_DUMP ((VIEWROWS - 20) / 2) From c184fcbf0fcec8c337afe3d7c321fb996def3fe0 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Mon, 19 May 2014 07:13:48 +0200 Subject: [PATCH 13/28] added support for Arduino Leonardo (and maybe Mega1280/2560, untested) --- config.in | 1 + profiles/LoL-Shield_Leonardo | 125 +++ ...d => LoL-Shield_Uno-Duemilanove-Diavolino} | 1 + src/borg_hw/borg_hw_lolshield.c | 978 ++++++++++++++---- src/borg_hw/config.in | 2 +- src/borg_hw/config_lolshield.in | 2 + src/util.c | 4 +- 7 files changed, 919 insertions(+), 194 deletions(-) create mode 100644 profiles/LoL-Shield_Leonardo rename profiles/{LoL-Shield => LoL-Shield_Uno-Duemilanove-Diavolino} (99%) diff --git a/config.in b/config.in index 809eada..61b6bf3 100644 --- a/config.in +++ b/config.in @@ -8,6 +8,7 @@ comment "General Setup" choice 'Target MCU' \ "ATmega8 atmega8 \ ATmega32 atmega32 \ + ATmega32U4 atmega32u4 \ ATmega328 atmega328 \ ATmega328p atmega328p \ ATmega644 atmega644 \ diff --git a/profiles/LoL-Shield_Leonardo b/profiles/LoL-Shield_Leonardo new file mode 100644 index 0000000..3edf168 --- /dev/null +++ b/profiles/LoL-Shield_Leonardo @@ -0,0 +1,125 @@ +# +# Automatically generated by make menuconfig: don't edit +# + +# +# General Setup +# +MCU=atmega32u4 +FREQ=16000000 + +# +# Borg Hardware +# +NUM_ROWS=9 +NUM_COLS=14 +NUMPLANE=3 +BORG_HW=HW_LOLSHIELD + +# +# lolshield setup +# +USER_TIMER0_FOR_WAIT=1 +BRIGHTNESS=127 + +# +# Features +# +RANDOM_SUPPORT=y +# LAP_TIME_EXTENSION is not set +SCROLLTEXT_SUPPORT=y +SCROLLTEXT_FONT=FONT_C64 +SCROLLTEXT_BUFFER_SIZE=128 +SCROLL_X_SPEED=20 +SCROLL_Y_SPEED=20 +SCROLLTEXT_TEXT=" #include #include +#if NUMPLANE >= 8 +# include +#endif #include "borg_hw.h" // buffer which holds the currently shown frame unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; +// Number of ticks of the prescaled timer per cycle per frame, based on the +// CPU clock speed and the desired frame rate. #define FRAMERATE 80UL +#define TICKS (F_CPU + 6 * (FRAMERATE << SLOWSCALERSHIFT)) / (12 * (FRAMERATE << SLOWSCALERSHIFT)) #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 +# if F_CPU < CUTOFF(8) +# define FASTPRESCALER (_BV(CS20)) // 1 +# define SLOWPRESCALER (_BV(CS21)) // 8 +# define FASTSCALERSHIFT 3 +# define SLOWSCALERSHIFT 3 +# elif F_CPU < CUTOFF(32) +# define FASTPRESCALER (_BV(CS21)) // 8 +# define SLOWPRESCALER (_BV(CS21) | _BV(CS20)) // 32 +# define FASTSCALERSHIFT 2 +# define SLOWSCALERSHIFT 5 +# elif F_CPU < CUTOFF(64) +# define FASTPRESCALER (_BV(CS21)) // 8 +# define SLOWPRESCALER (_BV(CS22)) // 64 +# define FASTSCALERSHIFT 3 +# define SLOWSCALERSHIFT 6 # 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 +# define FASTPRESCALER (_BV(CS21) | _BV(CS20)) // 32 +# define SLOWPRESCALER (_BV(CS22) | _BV(CS20)) // 128 +# define FASTSCALERSHIFT 2 +# define SLOWSCALERSHIFT 7 +# elif F_CPU < CUTOFF(256) +# define FASTPRESCALER (_BV(CS21) | _BV(CS20)) // 32 +# define SLOWPRESCALER (_BV(CS22) | _BV(CS21)) // 256 +# define FASTSCALERSHIFT 3 +# define SLOWSCALERSHIFT 8 # 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 +# define FASTPRESCALER (_BV(CS22) | _BV(CS20)) // 128 +# define SLOWPRESCALER (_BV(CS22) | _BV(CS21) | _BV(CS20)) // 1024 +# define FASTSCALERSHIFT 3 +# define SLOWSCALERSHIFT 10 +# else +# error frame rate is too low +# endif +#elif defined (__AVR_ATmega32U4__) +# if F_CPU < CUTOFF(8) +# define FASTPRESCALER (_BV(WGM12) | _BV(CS10)) // 1 +# define SLOWPRESCALER (_BV(WGM12) | _BV(CS11)) // 8 +# define FASTSCALERSHIFT 3 +# define SLOWSCALERSHIFT 3 +# elif F_CPU < CUTOFF(64) +# define FASTPRESCALER (_BV(WGM12) | _BV(CS11)) // 8 +# define SLOWPRESCALER (_BV(WGM12) | _BV(CS11) | _BV(CS10)) // 64 +# define FASTSCALERSHIFT 3 +# define SLOWSCALERSHIFT 6 +# elif F_CPU < CUTOFF(256) +# define FASTPRESCALER (_BV(WGM12) | _BV(CS11) | _BV(CS10)) // 64 +# define SLOWPRESCALER (_BV(WGM12) | _BV(CS12)) // 256 +# define FASTSCALERSHIFT 2 +# define SLOWSCALERSHIFT 8 +# elif F_CPU < CUTOFF(1024) +# define FASTPRESCALER (_BV(WGM12) | _BV(CS12)) // 256 +# define SLOWPRESCALER (_BV(WGM12) | _BV(CS12) | _BV(CS10)) // 1024 +# define FASTSCALERSHIFT 2 +# define SLOWSCALERSHIFT 10 +# 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 +#ifndef BRIGHTNESS +# define BRIGHTNESS 127 /* full brightness by default */ +#elif BRIGHTNESS < 0 || BRIGHTNESS > 127 +# error BRIGHTNESS must be between 0 and 127 +#endif - // 12 Cycles of Matrix - static uint8_t cycle = 0; +#define BRIGHTNESSPERCENT ((BRIGHTNESS * BRIGHTNESS + 8ul) / 16ul) +#define M (TICKS << FASTSCALERSHIFT) * BRIGHTNESSPERCENT /*10b*/ +#define C(x) ((M * (unsigned long)(x * 1024) + (1 << 19)) >> 20) /*10b+10b-20b=0b*/ - // planes to display - // NOTE: a "plane" in the Borgware is the same as a "page" in Jimmie's lib - static uint8_t plane = 0; +#if NUMPLANE < 8 +uint8_t const prescaler[NUMPLANE + 1] = { + FASTPRESCALER, +# if NUMPLANE >= 2 + FASTPRESCALER, +# endif +# if NUMPLANE >= 3 + FASTPRESCALER, +# endif +# if NUMPLANE >= 4 + FASTPRESCALER, +# endif +# if NUMPLANE >= 5 + FASTPRESCALER, +# endif +# if NUMPLANE >= 6 + FASTPRESCALER, +# endif +# if NUMPLANE >= 7 + FASTPRESCALER, +# endif + SLOWPRESCALER +}; +#else +uint8_t prescaler[NUMPLANE + 1] = {0}; +#endif +uint8_t counts[NUMPLANE + 1] = {0}; + +/** + * Set the overall brightness of the screen from 0 (off) to 127 (full on). + */ +static void setBrightness() +{ + /* ---- This needs review! Please review. -- thilo */ + // set up page counts + uint8_t i; + + // NOTE: The argument of C() is calculated as follows: + // pow((double)x / (double)NUMPLANE, 1.8) with 0 <= x <= NUMPLANE + // Changing the scale of 1.8 invalidates any tables above! +#if NUMPLANE < 8 + int const temp_counts[NUMPLANE + 1] = { + 0.000000000000000000000000000, +# if NUMPLANE == 2 + C(0.287174588749258719033719), +# elif NUMPLANE == 3 + C(0.138414548846168578011273), + C(0.481987453865643789008288), +# elif NUMPLANE == 4 + C(0.082469244423305887448095), + C(0.287174588749258719033719), + C(0.595813410589956848895099), +# elif NUMPLANE == 5 + C(0.055189186458448592775827), + C(0.192179909437029006191722), + C(0.398723883569384374148115), + C(0.669209313658414961523135), +# elif NUMPLANE == 6 + C(0.039749141141812646682574), + C(0.138414548846168578011273), + C(0.287174588749258719033719), + C(0.481987453865643789008288), + C(0.720234228706005730202833), +# elif NUMPLANE == 7 + C(0.030117819624378608378557), + C(0.104876339357015443964904), + C(0.217591430058779483625031), + C(0.365200625214741059210155), + C(0.545719579451565794947498), + C(0.757697368024318751444923), +# endif + C(1.000000000000000000000000), + }; +#else +# warning "NUMPLANE >= 8 links floating point stuff into the image" + // NOTE: Changing "scale" invalidates any tables above! + const float scale = 1.8f; + int temp_counts[NUMPLANE + 1] = {0}; + + for (i = 1; i < (NUMPLANE + 1); i++) { + temp_counts[i] = C(pow(i / (float)(NUMPLANE), scale)); + } +#endif + + // Compute on time for each of the pages + // Use the fast timer; slow timer is only useful for < 3 shades. + for (i = 0; i < NUMPLANE; i++) { + int interval = temp_counts[i + 1] - temp_counts[i]; + counts[i] = 256 - (interval ? interval : 1); +#if NUMPLANE >= 8 + prescaler[i] = FASTPRESCALER; +#endif + } + + // Compute off time + int interval = TICKS - (temp_counts[i] >> FASTSCALERSHIFT); + counts[i] = 256 - (interval ? interval : 1); +#if NUMPLANE >= 8 + prescaler[i] = SLOWPRESCALER; +#endif +} + +/** + * Distributes the framebuffer content among current cycle pins. + * @param cycle The cycle whose pattern should to be composed. + * @param plane The plane ("page" in LoL Shield lingo) to be drawn. + */ +static void compose_cycle(uint8_t const cycle, uint8_t plane) { // 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]; + uint8_t *const p = &pixmap[plane][0][0]; +#if defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) +# warning "BEWARE: Borgware-2D has not been tested on Arduino Mega 1280/2560!" // Set sink pin to Vcc/source, turning off current. - static uint8_t sink_b, sink_d = 0; + static uint8_t sink_b = 0, sink_e = 0, sink_g = 0, sink_h = 0; + PINB = sink_b; + PINE = sink_e; + PING = sink_g; + PINH = sink_h; + + DDRB &= ~0xf0; + DDRE &= ~0x38; + DDRG &= ~0x20; + DDRH &= ~0x78; + + static uint8_t const sink_b_cycle[] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0x80}; + static uint8_t const sink_e_cycle[] = + {0x10, 0x20, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static uint8_t const sink_g_cycle[] = + {0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static uint8_t const sink_h_cycle[] = + {0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00}; + + uint8_t pins_b = sink_b = pgm_read_byte(&sink_b_cycle[cycle]); + uint8_t pins_e = sink_e = pgm_read_byte(&sink_e_cycle[cycle]); + uint8_t pins_g = sink_g = pgm_read_byte(&sink_g_cycle[cycle]); + uint8_t pins_h = sink_h = pgm_read_byte(&sink_h_cycle[cycle]); + + // convert framebuffer to LoL Shield cycles on Arduino Mega 1280/2560 + // (I could have done this with a lookup table, but that would be slower as + // non-constant bit shifts are quite expensive on AVR) + // NOTE: (0,0) is UPPER RIGHT in the Borgware realm + if (plane < NUMPLANE) { + switch(cycle) { + case 0: + pins_b |= (0x02u & p[ 0]) << 6; // x= 1, y= 0, mapped pin D13 + pins_b |= (0x02u & p[ 2]) << 5; // x= 1, y= 1, mapped pin D12 + pins_b |= (0x02u & p[ 4]) << 4; // x= 1, y= 2, mapped pin D11 + pins_b |= (0x02u & p[ 6]) << 3; // x= 1, y= 3, mapped pin D10 + pins_e |= (0x02u & p[16]) << 2; // x= 1, y= 8, mapped pin D5 + pins_h |= (0x02u & p[ 8]) << 5; // x= 1, y= 4, mapped pin D9 + pins_h |= (0x02u & p[10]) << 4; // x= 1, y= 5, mapped pin D8 + pins_h |= (0x02u & p[12]) << 3; // x= 1, y= 6, mapped pin D7 + pins_h |= (0x02u & p[14]) << 2; // x= 1, y= 7, mapped pin D6 + break; + case 1: + pins_b |= (0x08u & p[ 0]) << 4; // x= 3, y= 0, mapped pin D13 + pins_b |= (0x08u & p[ 2]) << 3; // x= 3, y= 1, mapped pin D12 + pins_b |= (0x08u & p[ 4]) << 2; // x= 3, y= 2, mapped pin D11 + pins_b |= (0x08u & p[ 6]) << 1; // x= 3, y= 3, mapped pin D10 + pins_e |= (0x08u & p[16]); // x= 3, y= 8, mapped pin D5 + pins_h |= (0x08u & p[ 8]) << 3; // x= 3, y= 4, mapped pin D9 + pins_h |= (0x08u & p[10]) << 2; // x= 3, y= 5, mapped pin D8 + pins_h |= (0x08u & p[12]) << 1; // x= 3, y= 6, mapped pin D7 + pins_h |= (0x08u & p[14]); // x= 3, y= 7, mapped pin D6 + break; + case 2: + pins_b |= (0x20u & p[ 0]) << 2; // x= 5, y= 0, mapped pin D13 + pins_b |= (0x20u & p[ 2]) << 1; // x= 5, y= 1, mapped pin D12 + pins_b |= (0x20u & p[ 4]); // x= 5, y= 2, mapped pin D11 + pins_b |= (0x20u & p[ 6]) >> 1; // x= 5, y= 3, mapped pin D10 + pins_e |= (0x20u & p[16]) >> 2; // x= 5, y= 8, mapped pin D5 + pins_h |= (0x20u & p[ 8]) << 1; // x= 5, y= 4, mapped pin D9 + pins_h |= (0x20u & p[10]); // x= 5, y= 5, mapped pin D8 + pins_h |= (0x20u & p[12]) >> 1; // x= 5, y= 6, mapped pin D7 + pins_h |= (0x20u & p[14]) >> 2; // x= 5, y= 7, mapped pin D6 + break; + case 3: + pins_b |= (0x20u & p[ 1]) << 2; // x=13, y= 0, mapped pin D13 + pins_b |= (0x20u & p[ 3]) << 1; // x=13, y= 1, mapped pin D12 + pins_b |= (0x20u & p[ 5]); // x=13, y= 2, mapped pin D11 + pins_b |= (0x20u & p[ 7]) >> 1; // x=13, y= 3, mapped pin D10 + pins_e |= (0x01u & p[16]) << 4; // x= 0, y= 8, mapped pin D2 + pins_e |= (0x04u & p[16]) << 3; // x= 2, y= 8, mapped pin D3 + pins_g |= (0x10u & p[16]) << 1; // x= 4, y= 8, mapped pin D4 + pins_h |= (0x20u & p[ 9]) << 1; // x=13, y= 4, mapped pin D9 + pins_h |= (0x20u & p[11]); // x=13, y= 5, mapped pin D8 + pins_h |= (0x20u & p[13]) >> 1; // x=13, y= 6, mapped pin D7 + pins_h |= (0x20u & p[15]) >> 2; // x=13, y= 7, mapped pin D6 + break; + case 4: + pins_b |= (0x10u & p[ 1]) << 3; // x=12, y= 0, mapped pin D13 + pins_b |= (0x10u & p[ 3]) << 2; // x=12, y= 1, mapped pin D12 + pins_b |= (0x10u & p[ 5]) << 1; // x=12, y= 2, mapped pin D11 + pins_b |= (0x10u & p[ 7]); // x=12, y= 3, mapped pin D10 + pins_e |= (0x01u & p[14]) << 4; // x= 0, y= 7, mapped pin D2 + pins_e |= (0x04u & p[14]) << 3; // x= 2, y= 7, mapped pin D3 + pins_e |= (0x20u & p[17]) >> 2; // x=13, y= 8, mapped pin D5 + pins_g |= (0x10u & p[14]) << 1; // x= 4, y= 7, mapped pin D4 + pins_h |= (0x10u & p[ 9]) << 2; // x=12, y= 4, mapped pin D9 + pins_h |= (0x10u & p[11]) << 1; // x=12, y= 5, mapped pin D8 + pins_h |= (0x10u & p[13]); // x=12, y= 6, mapped pin D7 + break; + case 5: + pins_b |= (0x08u & p[ 1]) << 4; // x=11, y= 0, mapped pin D13 + pins_b |= (0x08u & p[ 3]) << 3; // x=11, y= 1, mapped pin D12 + pins_b |= (0x08u & p[ 5]) << 2; // x=11, y= 2, mapped pin D11 + pins_b |= (0x08u & p[ 7]) << 1; // x=11, y= 3, mapped pin D10 + pins_e |= (0x01u & p[12]) << 4; // x= 0, y= 6, mapped pin D2 + pins_e |= (0x04u & p[12]) << 3; // x= 2, y= 6, mapped pin D3 + pins_e |= (0x10u & p[17]) >> 1; // x=12, y= 8, mapped pin D5 + pins_g |= (0x10u & p[12]) << 1; // x= 4, y= 6, mapped pin D4 + pins_h |= (0x08u & p[ 9]) << 3; // x=11, y= 4, mapped pin D9 + pins_h |= (0x08u & p[11]) << 2; // x=11, y= 5, mapped pin D8 + pins_h |= (0x10u & p[15]) >> 1; // x=12, y= 7, mapped pin D6 + break; + case 6: + pins_b |= (0x04u & p[ 1]) << 5; // x=10, y= 0, mapped pin D13 + pins_b |= (0x04u & p[ 3]) << 4; // x=10, y= 1, mapped pin D12 + pins_b |= (0x04u & p[ 5]) << 3; // x=10, y= 2, mapped pin D11 + pins_b |= (0x04u & p[ 7]) << 2; // x=10, y= 3, mapped pin D10 + pins_e |= (0x01u & p[10]) << 4; // x= 0, y= 5, mapped pin D2 + pins_e |= (0x04u & p[10]) << 3; // x= 2, y= 5, mapped pin D3 + pins_e |= (0x08u & p[17]); // x=11, y= 8, mapped pin D5 + pins_g |= (0x10u & p[10]) << 1; // x= 4, y= 5, mapped pin D4 + pins_h |= (0x04u & p[ 9]) << 4; // x=10, y= 4, mapped pin D9 + pins_h |= (0x08u & p[13]) << 1; // x=11, y= 6, mapped pin D7 + pins_h |= (0x08u & p[15]); // x=11, y= 7, mapped pin D6 + break; + case 7: + pins_b |= (0x02u & p[ 1]) << 6; // x= 9, y= 0, mapped pin D13 + pins_b |= (0x02u & p[ 3]) << 5; // x= 9, y= 1, mapped pin D12 + pins_b |= (0x02u & p[ 5]) << 4; // x= 9, y= 2, mapped pin D11 + pins_b |= (0x02u & p[ 7]) << 3; // x= 9, y= 3, mapped pin D10 + pins_e |= (0x01u & p[ 8]) << 4; // x= 0, y= 4, mapped pin D2 + pins_e |= (0x04u & p[ 8]) << 3; // x= 2, y= 4, mapped pin D3 + pins_e |= (0x04u & p[17]) << 1; // x=10, y= 8, mapped pin D5 + pins_g |= (0x10u & p[ 8]) << 1; // x= 4, y= 4, mapped pin D4 + pins_h |= (0x04u & p[11]) << 3; // x=10, y= 5, mapped pin D8 + pins_h |= (0x04u & p[13]) << 2; // x=10, y= 6, mapped pin D7 + pins_h |= (0x04u & p[15]) << 1; // x=10, y= 7, mapped pin D6 + break; + case 8: + pins_b |= (0x01u & p[ 1]) << 7; // x= 8, y= 0, mapped pin D13 + pins_b |= (0x01u & p[ 3]) << 6; // x= 8, y= 1, mapped pin D12 + pins_b |= (0x01u & p[ 5]) << 5; // x= 8, y= 2, mapped pin D11 + pins_e |= (0x01u & p[ 6]) << 4; // x= 0, y= 3, mapped pin D2 + pins_e |= (0x02u & p[17]) << 2; // x= 9, y= 8, mapped pin D5 + pins_e |= (0x04u & p[ 6]) << 3; // x= 2, y= 3, mapped pin D3 + pins_g |= (0x10u & p[ 6]) << 1; // x= 4, y= 3, mapped pin D4 + pins_h |= (0x02u & p[ 9]) << 5; // x= 9, y= 4, mapped pin D9 + pins_h |= (0x02u & p[11]) << 4; // x= 9, y= 5, mapped pin D8 + pins_h |= (0x02u & p[13]) << 3; // x= 9, y= 6, mapped pin D7 + pins_h |= (0x02u & p[15]) << 2; // x= 9, y= 7, mapped pin D6 + break; + case 9: + pins_b |= (0x01u & p[ 7]) << 4; // x= 8, y= 3, mapped pin D10 + pins_b |= (0x80u & p[ 0]); // x= 7, y= 0, mapped pin D13 + pins_b |= (0x80u & p[ 2]) >> 1; // x= 7, y= 1, mapped pin D12 + pins_e |= (0x01u & p[ 4]) << 4; // x= 0, y= 2, mapped pin D2 + pins_e |= (0x01u & p[17]) << 3; // x= 8, y= 8, mapped pin D5 + pins_e |= (0x04u & p[ 4]) << 3; // x= 2, y= 2, mapped pin D3 + pins_g |= (0x10u & p[ 4]) << 1; // x= 4, y= 2, mapped pin D4 + pins_h |= (0x01u & p[ 9]) << 6; // x= 8, y= 4, mapped pin D9 + pins_h |= (0x01u & p[11]) << 5; // x= 8, y= 5, mapped pin D8 + pins_h |= (0x01u & p[13]) << 4; // x= 8, y= 6, mapped pin D7 + pins_h |= (0x01u & p[15]) << 3; // x= 8, y= 7, mapped pin D6 + break; + case 10: + pins_b |= (0x40u & p[ 0]) << 1; // x= 6, y= 0, mapped pin D13 + pins_b |= (0x80u & p[ 4]) >> 2; // x= 7, y= 2, mapped pin D11 + pins_b |= (0x80u & p[ 6]) >> 3; // x= 7, y= 3, mapped pin D10 + pins_e |= (0x01u & p[ 2]) << 4; // x= 0, y= 1, mapped pin D2 + pins_e |= (0x04u & p[ 2]) << 3; // x= 2, y= 1, mapped pin D3 + pins_e |= (0x80u & p[16]) >> 4; // x= 7, y= 8, mapped pin D5 + pins_g |= (0x10u & p[ 2]) << 1; // x= 4, y= 1, mapped pin D4 + pins_h |= (0x80u & p[ 8]) >> 1; // x= 7, y= 4, mapped pin D9 + pins_h |= (0x80u & p[10]) >> 2; // x= 7, y= 5, mapped pin D8 + pins_h |= (0x80u & p[12]) >> 3; // x= 7, y= 6, mapped pin D7 + pins_h |= (0x80u & p[14]) >> 4; // x= 7, y= 7, mapped pin D6 + break; + case 11: + pins_b |= (0x40u & p[ 2]); // x= 6, y= 1, mapped pin D12 + pins_b |= (0x40u & p[ 4]) >> 1; // x= 6, y= 2, mapped pin D11 + pins_b |= (0x40u & p[ 6]) >> 2; // x= 6, y= 3, mapped pin D10 + pins_e |= (0x01u & p[ 0]) << 4; // x= 0, y= 0, mapped pin D2 + pins_e |= (0x04u & p[ 0]) << 3; // x= 2, y= 0, mapped pin D3 + pins_e |= (0x40u & p[16]) >> 3; // x= 6, y= 8, mapped pin D5 + pins_g |= (0x10u & p[ 0]) << 1; // x= 4, y= 0, mapped pin D4 + pins_h |= (0x40u & p[ 8]); // x= 6, y= 4, mapped pin D9 + pins_h |= (0x40u & p[10]) >> 1; // x= 6, y= 5, mapped pin D8 + pins_h |= (0x40u & p[12]) >> 2; // x= 6, y= 6, mapped pin D7 + pins_h |= (0x40u & p[14]) >> 3; // x= 6, y= 7, mapped pin D6 + break; + } + } + + // Enable pullups (by toggling) on new output pins. + PINB = PORTB ^ pins_b; + PINE = PORTE ^ pins_e; + PING = PORTG ^ pins_g; + PINH = PORTH ^ pins_h; + + // Set pins to output mode; pullups become Vcc/source. + DDRB |= pins_b; + DDRE |= pins_e; + DDRG |= pins_g; + DDRH |= pins_h; + + // Set sink pin to GND/sink, turning on current. + PINB = sink_b; + PINE = sink_e; + PING = sink_g; + PINH = sink_h; +#elif defined (__AVR_ATmega32U4__) + // Set sink pin to Vcc/source, turning off current. + static uint8_t sink_b = 0, sink_c = 0, sink_d = 0, sink_e = 0; + PINB = sink_b; + PINC = sink_c; + PIND = sink_d; + PINE = sink_e; + + DDRB &= ~0xF0; + DDRC &= ~0xC0; + DDRD &= ~0xD3; + DDRE &= ~0x40; + + static uint8_t const PROGMEM sink_b_cycle[] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00}; + static uint8_t const PROGMEM sink_c_cycle[] = + {0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}; + static uint8_t const PROGMEM sink_d_cycle[] = + {0x02, 0x01, 0x10, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00}; + static uint8_t const PROGMEM sink_e_cycle[] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + uint8_t pins_b = sink_b = pgm_read_byte(&sink_b_cycle[cycle]); + uint8_t pins_c = sink_c = pgm_read_byte(&sink_c_cycle[cycle]); + uint8_t pins_d = sink_d = pgm_read_byte(&sink_d_cycle[cycle]); + uint8_t pins_e = sink_e = pgm_read_byte(&sink_e_cycle[cycle]); + + // convert Borgware-2D framebuffer to LoL Shield cycles on Arduino Leonardo + // (I could have done this with a lookup table, but that would be slower as + // non-constant bit shifts are quite expensive on AVR) + // NOTE: (0,0) is UPPER RIGHT in the Borgware realm + if (plane < NUMPLANE) { + switch(cycle) { + case 0: + pins_b |= (0x02u & p[ 4]) << 6; // x= 1, y= 2, mapped pin D11 + pins_b |= (0x02u & p[ 6]) << 5; // x= 1, y= 3, mapped pin D10 + pins_b |= (0x02u & p[ 8]) << 4; // x= 1, y= 4, mapped pin D9 + pins_b |= (0x02u & p[10]) << 3; // x= 1, y= 5, mapped pin D8 + pins_c |= (0x02u & p[ 0]) << 6; // x= 1, y= 0, mapped pin D13 + pins_c |= (0x02u & p[16]) << 5; // x= 1, y= 8, mapped pin D5 + pins_d |= (0x02u & p[ 2]) << 5; // x= 1, y= 1, mapped pin D12 + pins_d |= (0x02u & p[14]) << 6; // x= 1, y= 7, mapped pin D6 + pins_e |= (0x02u & p[12]) << 5; // x= 1, y= 6, mapped pin D7 + break; + case 1: + pins_b |= (0x08u & p[ 4]) << 4; // x= 3, y= 2, mapped pin D11 + pins_b |= (0x08u & p[ 6]) << 3; // x= 3, y= 3, mapped pin D10 + pins_b |= (0x08u & p[ 8]) << 2; // x= 3, y= 4, mapped pin D9 + pins_b |= (0x08u & p[10]) << 1; // x= 3, y= 5, mapped pin D8 + pins_c |= (0x08u & p[ 0]) << 4; // x= 3, y= 0, mapped pin D13 + pins_c |= (0x08u & p[16]) << 3; // x= 3, y= 8, mapped pin D5 + pins_d |= (0x08u & p[ 2]) << 3; // x= 3, y= 1, mapped pin D12 + pins_d |= (0x08u & p[14]) << 4; // x= 3, y= 7, mapped pin D6 + pins_e |= (0x08u & p[12]) << 3; // x= 3, y= 6, mapped pin D7 + break; + case 2: + pins_b |= (0x20u & p[ 4]) << 2; // x= 5, y= 2, mapped pin D11 + pins_b |= (0x20u & p[ 6]) << 1; // x= 5, y= 3, mapped pin D10 + pins_b |= (0x20u & p[ 8]); // x= 5, y= 4, mapped pin D9 + pins_b |= (0x20u & p[10]) >> 1; // x= 5, y= 5, mapped pin D8 + pins_c |= (0x20u & p[ 0]) << 2; // x= 5, y= 0, mapped pin D13 + pins_c |= (0x20u & p[16]) << 1; // x= 5, y= 8, mapped pin D5 + pins_d |= (0x20u & p[ 2]) << 1; // x= 5, y= 1, mapped pin D12 + pins_d |= (0x20u & p[14]) << 2; // x= 5, y= 7, mapped pin D6 + pins_e |= (0x20u & p[12]) << 1; // x= 5, y= 6, mapped pin D7 + break; + case 3: + pins_b |= (0x20u & p[ 5]) << 2; // x=13, y= 2, mapped pin D11 + pins_b |= (0x20u & p[ 7]) << 1; // x=13, y= 3, mapped pin D10 + pins_b |= (0x20u & p[ 9]); // x=13, y= 4, mapped pin D9 + pins_b |= (0x20u & p[11]) >> 1; // x=13, y= 5, mapped pin D8 + pins_c |= (0x20u & p[ 1]) << 2; // x=13, y= 0, mapped pin D13 + pins_d |= (0x01u & p[16]) << 1; // x= 0, y= 8, mapped pin D2 + pins_d |= (0x04u & p[16]) >> 2; // x= 2, y= 8, mapped pin D3 + pins_d |= (0x10u & p[16]); // x= 4, y= 8, mapped pin D4 + pins_d |= (0x20u & p[ 3]) << 1; // x=13, y= 1, mapped pin D12 + pins_d |= (0x20u & p[15]) << 2; // x=13, y= 7, mapped pin D6 + pins_e |= (0x20u & p[13]) << 1; // x=13, y= 6, mapped pin D7 + break; + case 4: + pins_b |= (0x10u & p[ 5]) << 3; // x=12, y= 2, mapped pin D11 + pins_b |= (0x10u & p[ 7]) << 2; // x=12, y= 3, mapped pin D10 + pins_b |= (0x10u & p[ 9]) << 1; // x=12, y= 4, mapped pin D9 + pins_b |= (0x10u & p[11]); // x=12, y= 5, mapped pin D8 + pins_c |= (0x10u & p[ 1]) << 3; // x=12, y= 0, mapped pin D13 + pins_c |= (0x20u & p[17]) << 1; // x=13, y= 8, mapped pin D5 + pins_d |= (0x01u & p[14]) << 1; // x= 0, y= 7, mapped pin D2 + pins_d |= (0x04u & p[14]) >> 2; // x= 2, y= 7, mapped pin D3 + pins_d |= (0x10u & p[ 3]) << 2; // x=12, y= 1, mapped pin D12 + pins_d |= (0x10u & p[14]); // x= 4, y= 7, mapped pin D4 + pins_e |= (0x10u & p[13]) << 2; // x=12, y= 6, mapped pin D7 + break; + case 5: + pins_b |= (0x08u & p[ 5]) << 4; // x=11, y= 2, mapped pin D11 + pins_b |= (0x08u & p[ 7]) << 3; // x=11, y= 3, mapped pin D10 + pins_b |= (0x08u & p[ 9]) << 2; // x=11, y= 4, mapped pin D9 + pins_b |= (0x08u & p[11]) << 1; // x=11, y= 5, mapped pin D8 + pins_c |= (0x08u & p[ 1]) << 4; // x=11, y= 0, mapped pin D13 + pins_c |= (0x10u & p[17]) << 2; // x=12, y= 8, mapped pin D5 + pins_d |= (0x01u & p[12]) << 1; // x= 0, y= 6, mapped pin D2 + pins_d |= (0x04u & p[12]) >> 2; // x= 2, y= 6, mapped pin D3 + pins_d |= (0x08u & p[ 3]) << 3; // x=11, y= 1, mapped pin D12 + pins_d |= (0x10u & p[12]); // x= 4, y= 6, mapped pin D4 + pins_d |= (0x10u & p[15]) << 3; // x=12, y= 7, mapped pin D6 + break; + case 6: + pins_b |= (0x04u & p[ 5]) << 5; // x=10, y= 2, mapped pin D11 + pins_b |= (0x04u & p[ 7]) << 4; // x=10, y= 3, mapped pin D10 + pins_b |= (0x04u & p[ 9]) << 3; // x=10, y= 4, mapped pin D9 + pins_c |= (0x04u & p[ 1]) << 5; // x=10, y= 0, mapped pin D13 + pins_c |= (0x08u & p[17]) << 3; // x=11, y= 8, mapped pin D5 + pins_d |= (0x01u & p[10]) << 1; // x= 0, y= 5, mapped pin D2 + pins_d |= (0x04u & p[ 3]) << 4; // x=10, y= 1, mapped pin D12 + pins_d |= (0x04u & p[10]) >> 2; // x= 2, y= 5, mapped pin D3 + pins_d |= (0x08u & p[15]) << 4; // x=11, y= 7, mapped pin D6 + pins_d |= (0x10u & p[10]); // x= 4, y= 5, mapped pin D4 + pins_e |= (0x08u & p[13]) << 3; // x=11, y= 6, mapped pin D7 + break; + case 7: + pins_b |= (0x02u & p[ 5]) << 6; // x= 9, y= 2, mapped pin D11 + pins_b |= (0x02u & p[ 7]) << 5; // x= 9, y= 3, mapped pin D10 + pins_b |= (0x04u & p[11]) << 2; // x=10, y= 5, mapped pin D8 + pins_c |= (0x02u & p[ 1]) << 6; // x= 9, y= 0, mapped pin D13 + pins_c |= (0x04u & p[17]) << 4; // x=10, y= 8, mapped pin D5 + pins_d |= (0x01u & p[ 8]) << 1; // x= 0, y= 4, mapped pin D2 + pins_d |= (0x02u & p[ 3]) << 5; // x= 9, y= 1, mapped pin D12 + pins_d |= (0x04u & p[ 8]) >> 2; // x= 2, y= 4, mapped pin D3 + pins_d |= (0x04u & p[15]) << 5; // x=10, y= 7, mapped pin D6 + pins_d |= (0x10u & p[ 8]); // x= 4, y= 4, mapped pin D4 + pins_e |= (0x04u & p[13]) << 4; // x=10, y= 6, mapped pin D7 + break; + case 8: + pins_b |= (0x01u & p[ 5]) << 7; // x= 8, y= 2, mapped pin D11 + pins_b |= (0x02u & p[ 9]) << 4; // x= 9, y= 4, mapped pin D9 + pins_b |= (0x02u & p[11]) << 3; // x= 9, y= 5, mapped pin D8 + pins_c |= (0x01u & p[ 1]) << 7; // x= 8, y= 0, mapped pin D13 + pins_c |= (0x02u & p[17]) << 5; // x= 9, y= 8, mapped pin D5 + pins_d |= (0x01u & p[ 3]) << 6; // x= 8, y= 1, mapped pin D12 + pins_d |= (0x01u & p[ 6]) << 1; // x= 0, y= 3, mapped pin D2 + pins_d |= (0x02u & p[15]) << 6; // x= 9, y= 7, mapped pin D6 + pins_d |= (0x04u & p[ 6]) >> 2; // x= 2, y= 3, mapped pin D3 + pins_d |= (0x10u & p[ 6]); // x= 4, y= 3, mapped pin D4 + pins_e |= (0x02u & p[13]) << 5; // x= 9, y= 6, mapped pin D7 + break; + case 9: + pins_b |= (0x01u & p[ 7]) << 6; // x= 8, y= 3, mapped pin D10 + pins_b |= (0x01u & p[ 9]) << 5; // x= 8, y= 4, mapped pin D9 + pins_b |= (0x01u & p[11]) << 4; // x= 8, y= 5, mapped pin D8 + pins_c |= (0x01u & p[17]) << 6; // x= 8, y= 8, mapped pin D5 + pins_c |= (0x80u & p[ 0]); // x= 7, y= 0, mapped pin D13 + pins_d |= (0x01u & p[ 4]) << 1; // x= 0, y= 2, mapped pin D2 + pins_d |= (0x01u & p[15]) << 7; // x= 8, y= 7, mapped pin D6 + pins_d |= (0x04u & p[ 4]) >> 2; // x= 2, y= 2, mapped pin D3 + pins_d |= (0x10u & p[ 4]); // x= 4, y= 2, mapped pin D4 + pins_d |= (0x80u & p[ 2]) >> 1; // x= 7, y= 1, mapped pin D12 + pins_e |= (0x01u & p[13]) << 6; // x= 8, y= 6, mapped pin D7 + break; + case 10: + pins_b |= (0x80u & p[ 4]); // x= 7, y= 2, mapped pin D11 + pins_b |= (0x80u & p[ 6]) >> 1; // x= 7, y= 3, mapped pin D10 + pins_b |= (0x80u & p[ 8]) >> 2; // x= 7, y= 4, mapped pin D9 + pins_b |= (0x80u & p[10]) >> 3; // x= 7, y= 5, mapped pin D8 + pins_c |= (0x40u & p[ 0]) << 1; // x= 6, y= 0, mapped pin D13 + pins_c |= (0x80u & p[16]) >> 1; // x= 7, y= 8, mapped pin D5 + pins_d |= (0x01u & p[ 2]) << 1; // x= 0, y= 1, mapped pin D2 + pins_d |= (0x04u & p[ 2]) >> 2; // x= 2, y= 1, mapped pin D3 + pins_d |= (0x10u & p[ 2]); // x= 4, y= 1, mapped pin D4 + pins_d |= (0x80u & p[14]); // x= 7, y= 7, mapped pin D6 + pins_e |= (0x80u & p[12]) >> 1; // x= 7, y= 6, mapped pin D7 + break; + case 11: + pins_b |= (0x40u & p[ 4]) << 1; // x= 6, y= 2, mapped pin D11 + pins_b |= (0x40u & p[ 6]); // x= 6, y= 3, mapped pin D10 + pins_b |= (0x40u & p[ 8]) >> 1; // x= 6, y= 4, mapped pin D9 + pins_b |= (0x40u & p[10]) >> 2; // x= 6, y= 5, mapped pin D8 + pins_c |= (0x40u & p[16]); // x= 6, y= 8, mapped pin D5 + pins_d |= (0x01u & p[ 0]) << 1; // x= 0, y= 0, mapped pin D2 + pins_d |= (0x04u & p[ 0]) >> 2; // x= 2, y= 0, mapped pin D3 + pins_d |= (0x10u & p[ 0]); // x= 4, y= 0, mapped pin D4 + pins_d |= (0x40u & p[ 2]); // x= 6, y= 1, mapped pin D12 + pins_d |= (0x40u & p[14]) << 1; // x= 6, y= 7, mapped pin D6 + pins_e |= (0x40u & p[12]); // x= 6, y= 6, mapped pin D7 + break; + } + } + + // Enable pullups (by toggling) on new output pins. + PINB = PORTB ^ pins_b; + PINC = PORTC ^ pins_c; + PIND = PORTD ^ pins_d; + PINE = PORTE ^ pins_e; + + // Set pins to output mode; pullups become Vcc/source. + DDRB |= pins_b; + DDRC |= pins_c; + DDRD |= pins_d; + DDRE |= pins_e; + + // Set sink pin to GND/sink, turning on current. + PINB = sink_b; + PINC = sink_c; + PIND = sink_d; + PINE = sink_e; +#else + // Set sink pin to Vcc/source, turning off current. + static uint8_t sink_b = 0, sink_d = 0; PIND = sink_d; PINB = sink_b; @@ -114,168 +650,169 @@ ISR(TIMER2_OVF_vect) { DDRD = 0; DDRB = 0; - static uint8_t const sink_d_cycle[] = + static uint8_t const PROGMEM sink_d_cycle[] = {0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - static uint8_t const sink_b_cycle[] = + static uint8_t const PROGMEM 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]; + uint8_t pins_d = sink_d = pgm_read_byte(&sink_d_cycle[cycle]); + uint8_t pins_b = sink_b = pgm_read_byte(&sink_b_cycle[cycle]); - // convert Borgware-2D framebuffer to LoL Shield cycles + // convert Borgware-2D framebuffer to LoL Shield cycles on Diavolino // (I could have done this with a lookup table, but that would be slower as // non-constant bit shifts are quite expensive on AVR) + // NOTE: (0,0) is UPPER RIGHT in the Borgware realm 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 + pins_b |= (0x02u & p[ 0]) << 4; // x= 1, y= 0, mapped pin D13 + pins_b |= (0x02u & p[ 2]) << 3; // x= 1, y= 1, mapped pin D12 + pins_b |= (0x02u & p[ 4]) << 2; // x= 1, y= 2, mapped pin D11 + pins_b |= (0x02u & p[ 6]) << 1; // x= 1, y= 3, mapped pin D10 + pins_b |= (0x02u & p[ 8]); // x= 1, y= 4, mapped pin D9 + pins_b |= (0x02u & p[10]) >> 1; // x= 1, y= 5, mapped pin D8 + pins_d |= (0x02u & p[12]) << 6; // x= 1, y= 6, mapped pin D7 + pins_d |= (0x02u & p[14]) << 5; // x= 1, y= 7, mapped pin D6 + pins_d |= (0x02u & p[16]) << 4; // x= 1, y= 8, mapped pin D5 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 + pins_b |= (0x08u & p[ 0]) << 2; // x= 3, y= 0, mapped pin D13 + pins_b |= (0x08u & p[ 2]) << 1; // x= 3, y= 1, mapped pin D12 + pins_b |= (0x08u & p[ 4]); // x= 3, y= 2, mapped pin D11 + pins_b |= (0x08u & p[ 6]) >> 1; // x= 3, y= 3, mapped pin D10 + pins_b |= (0x08u & p[ 8]) >> 2; // x= 3, y= 4, mapped pin D9 + pins_b |= (0x08u & p[10]) >> 3; // x= 3, y= 5, mapped pin D8 + pins_d |= (0x08u & p[12]) << 4; // x= 3, y= 6, mapped pin D7 + pins_d |= (0x08u & p[14]) << 3; // x= 3, y= 7, mapped pin D6 + pins_d |= (0x08u & p[16]) << 2; // x= 3, y= 8, mapped pin D5 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 + pins_b |= (0x20u & p[ 0]); // x= 5, y= 0, mapped pin D13 + pins_b |= (0x20u & p[ 2]) >> 1; // x= 5, y= 1, mapped pin D12 + pins_b |= (0x20u & p[ 4]) >> 2; // x= 5, y= 2, mapped pin D11 + pins_b |= (0x20u & p[ 6]) >> 3; // x= 5, y= 3, mapped pin D10 + pins_b |= (0x20u & p[ 8]) >> 4; // x= 5, y= 4, mapped pin D9 + pins_b |= (0x20u & p[10]) >> 5; // x= 5, y= 5, mapped pin D8 + pins_d |= (0x20u & p[12]) << 2; // x= 5, y= 6, mapped pin D7 + pins_d |= (0x20u & p[14]) << 1; // x= 5, y= 7, mapped pin D6 + pins_d |= (0x20u & p[16]); // x= 5, y= 8, mapped pin D5 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 + pins_b |= (0x20u & p[ 1]); // x=13, y= 0, mapped pin D13 + pins_b |= (0x20u & p[ 3]) >> 1; // x=13, y= 1, mapped pin D12 + pins_b |= (0x20u & p[ 5]) >> 2; // x=13, y= 2, mapped pin D11 + pins_b |= (0x20u & p[ 7]) >> 3; // x=13, y= 3, mapped pin D10 + pins_b |= (0x20u & p[ 9]) >> 4; // x=13, y= 4, mapped pin D9 + pins_b |= (0x20u & p[11]) >> 5; // x=13, y= 5, mapped pin D8 + pins_d |= (0x01u & p[16]) << 2; // x= 0, y= 8, mapped pin D2 + pins_d |= (0x04u & p[16]) << 1; // x= 2, y= 8, mapped pin D3 + pins_d |= (0x10u & p[16]); // x= 4, y= 8, mapped pin D4 + pins_d |= (0x20u & p[13]) << 2; // x=13, y= 6, mapped pin D7 + pins_d |= (0x20u & p[15]) << 1; // x=13, y= 7, mapped pin D6 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 + pins_b |= (0x10u & p[ 1]) << 1; // x=12, y= 0, mapped pin D13 + pins_b |= (0x10u & p[ 3]); // x=12, y= 1, mapped pin D12 + pins_b |= (0x10u & p[ 5]) >> 1; // x=12, y= 2, mapped pin D11 + pins_b |= (0x10u & p[ 7]) >> 2; // x=12, y= 3, mapped pin D10 + pins_b |= (0x10u & p[ 9]) >> 3; // x=12, y= 4, mapped pin D9 + pins_b |= (0x10u & p[11]) >> 4; // x=12, y= 5, mapped pin D8 + pins_d |= (0x01u & p[14]) << 2; // x= 0, y= 7, mapped pin D2 + pins_d |= (0x04u & p[14]) << 1; // x= 2, y= 7, mapped pin D3 + pins_d |= (0x10u & p[13]) << 3; // x=12, y= 6, mapped pin D7 + pins_d |= (0x10u & p[14]); // x= 4, y= 7, mapped pin D4 + pins_d |= (0x20u & p[17]); // x=13, y= 8, mapped pin D5 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 + pins_b |= (0x08u & p[ 1]) << 2; // x=11, y= 0, mapped pin D13 + pins_b |= (0x08u & p[ 3]) << 1; // x=11, y= 1, mapped pin D12 + pins_b |= (0x08u & p[ 5]); // x=11, y= 2, mapped pin D11 + pins_b |= (0x08u & p[ 7]) >> 1; // x=11, y= 3, mapped pin D10 + pins_b |= (0x08u & p[ 9]) >> 2; // x=11, y= 4, mapped pin D9 + pins_b |= (0x08u & p[11]) >> 3; // x=11, y= 5, mapped pin D8 + pins_d |= (0x01u & p[12]) << 2; // x= 0, y= 6, mapped pin D2 + pins_d |= (0x04u & p[12]) << 1; // x= 2, y= 6, mapped pin D3 + pins_d |= (0x10u & p[12]); // x= 4, y= 6, mapped pin D4 + pins_d |= (0x10u & p[15]) << 2; // x=12, y= 7, mapped pin D6 + pins_d |= (0x10u & p[17]) << 1; // x=12, y= 8, mapped pin D5 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 + pins_b |= (0x04u & p[ 1]) << 3; // x=10, y= 0, mapped pin D13 + pins_b |= (0x04u & p[ 3]) << 2; // x=10, y= 1, mapped pin D12 + pins_b |= (0x04u & p[ 5]) << 1; // x=10, y= 2, mapped pin D11 + pins_b |= (0x04u & p[ 7]); // x=10, y= 3, mapped pin D10 + pins_b |= (0x04u & p[ 9]) >> 1; // x=10, y= 4, mapped pin D9 + pins_d |= (0x01u & p[10]) << 2; // x= 0, y= 5, mapped pin D2 + pins_d |= (0x04u & p[10]) << 1; // x= 2, y= 5, mapped pin D3 + pins_d |= (0x08u & p[13]) << 4; // x=11, y= 6, mapped pin D7 + pins_d |= (0x08u & p[15]) << 3; // x=11, y= 7, mapped pin D6 + pins_d |= (0x08u & p[17]) << 2; // x=11, y= 8, mapped pin D5 + pins_d |= (0x10u & p[10]); // x= 4, y= 5, mapped pin D4 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 + pins_b |= (0x02u & p[ 1]) << 4; // x= 9, y= 0, mapped pin D13 + pins_b |= (0x02u & p[ 3]) << 3; // x= 9, y= 1, mapped pin D12 + pins_b |= (0x02u & p[ 5]) << 2; // x= 9, y= 2, mapped pin D11 + pins_b |= (0x02u & p[ 7]) << 1; // x= 9, y= 3, mapped pin D10 + pins_b |= (0x04u & p[11]) >> 2; // x=10, y= 5, mapped pin D8 + pins_d |= (0x01u & p[ 8]) << 2; // x= 0, y= 4, mapped pin D2 + pins_d |= (0x04u & p[ 8]) << 1; // x= 2, y= 4, mapped pin D3 + pins_d |= (0x04u & p[13]) << 5; // x=10, y= 6, mapped pin D7 + pins_d |= (0x04u & p[15]) << 4; // x=10, y= 7, mapped pin D6 + pins_d |= (0x04u & p[17]) << 3; // x=10, y= 8, mapped pin D5 + pins_d |= (0x10u & p[ 8]); // x= 4, y= 4, mapped pin D4 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 + pins_b |= (0x01u & p[ 1]) << 5; // x= 8, y= 0, mapped pin D13 + pins_b |= (0x01u & p[ 3]) << 4; // x= 8, y= 1, mapped pin D12 + pins_b |= (0x01u & p[ 5]) << 3; // x= 8, y= 2, mapped pin D11 + pins_b |= (0x02u & p[ 9]); // x= 9, y= 4, mapped pin D9 + pins_b |= (0x02u & p[11]) >> 1; // x= 9, y= 5, mapped pin D8 + pins_d |= (0x01u & p[ 6]) << 2; // x= 0, y= 3, mapped pin D2 + pins_d |= (0x02u & p[13]) << 6; // x= 9, y= 6, mapped pin D7 + pins_d |= (0x02u & p[15]) << 5; // x= 9, y= 7, mapped pin D6 + pins_d |= (0x02u & p[17]) << 4; // x= 9, y= 8, mapped pin D5 + pins_d |= (0x04u & p[ 6]) << 1; // x= 2, y= 3, mapped pin D3 + pins_d |= (0x10u & p[ 6]); // x= 4, y= 3, mapped pin D4 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 + pins_b |= (0x01u & p[ 7]) << 2; // x= 8, y= 3, mapped pin D10 + pins_b |= (0x01u & p[ 9]) << 1; // x= 8, y= 4, mapped pin D9 + pins_b |= (0x01u & p[11]); // x= 8, y= 5, mapped pin D8 + pins_b |= (0x80u & p[ 0]) >> 2; // x= 7, y= 0, mapped pin D13 + pins_b |= (0x80u & p[ 2]) >> 3; // x= 7, y= 1, mapped pin D12 + pins_d |= (0x01u & p[ 4]) << 2; // x= 0, y= 2, mapped pin D2 + pins_d |= (0x01u & p[13]) << 7; // x= 8, y= 6, mapped pin D7 + pins_d |= (0x01u & p[15]) << 6; // x= 8, y= 7, mapped pin D6 + pins_d |= (0x01u & p[17]) << 5; // x= 8, y= 8, mapped pin D5 + pins_d |= (0x04u & p[ 4]) << 1; // x= 2, y= 2, mapped pin D3 + pins_d |= (0x10u & p[ 4]); // x= 4, y= 2, mapped pin D4 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 + pins_b |= (0x40u & p[ 0]) >> 1; // x= 6, y= 0, mapped pin D13 + pins_b |= (0x80u & p[ 4]) >> 4; // x= 7, y= 2, mapped pin D11 + pins_b |= (0x80u & p[ 6]) >> 5; // x= 7, y= 3, mapped pin D10 + pins_b |= (0x80u & p[ 8]) >> 6; // x= 7, y= 4, mapped pin D9 + pins_b |= (0x80u & p[10]) >> 7; // x= 7, y= 5, mapped pin D8 + pins_d |= (0x01u & p[ 2]) << 2; // x= 0, y= 1, mapped pin D2 + pins_d |= (0x04u & p[ 2]) << 1; // x= 2, y= 1, mapped pin D3 + pins_d |= (0x10u & p[ 2]); // x= 4, y= 1, mapped pin D4 + pins_d |= (0x80u & p[12]); // x= 7, y= 6, mapped pin D7 + pins_d |= (0x80u & p[14]) >> 1; // x= 7, y= 7, mapped pin D6 + pins_d |= (0x80u & p[16]) >> 2; // x= 7, y= 8, mapped pin D5 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 + pins_b |= (0x40u & p[ 2]) >> 2; // x= 6, y= 1, mapped pin D12 + pins_b |= (0x40u & p[ 4]) >> 3; // x= 6, y= 2, mapped pin D11 + pins_b |= (0x40u & p[ 6]) >> 4; // x= 6, y= 3, mapped pin D10 + pins_b |= (0x40u & p[ 8]) >> 5; // x= 6, y= 4, mapped pin D9 + pins_b |= (0x40u & p[10]) >> 6; // x= 6, y= 5, mapped pin D8 + pins_d |= (0x01u & p[ 0]) << 2; // x= 0, y= 0, mapped pin D2 + pins_d |= (0x04u & p[ 0]) << 1; // x= 2, y= 0, mapped pin D3 + pins_d |= (0x10u & p[ 0]); // x= 4, y= 0, mapped pin D4 + pins_d |= (0x40u & p[12]) << 1; // x= 6, y= 6, mapped pin D7 + pins_d |= (0x40u & p[14]); // x= 6, y= 7, mapped pin D6 + pins_d |= (0x40u & p[16]) >> 1; // x= 6, y= 8, mapped pin D5 break; } } @@ -289,8 +826,40 @@ ISR(TIMER2_OVF_vect) { // Set sink pin to GND/sink, turning on current. PIND = sink_d; PINB = sink_b; +#endif +} - plane++; +#if !defined (__AVR_ATmega32U4__) +ISR(TIMER2_OVF_vect) { +#else +ISR(TIMER1_COMPA_vect) { +#endif + // 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" is a subset of LEDs that can be driven at once. + + // 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; + +#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) + TCCR2B = prescaler[plane]; +#elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega128__) + TCCR2 = prescaler[page]; +#elif defined (__AVR_ATmega32U4__) + TCCR1B = prescaler[plane]; +#endif +#if !defined (__AVR_ATmega32U4__) + TCNT2 = counts[plane]; +#else + TCNT1 = counts[plane]; +#endif + + // distribute framebuffer contents among current cycle pins + compose_cycle(cycle, plane++); if (plane >= (NUMPLANE + 1)) { plane = 0; @@ -303,20 +872,49 @@ ISR(TIMER2_OVF_vect) { } void borg_hw_init() { - // prepare Timer2 + +#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) TIMSK2 &= ~(_BV(TOIE2) | _BV(OCIE2A)); TCCR2A &= ~(_BV(WGM21) | _BV(WGM20)); TCCR2B &= ~_BV(WGM22); ASSR &= ~_BV(AS2); +#elif defined (__AVR_ATmega8__) + TIMSK &= ~(_BV(TOIE2) | _BV(OCIE2)); + TCCR2 &= ~(_BV(WGM21) | _BV(WGM20)); + ASSR &= ~_BV(AS2); +#elif defined (__AVR_ATmega128__) + TIMSK &= ~(_BV(TOIE2) | _BV(OCIE2)); + TCCR2 &= ~(_BV(WGM21) | _BV(WGM20)); +#elif defined (__AVR_ATmega32U4__) + // The only 8bit timer on the Leonardo is used by default, so we use the 16bit Timer1 + // in CTC mode with a compare value of 256 to achieve the same behaviour. + TIMSK1 &= ~(_BV(TOIE1) | _BV(OCIE1A)); + TCCR1A &= ~(_BV(WGM10) | _BV(WGM11)); + OCR1A = 256; +#endif - // Then start the display - TIMSK2 |= _BV(TOIE2); - TCCR2B = fastPrescaler; + setBrightness(); - // interrupt ASAP - TCNT2 = 0xff; + // Then start the display +#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) + TIMSK2 |= _BV(TOIE2); + TCCR2B = FASTPRESCALER; +#elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega128__) + TIMSK |= _BV(TOIE2); + TCCR2 = FASTPRESCALER; +#elif defined (__AVR_ATmega32U4__) + // Enable output compare match interrupt + TIMSK1 |= _BV(OCIE1A); + TCCR1B = FASTPRESCALER; +#endif + // interrupt ASAP +#if !defined (__AVR_ATmega32U4__) + TCNT2 = 255; +#else + TCNT1 = 255; +#endif // activate watchdog timer wdt_reset(); - wdt_enable(0x00); // 17ms watchdog + wdt_enable(WDTO_500MS); // 17ms watchdog } diff --git a/src/borg_hw/config.in b/src/borg_hw/config.in index 9aabae5..7c1d244 100644 --- a/src/borg_hw/config.in +++ b/src/borg_hw/config.in @@ -14,7 +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 \ + LoL-Shield HW_LOLSHIELD \ FFM-Jochen HW_BORG_LSJO \ FFM-LedBrett HW_LEDBRETT \ Borg-Mini HW_BORG_MINI \ diff --git a/src/borg_hw/config_lolshield.in b/src/borg_hw/config_lolshield.in index ceaf309..fd99bed 100644 --- a/src/borg_hw/config_lolshield.in +++ b/src/borg_hw/config_lolshield.in @@ -3,4 +3,6 @@ comment "lolshield setup" define_int USER_TIMER0_FOR_WAIT 1 +uint "Brightness (0-127)" BRIGHTNESS 127 + endmenu diff --git a/src/util.c b/src/util.c index bdd2a29..3b608e9 100644 --- a/src/util.c +++ b/src/util.c @@ -21,7 +21,6 @@ extern jmp_buf newmode_jmpbuf; void wait(int ms){ - /* Always use Timer1 except for the Arduino/LoL Shield platform. */ #ifndef USER_TIMER0_FOR_WAIT TCCR1B = _BV(WGM12) | _BV(CS12); //CTC Mode, clk/256 @@ -36,7 +35,6 @@ void wait(int ms){ OCR0A = (F_CPU/256000); //1000Hz #endif - for(;ms>0;ms--){ #ifdef CAN_SUPPORT @@ -57,7 +55,7 @@ void wait(int ms){ } #endif -#if defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__) +#if defined (__AVR_ATmega32U4__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__) /* Timer1 for the masses */ # ifndef USER_TIMER0_FOR_WAIT while(!(TIFR1 & _BV(OCF1A))); //wait for compare match flag From 3675e19e9d70f5e3b07bbf4523cc712a3ab42130 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Mon, 19 May 2014 07:23:40 +0200 Subject: [PATCH 14/28] forgot to reduce watchdog timeout after debugging --- src/borg_hw/borg_hw_lolshield.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/borg_hw/borg_hw_lolshield.c b/src/borg_hw/borg_hw_lolshield.c index 237be9c..1faf07a 100644 --- a/src/borg_hw/borg_hw_lolshield.c +++ b/src/borg_hw/borg_hw_lolshield.c @@ -916,5 +916,5 @@ void borg_hw_init() { // activate watchdog timer wdt_reset(); - wdt_enable(WDTO_500MS); // 17ms watchdog + wdt_enable(WDTO_15MS); // 15ms watchdog } From 2113b8f2b795e9048aadb29193825fb5fca0b97a Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Mon, 19 May 2014 08:03:44 +0200 Subject: [PATCH 15/28] although I still don't know whether Arduino Mega 1280/2560 boards will work, their MCUs should at least be configurable from menuconfig --- config.in | 2 + defaults.mk | 10 +- ld_scripts/avr51.x | 2 +- ld_scripts/avr6.x | 231 +++++++++++++++++++++++++++++++++++++++++++++ src/util.c | 2 +- 5 files changed, 242 insertions(+), 5 deletions(-) create mode 100644 ld_scripts/avr6.x diff --git a/config.in b/config.in index 61b6bf3..6a3351c 100644 --- a/config.in +++ b/config.in @@ -13,8 +13,10 @@ comment "General Setup" ATmega328p atmega328p \ ATmega644 atmega644 \ ATmega644p atmega644p \ + ATmega1280 atmega1280 \ ATmega1284 atmega1284 \ ATmega1284p atmega1284p \ + ATmega2560 atmega2560 \ ATmega8515 atmega8515" \ 'ATmega32' MCU diff --git a/defaults.mk b/defaults.mk index 129e2c5..3bbed3d 100644 --- a/defaults.mk +++ b/defaults.mk @@ -104,10 +104,14 @@ include $(MAKETOPDIR)/.config CPPFLAGS += -DF_CPU=$(FREQ)UL -mmcu=$(MCU) # flags for the linker, choose appropriate linker script -ifeq ($(findstring atmega128,$(MCU)),atmega128) - LDFLAGS += -T ld_scripts/avr51.x -Wl,-Map,image.map -mmcu=$(MCU) +ifeq ($(findstring atmega256,$(MCU)),atmega256) + LDFLAGS += -T ld_scripts/avr6.x -Wl,-Map,image.map -mmcu=$(MCU) else - LDFLAGS += -T ld_scripts/avr5.x -Wl,-Map,image.map -mmcu=$(MCU) + ifeq ($(findstring atmega128,$(MCU)),atmega128) + LDFLAGS += -T ld_scripts/avr51.x -Wl,-Map,image.map -mmcu=$(MCU) + else + LDFLAGS += -T ld_scripts/avr5.x -Wl,-Map,image.map -mmcu=$(MCU) + endif endif endif # MAKECMDGOALS!=menuconfig diff --git a/ld_scripts/avr51.x b/ld_scripts/avr51.x index a16ad36..3be4c35 100644 --- a/ld_scripts/avr51.x +++ b/ld_scripts/avr51.x @@ -4,7 +4,7 @@ OUTPUT_ARCH(avr:51) MEMORY { text (rx) : ORIGIN = 0, LENGTH = 128K - data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0 + data (rw!x) : ORIGIN = 0x800100, LENGTH = 0xff00 eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K diff --git a/ld_scripts/avr6.x b/ld_scripts/avr6.x new file mode 100644 index 0000000..26db017 --- /dev/null +++ b/ld_scripts/avr6.x @@ -0,0 +1,231 @@ +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") +OUTPUT_ARCH(avr:6) +MEMORY +{ + text (rx) : ORIGIN = 0, LENGTH = 1024K + data (rw!x) : ORIGIN = 0x800200, LENGTH = 0xfe00 + eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K + fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K + lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K + signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K +} +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : + { + *(.rel.text) + *(.rel.text.*) + *(.rel.gnu.linkonce.t*) + } + .rela.text : + { + *(.rela.text) + *(.rela.text.*) + *(.rela.gnu.linkonce.t*) + } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : + { + *(.rel.rodata) + *(.rel.rodata.*) + *(.rel.gnu.linkonce.r*) + } + .rela.rodata : + { + *(.rela.rodata) + *(.rela.rodata.*) + *(.rela.gnu.linkonce.r*) + } + .rel.data : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.gnu.linkonce.d*) + } + .rela.data : + { + *(.rela.data) + *(.rela.data.*) + *(.rela.gnu.linkonce.d*) + } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + /* Internal text space or external memory. */ + .text : + { + *(.vectors) + KEEP(*(.vectors)) + /* For data that needs to reside in the lower 64k of progmem. */ + *(.progmem.gcc*) + *(.progmem*) + . = ALIGN(2); + __trampolines_start = . ; + /* The jump trampolines for the 16-bit limited relocs will reside here. */ + *(.trampolines) + *(.trampolines*) + __trampolines_end = . ; + /* For future tablejump instruction arrays for 3 byte pc devices. + We don't relax jump/call instructions within these sections. */ + *(.jumptables) + *(.jumptables*) + /* For code that needs to reside in the lower 128k progmem. */ + *(.lowtext) + *(.lowtext*) + __ctors_start = . ; + *(.ctors) + __ctors_end = . ; + __dtors_start = . ; + *(.dtors) + __dtors_end = . ; + KEEP(SORT(*)(.ctors)) + KEEP(SORT(*)(.dtors)) + /* From this point on, we don't bother about wether the insns are + below or above the 16 bits boundary. */ + *(.init0) /* Start here after reset. */ + KEEP (*(.init0)) + *(.init1) + KEEP (*(.init1)) + *(.init2) /* Clear __zero_reg__, set up stack pointer. */ + KEEP (*(.init2)) + *(.init3) + KEEP (*(.init3)) + *(.init4) /* Initialize data and BSS. */ + KEEP (*(.init4)) + *(.init5) + KEEP (*(.init5)) + *(.init6) /* C++ constructors. */ + KEEP (*(.init6)) + *(.init7) + KEEP (*(.init7)) + *(.init8) + KEEP (*(.init8)) + *(.init9) /* Call main(). */ + KEEP (*(.init9)) + *(.text) + . = ALIGN(2); + *(.text.*) + . = ALIGN(2); + *(.fini9) /* _exit() starts here. */ + KEEP (*(.fini9)) + *(.fini8) + KEEP (*(.fini8)) + *(.fini7) + KEEP (*(.fini7)) + *(.fini6) /* C++ destructors. */ + KEEP (*(.fini6)) + *(.fini5) + KEEP (*(.fini5)) + *(.fini4) + KEEP (*(.fini4)) + *(.fini3) + KEEP (*(.fini3)) + *(.fini2) + KEEP (*(.fini2)) + *(.fini1) + KEEP (*(.fini1)) + *(.fini0) /* Infinite loop after program termination. */ + KEEP (*(.fini0)) + _etext = . ; + } > text + .data : AT (ADDR (.text) + SIZEOF (.text)) + { + PROVIDE (__data_start = .) ; + *(.data) + *(.data*) + *(.rodata) /* We need to include .rodata here if gcc is used */ + *(.rodata*) /* with -fdata-sections. */ + *(.gnu.linkonce.d*) + PROVIDE (_game_descriptors_start__ = .) ; + *(.game_descriptors) + PROVIDE (_game_descriptors_end__ = .) ; + . = ALIGN(2); + _edata = . ; + PROVIDE (__data_end = .) ; + } > data + .bss SIZEOF(.data) + ADDR(.data) : + { + PROVIDE (__bss_start = .) ; + *(.bss) + *(.bss*) + *(COMMON) + PROVIDE (__bss_end = .) ; + } > data + __data_load_start = LOADADDR(.data); + __data_load_end = __data_load_start + SIZEOF(.data); + /* Global data not cleared after reset. */ + .noinit SIZEOF(.bss) + ADDR(.bss) : + { + PROVIDE (__noinit_start = .) ; + *(.noinit*) + PROVIDE (__noinit_end = .) ; + _end = . ; + PROVIDE (__heap_start = .) ; + } > data + .eeprom : + { + *(.eeprom*) + __eeprom_end = . ; + } > eeprom + .fuse : + { + KEEP(*(.fuse)) + KEEP(*(.lfuse)) + KEEP(*(.hfuse)) + KEEP(*(.efuse)) + } > fuse + .lock : + { + KEEP(*(.lock*)) + } > lock + .signature : + { + KEEP(*(.signature*)) + } > signature + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } +} diff --git a/src/util.c b/src/util.c index 3b608e9..87e366c 100644 --- a/src/util.c +++ b/src/util.c @@ -55,7 +55,7 @@ void wait(int ms){ } #endif -#if defined (__AVR_ATmega32U4__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__) +#if defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) || defined (__AVR_ATmega32U4__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__) /* Timer1 for the masses */ # ifndef USER_TIMER0_FOR_WAIT while(!(TIFR1 & _BV(OCF1A))); //wait for compare match flag From 7956988060a528d27a3508e1e45b932729f4b7c2 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Mon, 19 May 2014 10:31:30 +0200 Subject: [PATCH 16/28] default for "null joystick" in menuconfig is "no" --- src/joystick/config.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/config.in b/src/joystick/config.in index b68b099..5619ef2 100644 --- a/src/joystick/config.in +++ b/src/joystick/config.in @@ -194,7 +194,7 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then ############################################################################### ###################### null joystick menu #################################### - dep_bool "null joystick support" NULL_JOYSTICK_SUPPORT y + dep_bool "null joystick support" NULL_JOYSTICK_SUPPORT n ############################################################################### From d2a1942e13abfececaa00e9de5288480afb4c54a Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Mon, 19 May 2014 11:09:07 +0200 Subject: [PATCH 17/28] advertise support for LoL Shield --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 35f3d6f..61641a0 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,10 @@ Firmware for AVR based two-dimensional LED matrices, especially the Main platform is the [Borg16](http://www.das-labor.org/wiki/Borg16) construction kit. Other supported platforms are the [LED Brett](http://www.hackerspace-ffm.de/wiki/index.php?title=LedBrett) -projector from [Hackerspace FFM](http://www.hackerspace-ffm.de) or the -[ELO Ping-Pong Board](http://www.elo-web.de/elo/mikrocontroller-und-programmierung/ping-pong/das-franzis-pingpong). +projector from [Hackerspace FFM](http://www.hackerspace-ffm.de), the +[ELO Ping-Pong Board](http://www.elo-web.de/elo/mikrocontroller-und-programmierung/ping-pong/das-franzis-pingpong) +or the [LoL Shield](http://jimmieprodgers.com/kits/lolshield/) from Jimmie P. +Rodgers. ![Small Borg16](/doc/img/Borg16-small.jpg) ![Glow Lamp Borg](/doc/img/Glow_Lamp_Borg.jpg) From 7edb0188f9d48bad70614d7dc5ca77649e7ae605 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Mon, 19 May 2014 13:22:06 +0200 Subject: [PATCH 18/28] src/joystick/config.in: next try... --- src/joystick/config.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/config.in b/src/joystick/config.in index 5619ef2..68c90df 100644 --- a/src/joystick/config.in +++ b/src/joystick/config.in @@ -194,7 +194,7 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then ############################################################################### ###################### null joystick menu #################################### - dep_bool "null joystick support" NULL_JOYSTICK_SUPPORT n + bool "null joystick support" NULL_JOYSTICK_SUPPORT n ############################################################################### From ad2a7939ab4e22803e22db411a43a0e76876056f Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Wed, 21 May 2014 01:30:38 +0200 Subject: [PATCH 19/28] completed support for Arduino Mega 2560 (now tested) --- profiles/LoL-Shield_Mega2560 | 125 ++++++++++++++++++++++++++++++++ src/borg_hw/borg_hw_lolshield.c | 17 +++-- src/random/Makefile | 9 ++- src/random/noekeon.c | 8 +- 4 files changed, 146 insertions(+), 13 deletions(-) create mode 100644 profiles/LoL-Shield_Mega2560 diff --git a/profiles/LoL-Shield_Mega2560 b/profiles/LoL-Shield_Mega2560 new file mode 100644 index 0000000..2e60578 --- /dev/null +++ b/profiles/LoL-Shield_Mega2560 @@ -0,0 +1,125 @@ +# +# Automatically generated by make menuconfig: don't edit +# + +# +# General Setup +# +MCU=atmega2560 +FREQ=16000000 + +# +# Borg Hardware +# +NUM_ROWS=9 +NUM_COLS=14 +NUMPLANE=3 +BORG_HW=HW_LOLSHIELD + +# +# lolshield setup +# +USER_TIMER0_FOR_WAIT=1 +BRIGHTNESS=127 + +# +# Features +# +RANDOM_SUPPORT=y +# LAP_TIME_EXTENSION is not set +SCROLLTEXT_SUPPORT=y +SCROLLTEXT_FONT=FONT_C64 +SCROLLTEXT_BUFFER_SIZE=128 +SCROLL_X_SPEED=20 +SCROLL_Y_SPEED=20 +SCROLLTEXT_TEXT="> 1; // x= 6, y= 8, mapped pin D5 break; } - } + } // Enable pullups on new output pins. PORTD = pins_d; diff --git a/src/random/Makefile b/src/random/Makefile index 725498e..0597a7c 100644 --- a/src/random/Makefile +++ b/src/random/Makefile @@ -5,8 +5,13 @@ TARGET = objects_avr include $(MAKETOPDIR)/defaults.mk #for AVR -SRC = prng.c persistentCounter.c -ASRC = noekeon_asm.S memxor.S +ifeq ($(findstring atmega256,$(MCU)),atmega256) + # handmade assembler routines don't work on ATmega2560 + SRC = prng.c persistentCounter.c noekeon.c memxor_c.c +else + SRC = prng.c persistentCounter.c + ASRC = noekeon_asm.S memxor.S +endif #for simulator SRC_SIM = prng.c persistentCounter.c noekeon.c memxor_c.c diff --git a/src/random/noekeon.c b/src/random/noekeon.c index 8a4c23a..ea15f27 100644 --- a/src/random/noekeon.c +++ b/src/random/noekeon.c @@ -98,9 +98,9 @@ void noekeon_round(uint32_t* key, uint32_t* state, uint8_t const1, uint8_t const pi2(state); } -uint8_t rc_tab[] +uint8_t const rc_tab[] #ifdef __AVR__ - PROGMEM + PROGMEM #endif = { /* 0x80, */ @@ -146,7 +146,7 @@ void noekeon_enc(void* buffer, const void* key){ for(i=0; i=0; --i){ #ifdef __AVR__ - rc = pgm_read_byte(rc_tab+i); + rc = pgm_read_byte(&rc_tab[i]); #else rc = rc_tab[i]; #endif From 2b0a6b6b762750269aab766b45139c5bf33c961f Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Wed, 21 May 2014 07:21:12 +0200 Subject: [PATCH 20/28] resolved name clash (gamma() is also defined elsewhere in the avr-realm) --- src/random/noekeon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/random/noekeon.c b/src/random/noekeon.c index ea15f27..5772e8d 100644 --- a/src/random/noekeon.c +++ b/src/random/noekeon.c @@ -39,7 +39,7 @@ #define RC_POS 0 static -void gamma(uint32_t* a){ +void noekeon_gamma(uint32_t* a){ uint32_t tmp; a[1] ^= ~((a[3]) | (a[2])); @@ -94,7 +94,7 @@ void noekeon_round(uint32_t* key, uint32_t* state, uint8_t const1, uint8_t const theta(key, state); ((uint8_t*)state)[RC_POS] ^= const2; pi1(state); - gamma(state); + noekeon_gamma(state); pi2(state); } From 97f93a4a4c955cb4349715f3b934fd813ee3c979 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Wed, 21 May 2014 08:18:56 +0200 Subject: [PATCH 21/28] added some MCUs in menuconfig --- config.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config.in b/config.in index 6a3351c..6ed2601 100644 --- a/config.in +++ b/config.in @@ -7,6 +7,9 @@ comment "General Setup" choice 'Target MCU' \ "ATmega8 atmega8 \ + ATmega16 atmega16 \ + ATmega168 atmega168 \ + ATmega168P atmega168p \ ATmega32 atmega32 \ ATmega32U4 atmega32u4 \ ATmega328 atmega328 \ From e10166a31625da34015428660959a52aecd97d3a Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Thu, 22 May 2014 19:17:28 +0200 Subject: [PATCH 22/28] program.c: sign error (non-fatal but annoying) --- src/animations/program.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/animations/program.c b/src/animations/program.c index 56496d8..c964731 100644 --- a/src/animations/program.c +++ b/src/animations/program.c @@ -172,7 +172,7 @@ void random_bright(unsigned int cycles) { for (unsigned char y = NUM_ROWS; y--;) { for (unsigned char x = LINEBYTES; x--;) { if (p < (NUMPLANE - 1)) { - pixmap[p][y][x] |= pixmap[p - 1][y][x]; + pixmap[p][y][x] |= pixmap[p + 1][y][x]; } pixmap[p][y][x] = random8(); } From 720d547f4a7af774214267949dd41d3c3c6dec58 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sun, 25 May 2014 11:08:35 +0200 Subject: [PATCH 23/28] joystick support for lolshield (A0-up,A1-down,A2-left,A3-right,A5-fire) --- profiles/FFM-Jochen | 6 + profiles/FFM-LedBrett | 20 +++- profiles/LoL-Shield_Leonardo | 11 +- profiles/LoL-Shield_Mega2560 | 11 +- profiles/LoL-Shield_Uno-Duemilanove-Diavolino | 11 +- profiles/borg-16 | 14 ++- profiles/borg-ancient | 16 ++- profiles/borg-andre | 14 ++- profiles/borg-ls | 17 ++- profiles/borgjacke | 27 +++-- src/joystick/Makefile | 3 + src/joystick/config.in | 111 +++++++++++------- src/joystick/joystick.h | 62 +++++++++- src/joystick/lolshield_joystick.c | 89 ++++++++++++++ 14 files changed, 337 insertions(+), 75 deletions(-) create mode 100644 src/joystick/lolshield_joystick.c diff --git a/profiles/FFM-Jochen b/profiles/FFM-Jochen index f509c24..5da3e44 100644 --- a/profiles/FFM-Jochen +++ b/profiles/FFM-Jochen @@ -37,7 +37,12 @@ SCROLL_X_SPEED=10 SCROLL_Y_SPEED=20 SCROLLTEXT_TEXT="5+:<5|90>6:<6|78>:p10d50/#Labor#<5;>5|30<6;>6|40<6;p10+d50/# Borg#2d50-+/#Widerstand#ist#d50-b20p15#ZWECKLOS !" +# RFM12_SUPPORT is not set + +# +# Joystick Support +# # JOYSTICK_SUPPORT is not set +JOYSTICK_CHOICE="JOY_PARALLEL" CAN_SUPPORT=y SPI_HARDWARE=y SPI_PORTIDX=1 @@ -91,6 +97,7 @@ GOL_DELAY=12 GOL_CYCLES=180 # ANIMATION_BREAKOUT is not set # ANIMATION_MHERWEG is not set +# ANIMATION_MOIRE is not set # ANIMATION_LTN_ANT is not set ANIMATION_TIME=y TIME_MASTER_ADDR=00 @@ -99,9 +106,17 @@ TIME_UPDATE_TIMEOUT=50 # ANIMATION_LABORLOGO is not set # ANIMATION_AMPHIBIAN is not set # ANIMATION_LOGO_OOS is not set -# ANIMATION_LOGO_28C3 is not set +# ANIMATION_FAIRYDUST is not set + +# +# Fixed-point math patterns +# # ANIMATION_PLASMA is not set +FP_PLASMA_DELAY=1 # ANIMATION_PSYCHEDELIC is not set +FP_PSYCHO_DELAY=15 +# ANIMATION_BLACKHOLE is not set +# ANIMATION_SQUARES is not set ANIMATION_TESTS=y ANIMATION_OFF=y diff --git a/profiles/borgjacke b/profiles/borgjacke index 73bf84b..3468712 100644 --- a/profiles/borgjacke +++ b/profiles/borgjacke @@ -49,9 +49,12 @@ BIT_MISO=6 BIT_SCK=7 PORT_SS=PORTB BIT_SS=4 + +# +# Joystick Support +# JOYSTICK_SUPPORT=y -# PARALLEL_JOYSTICK_SUPPORT is not set -# NES_PAD_SUPPORT is not set +JOYSTICK_CHOICE=JOY_RFM12 RFM12_JOYSTICK_SUPPORT=y # CAN_SUPPORT is not set MENU_SUPPORT=y @@ -65,7 +68,7 @@ GAME_TETRIS=y # GAME_TETRIS_FP is not set GAME_SPACE_INVADERS=y GAME_SNAKE=y -# GAME_BREAKOUT is not set +GAME_BREAKOUT=y # # Animations @@ -91,14 +94,15 @@ MATRIX_STREAMER_NUM=30 MATRIX_CYCLES=500 MATRIX_DELAY=60 ANIMATION_RANDOM_BRIGHT=y -# ANIMATION_STONEFLY is not set -# ANIMATION_FLYINGDOTS is not set +ANIMATION_STONEFLY=y +ANIMATION_FLYINGDOTS=y ANIMATION_GAMEOFLIFE=y GOL_DELAY=100 GOL_CYCLES=360 -# ANIMATION_BREAKOUT is not set +ANIMATION_BREAKOUT=y # ANIMATION_MHERWEG is not set -# ANIMATION_LTN_ANT is not set +ANIMATION_MOIRE=y +ANIMATION_LTN_ANT=y # ANIMATION_TIME is not set TIME_MASTER_ADDR=0x00 TIME_UPDATE_TIMEOUT=23 @@ -107,9 +111,16 @@ ANIMATION_LABORLOGO=y # ANIMATION_AMPHIBIAN is not set # ANIMATION_LOGO_OOS is not set # ANIMATION_FAIRYDUST is not set + +# +# Fixed-point math patterns +# ANIMATION_PLASMA=y +FP_PLASMA_DELAY=1 ANIMATION_PSYCHEDELIC=y -# ANIMATION_BLACKHOLE is not set +FP_PSYCHO_DELAY=15 +ANIMATION_BLACKHOLE=y +ANIMATION_SQUARES=y ANIMATION_TESTS=y ANIMATION_OFF=y diff --git a/src/joystick/Makefile b/src/joystick/Makefile index bbbb411..6a5b92e 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 ($(LOLSHIELD_JOYSTICK_SUPPORT), y) + SRC = lolshield_joystick.c +endif ifeq ($(NULL_JOYSTICK_SUPPORT), y) SRC = null_joystick.c endif diff --git a/src/joystick/config.in b/src/joystick/config.in index 68c90df..d67c536 100644 --- a/src/joystick/config.in +++ b/src/joystick/config.in @@ -1,18 +1,36 @@ -dep_bool_menu "joystick support" JOYSTICK_SUPPORT y +mainmenu_option next_comment +comment "Joystick Support" + +bool "Joystick Support" JOYSTICK_SUPPORT n + +if [ "x$JOYSTICK_CHOICE" == "x" ] ; then + define_string JOYSTICK_CHOICE "JOY_PARALLEL" +fi if [ "$JOYSTICK_SUPPORT" = "y" ]; then -###################### Parallel joystick menu ################################# - dep_bool_menu "parallel joystick support" PARALLEL_JOYSTICK_SUPPORT y + choice 'Joystick Type' \ + "Atari-9-Pin JOY_PARALLEL \ + NES-Game-Pad JOY_NES_PAD \ + RFM12 JOY_RFM12 \ + LED-Brett JOY_LEDBRETT \ + LoL-Shield JOY_LOLSHIELD \ + None JOY_NULL" \ + 'Atari-9-Pin' JOYSTICK_CHOICE - if [ "$PARALLEL_JOYSTICK_SUPPORT" = "y" ]; then - choice 'Pin up' \ +###################### parallel joystick menu ################################# + if [ "$JOYSTICK_CHOICE" == "JOY_PARALLEL" ]; then + mainmenu_option next_comment + comment "Joystick Settings" + + define_bool PARALLEL_JOYSTICK_SUPPORT y + choice 'Pin up' \ "PINA PINA \ PINB PINB \ PINC PINC \ PIND PIND" \ 'PINB' JOYSTICK_PIN_UP - choice 'Bit up' \ + choice 'Bit up' \ "Bit0 0 \ Bit1 1 \ Bit2 2 \ @@ -23,14 +41,14 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then Bit7 7" \ 'Bit0' JOYSTICK_BIT_UP - choice 'Pin down' \ + choice 'Pin down' \ "PINA PINA \ PINB PINB \ PINC PINC \ PIND PIND" \ 'PINB' JOYSTICK_PIN_DOWN - choice 'Bit down' \ + choice 'Bit down' \ "Bit0 0 \ Bit1 1 \ Bit2 2 \ @@ -41,14 +59,14 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then Bit7 7" \ 'Bit1' JOYSTICK_BIT_DOWN - choice 'Pin left' \ + choice 'Pin left' \ "PINA PINA \ PINB PINB \ PINC PINC \ PIND PIND" \ 'PINB' JOYSTICK_PIN_LEFT - choice 'Bit left' \ + choice 'Bit left' \ "Bit0 0 \ Bit1 1 \ Bit2 2 \ @@ -59,14 +77,14 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then Bit7 7" \ 'Bit2' JOYSTICK_BIT_LEFT - choice 'Pin right' \ + choice 'Pin right' \ "PINA PINA \ PINB PINB \ PINC PINC \ PIND PIND" \ 'PINB' JOYSTICK_PIN_RIGHT - choice 'Bit right' \ + choice 'Bit right' \ "Bit0 0 \ Bit1 1 \ Bit2 2 \ @@ -77,14 +95,14 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then Bit7 7" \ 'Bit3' JOYSTICK_BIT_RIGHT - choice 'Pin fire' \ + choice 'Pin fire' \ "PINA PINA \ PINB PINB \ PINC PINC \ PIND PIND" \ 'PIND' JOYSTICK_PIN_FIRE - choice 'Bit fire' \ + choice 'Bit fire' \ "Bit0 0 \ Bit1 1 \ Bit2 2 \ @@ -94,37 +112,40 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then Bit6 6 \ Bit7 7" \ 'Bit3' JOYSTICK_BIT_FIRE - fi - endmenu + endmenu + fi ############################################################################### -###################### NES-Pad menu ################################# - dep_bool_menu "nes-pad support" NES_PAD_SUPPORT y +###################### NES-Pad menu ########################################### + if [ "$JOYSTICK_CHOICE" == "JOY_NES_PAD" ]; then + mainmenu_option next_comment + comment "Joystick Settings" - if [ "$NES_PAD_SUPPORT" = "y" ]; then - choice 'Port clk' \ + define_bool NES_PAD_SUPPORT y + + choice 'Port clk' \ "PORTA PORTA \ PORTB PORTB \ PORTC PORTC \ PORTD PORTD" \ 'PORTB' NES_PAD_PORT_CLK - choice 'Port ds' \ + choice 'Port ds' \ "PORTA PORTA \ PORTB PORTB \ PORTC PORTC \ PORTD PORTD" \ - 'PORTB' NES_PAD_PORT_PL + 'PORTB' NES_PAD_PORT_PL - choice 'Pin pl' \ + choice 'Pin pl' \ "PORTA PORTA \ PORTB PORTB \ PORTC PORTC \ PORTD PORTD" \ 'PORTB' NES_PAD_PORT_DS - choice 'Bit clk' \ + choice 'Bit clk' \ "Bit0 0 \ Bit1 1 \ Bit2 2 \ @@ -135,7 +156,7 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then Bit7 7" \ 'Bit0' NES_PAD_BIT_CLK - choice 'Bit pl' \ + choice 'Bit pl' \ "Bit0 0 \ Bit1 1 \ Bit2 2 \ @@ -146,7 +167,7 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then Bit7 7" \ 'Bit1' NES_PAD_BIT_PL - choice 'Bit ds' \ + choice 'Bit ds' \ "Bit0 0 \ Bit1 1 \ Bit2 2 \ @@ -157,28 +178,31 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then Bit7 7" \ 'Bit2' NES_PAD_BIT_DS + endmenu fi - - endmenu ############################################################################### ###################### RFM12 joystick menu #################################### - dep_bool_menu "RFM12 Joystick support" RFM12_JOYSTICK_SUPPORT y - - endmenu + if [ "$JOYSTICK_CHOICE" == "JOY_RFM12" ]; then + define_bool RFM12_JOYSTICK_SUPPORT y + fi +############################################################################### ###################### 74HC165 joystick menu ################################# - dep_bool_menu "74HC165 joystick support" HC165_JOYSTICK_SUPPORT y + if [ "$JOYSTICK_CHOICE" == "JOY_LEDBRETT" ]; then + mainmenu_option next_comment + comment "Joystick Settings" - if [ "$HC165_JOYSTICK_SUPPORT" = "y" ]; then - choice 'Port load' \ + define_bool HC165_JOYSTICK_SUPPORT y + + choice 'Port load' \ "PORTA PORTA \ PORTB PORTB \ PORTC PORTC \ PORTD PORTD" \ 'PORTD' HC165_JOYSTICK_PORT_LOAD - choice 'Bit load' \ + choice 'Bit load' \ "Bit0 0 \ Bit1 1 \ Bit2 2 \ @@ -188,16 +212,23 @@ if [ "$JOYSTICK_SUPPORT" = "y" ]; then Bit6 6 \ Bit7 7" \ 'Bit2' HC165_JOYSTICK_BIT_LOAD + + endmenu fi - - endmenu ############################################################################### -###################### null joystick menu #################################### - bool "null joystick support" NULL_JOYSTICK_SUPPORT n +###################### LoL Shield joystick menu ############################### + if [ "$JOYSTICK_CHOICE" == "JOY_NULL" ]; then + define_bool NULL_JOYSTICK_SUPPORT y + fi ############################################################################### +###################### null joystick menu ##################################### + if [ "$JOYSTICK_CHOICE" == "JOY_LOLSHIELD" ]; then + define_bool LOLSHIELD_JOYSTICK_SUPPORT y + fi +############################################################################### fi -endmenu +endmenu \ No newline at end of file diff --git a/src/joystick/joystick.h b/src/joystick/joystick.h index 0c606f4..abd0a00 100644 --- a/src/joystick/joystick.h +++ b/src/joystick/joystick.h @@ -1,6 +1,10 @@ #ifndef JOYSTICK_H #define JOYSTICK_H +#ifdef __AVR__ +# include +#endif + #include "../config.h" extern unsigned char waitForFire; @@ -49,7 +53,63 @@ void joy_init(); # define JOYISRIGHT (0) # define JOYISFIRE (0) -# else +# elif defined (LOLSHIELD_JOYSTICK_SUPPORT) + +# if defined (__AVR_ATmega48__) || \ + defined (__AVR_ATmega48P__) || \ + defined (__AVR_ATmega88__) || \ + defined (__AVR_ATmega88P__) || \ + defined (__AVR_ATmega168__) || \ + defined (__AVR_ATmega168P__) || \ + defined (__AVR_ATmega328__) || \ + defined (__AVR_ATmega328P__) + /* + * A0 => PC0 => JOYISUP + * A1 => PC1 => JOYISDOWN + * A2 => PC2 => JOYISLEFT + * A3 => PC3 => JOYISRIGHT + * A4 => PC4 => NC (JOYIS2GND) + * A5 => PC5 => JOYISFIRE + */ +# define JOYISUP (!(PINC & _BV(PINC0))) +# define JOYISDOWN (!(PINC & _BV(PINC1))) +# define JOYISLEFT (!(PINC & _BV(PINC2))) +# define JOYISRIGHT (!(PINC & _BV(PINC3))) +# define JOYISFIRE (!(PINC & _BV(PINC5))) +# elif defined (__AVR_ATmega32U4__) + /* + * A0 => PF7 => JOYISUP + * A1 => PF6 => JOYISDOWN + * A2 => PF5 => JOYISLEFT + * A3 => PF4 => JOYISRIGHT + * A4 => PF1 => NC (JOYIS2GND) + * A5 => PF0 => JOYISFIRE + */ +# define JOYISUP (!(PINF & _BV(PINF7))) +# define JOYISDOWN (!(PINF & _BV(PINF6))) +# define JOYISLEFT (!(PINF & _BV(PINF5))) +# define JOYISRIGHT (!(PINF & _BV(PINF4))) +# define JOYISFIRE (!(PINF & _BV(PINF0))) +# elif defined (__AVR_ATmega1280__) || \ + defined (__AVR_ATmega2560__) + /* + * A0 => PF0 => JOYISUP + * A1 => PF1 => JOYISDOWN + * A2 => PF2 => JOYISLEFT + * A3 => PF3 => JOYISRIGHT + * A4 => PF4 => NC (JOYIS2GND) + * A5 => PF5 => JOYISFIRE + */ +# define JOYISUP (!(PINF & _BV(PINF0))) +# define JOYISDOWN (!(PINF & _BV(PINF1))) +# define JOYISLEFT (!(PINF & _BV(PINF2))) +# define JOYISRIGHT (!(PINF & _BV(PINF3))) +# define JOYISFIRE (!(PINF & _BV(PINF5))) +# else +# error "Unsupported Arduino board!" +# endif + +# elif defined (PARALLEL_JOYSTICK_SUPPORT) # define JOYISUP (!(JOYSTICK_PIN_UP & (1< + +void joy_init(){ +#if defined (__AVR_ATmega48__) || \ + defined (__AVR_ATmega48P__) || \ + defined (__AVR_ATmega88__) || \ + defined (__AVR_ATmega88P__) || \ + defined (__AVR_ATmega168__) || \ + defined (__AVR_ATmega168P__) || \ + defined (__AVR_ATmega328__) || \ + defined (__AVR_ATmega328P__) + /* + * A0 => PC0 => JOYISUP + * A1 => PC1 => JOYISDOWN + * A2 => PC2 => JOYISLEFT + * A3 => PC3 => JOYISRIGHT + * A4 => PC4 => NC (JOYIS2GND) + * A5 => PC5 => JOYISFIRE + */ + + // set joystick pins to input + DDRC &= ~(_BV(PINC0) | _BV(PINC1) | _BV(PINC2) | + _BV(PINC3) | _BV(PINC4) | _BV(PINC5)); + // activate pullups + PORTC |= _BV(PINC0) | _BV(PINC1) | _BV(PINC2) | + _BV(PINC3) | _BV(PINC4) | _BV(PINC5); +#elif defined (__AVR_ATmega32U4__) + /* + * A0 => PF7 => JOYISUP + * A1 => PF6 => JOYISDOWN + * A2 => PF5 => JOYISLEFT + * A3 => PF4 => JOYISRIGHT + * A4 => PF1 => NC (JOYIS2GND) + * A5 => PF0 => JOYISFIRE + */ + + // set joystick pins to input + DDRF &= ~(_BV(PINF7) | _BV(PINF6) | _BV(PINF5) | + _BV(PINF4) | _BV(PINF1) | _BV(PINF0)); + // activate pullups + PORTF |= _BV(PINF7) | _BV(PINF6) | _BV(PINF5) | _BV(PINF4) | + _BV(PINF1) | _BV(PINF0); +#elif defined (__AVR_ATmega1280__) || \ + defined (__AVR_ATmega2560__) + /* + * A0 => PF0 => JOYISUP + * A1 => PF1 => JOYISDOWN + * A2 => PF2 => JOYISLEFT + * A3 => PF3 => JOYISRIGHT + * A4 => PF4 => NC (JOYIS2GND) + * A5 => PF5 => JOYISFIRE + */ + + // set joystick pins to input + DDRF &= ~(_BV(PINF0) | _BV(PINF1) | _BV(PINF2) | + _BV(PINF3) | _BV(PINF4) | _BV(PINF5)); + // activate pullups + PORTF |= _BV(PINF0) | _BV(PINF1) | _BV(PINF2) | + _BV(PINF3) | _BV(PINF4) | _BV(PINF5); +#else +# error "Unsupported Arduino board!" +#endif +} From f0fdc0521e83442fcc3f4bac3ddf07b4f701e226 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sun, 25 May 2014 18:12:12 +0200 Subject: [PATCH 24/28] Tetris is tilted on displays with both height < 16 and height < width --- src/games/tetris/view.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/games/tetris/view.c b/src/games/tetris/view.c index ba542d6..204ac01 100644 --- a/src/games/tetris/view.c +++ b/src/games/tetris/view.c @@ -52,8 +52,14 @@ /** color of line counter */ #define TETRIS_VIEW_COLORCOUNTER 2 -#define VIEWCOLS NUM_COLS -#define VIEWROWS NUM_ROWS +#if (NUM_ROWS < 16) && (NUM_COLS > NUM_ROWS) && (!defined GAME_TETRIS_FP) +# define VIEWCOLS NUM_ROWS +# define VIEWROWS NUM_COLS +# define VIEW_TILT +#else +# define VIEWCOLS NUM_COLS +# define VIEWROWS NUM_ROWS +#endif #if VIEWROWS >= 20 #define TETRIS_VIEW_YOFFSET_DUMP ((VIEWROWS - 20) / 2) @@ -112,6 +118,11 @@ static void tetris_view_setpixel(tetris_bearing_t nBearing, uint8_t y, uint8_t nColor) { +#ifdef VIEW_TILT + // tilt counter clockwise + nBearing = (nBearing + 3) % 4u; +#endif + x = VIEWCOLS - 1 - x; pixel px; From 45fb2f8cd66fb75bd7c17b558a05b8a601e3a874 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sun, 25 May 2014 22:21:45 +0200 Subject: [PATCH 25/28] tweaked Arduino Mega 2560 config (we have plenty of flash memory to fill) --- profiles/LoL-Shield_Mega2560 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/profiles/LoL-Shield_Mega2560 b/profiles/LoL-Shield_Mega2560 index 56f02e2..f6e9d40 100644 --- a/profiles/LoL-Shield_Mega2560 +++ b/profiles/LoL-Shield_Mega2560 @@ -42,17 +42,17 @@ JOYSTICK_SUPPORT=y JOYSTICK_CHOICE=JOY_LOLSHIELD LOLSHIELD_JOYSTICK_SUPPORT=y # CAN_SUPPORT is not set -# MENU_SUPPORT is not set +MENU_SUPPORT=y # # Games # GAME_TETRIS_CORE=y -# GAME_TETRIS is not set -# GAME_BASTET is not set +GAME_TETRIS=y +GAME_BASTET=y # GAME_TETRIS_FP is not set -# GAME_SPACE_INVADERS is not set -# GAME_SNAKE is not set +GAME_SPACE_INVADERS=y +GAME_SNAKE=y GAME_BREAKOUT=y # @@ -106,8 +106,8 @@ ANIMATION_PSYCHEDELIC=y FP_PSYCHO_DELAY=25 ANIMATION_BLACKHOLE=y ANIMATION_SQUARES=y -# ANIMATION_TESTS is not set -# ANIMATION_OFF is not set +ANIMATION_TESTS=y +ANIMATION_OFF=y # # small Animations From ece146fe72abe887755a9f20ba4203a7dd3ac3d0 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sun, 25 May 2014 22:45:55 +0200 Subject: [PATCH 26/28] tweaked Ard. Duemilanove config (limited flash memory, but enough for games) --- profiles/LoL-Shield_Uno-Duemilanove-Diavolino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/profiles/LoL-Shield_Uno-Duemilanove-Diavolino b/profiles/LoL-Shield_Uno-Duemilanove-Diavolino index 480f10a..f8836f9 100644 --- a/profiles/LoL-Shield_Uno-Duemilanove-Diavolino +++ b/profiles/LoL-Shield_Uno-Duemilanove-Diavolino @@ -42,17 +42,17 @@ JOYSTICK_SUPPORT=y JOYSTICK_CHOICE=JOY_LOLSHIELD LOLSHIELD_JOYSTICK_SUPPORT=y # CAN_SUPPORT is not set -# MENU_SUPPORT is not set +MENU_SUPPORT=y # # Games # GAME_TETRIS_CORE=y -# GAME_TETRIS is not set +GAME_TETRIS=y # GAME_BASTET is not set # GAME_TETRIS_FP is not set # GAME_SPACE_INVADERS is not set -# GAME_SNAKE is not set +GAME_SNAKE=y GAME_BREAKOUT=y # From a722716bb40384a7a9ef56431f592afae026226f Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Sun, 25 May 2014 23:00:41 +0200 Subject: [PATCH 27/28] tweaked Ard. Leonardo config (only 28KiB of usable flash, stripped some anims) --- profiles/LoL-Shield_Leonardo | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/profiles/LoL-Shield_Leonardo b/profiles/LoL-Shield_Leonardo index 3fea5e4..a9ac512 100644 --- a/profiles/LoL-Shield_Leonardo +++ b/profiles/LoL-Shield_Leonardo @@ -42,17 +42,17 @@ JOYSTICK_SUPPORT=y JOYSTICK_CHOICE=JOY_LOLSHIELD LOLSHIELD_JOYSTICK_SUPPORT=y # CAN_SUPPORT is not set -# MENU_SUPPORT is not set +MENU_SUPPORT=y # # Games # GAME_TETRIS_CORE=y -# GAME_TETRIS is not set +GAME_TETRIS=y # GAME_BASTET is not set # GAME_TETRIS_FP is not set # GAME_SPACE_INVADERS is not set -# GAME_SNAKE is not set +GAME_SNAKE=y GAME_BREAKOUT=y # @@ -80,20 +80,20 @@ MATRIX_CYCLES=500 MATRIX_DELAY=60 ANIMATION_RANDOM_BRIGHT=y ANIMATION_STONEFLY=y -ANIMATION_FLYINGDOTS=y +# ANIMATION_FLYINGDOTS is not set ANIMATION_GAMEOFLIFE=y GOL_DELAY=100 GOL_CYCLES=360 ANIMATION_BREAKOUT=y # ANIMATION_MHERWEG is not set ANIMATION_MOIRE=y -ANIMATION_LTN_ANT=y +# ANIMATION_LTN_ANT is not set # ANIMATION_TIME is not set TIME_MASTER_ADDR=00 TIME_UPDATE_TIMEOUT=50 ANIMATION_BMSCROLLER=y # ANIMATION_LABORLOGO is not set -ANIMATION_AMPHIBIAN=y +# ANIMATION_AMPHIBIAN is not set # ANIMATION_LOGO_OOS is not set ANIMATION_FAIRYDUST=y From 24cd3f5d1d5d37269107f35982b579ecf4638e96 Mon Sep 17 00:00:00 2001 From: Christian Kroll Date: Tue, 27 May 2014 08:27:27 +0200 Subject: [PATCH 28/28] snake: better playability --- profiles/FFM-Jochen | 3 +- profiles/FFM-LedBrett | 3 +- profiles/LoL-Shield_Leonardo | 3 +- profiles/LoL-Shield_Mega2560 | 3 +- profiles/LoL-Shield_Uno-Duemilanove-Diavolino | 3 +- profiles/borg-16 | 3 +- profiles/borg-ancient | 3 +- profiles/borg-andre | 3 +- profiles/borg-ls | 3 +- profiles/borgjacke | 3 +- src/animations/config.in | 3 +- src/games/snake/snake_game.c | 100 ++++++++++++------ 12 files changed, 90 insertions(+), 43 deletions(-) diff --git a/profiles/FFM-Jochen b/profiles/FFM-Jochen index 5da3e44..f7a0072 100644 --- a/profiles/FFM-Jochen +++ b/profiles/FFM-Jochen @@ -65,7 +65,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=5 # ANIMATION_JOERN1 is not set ANIMATION_SNAKE=y -SNAKE_CYCLE_DELAY=40 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=40 SNAKE_TERMINATION_DELAY=30 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/profiles/FFM-LedBrett b/profiles/FFM-LedBrett index ce52f87..72fabea 100644 --- a/profiles/FFM-LedBrett +++ b/profiles/FFM-LedBrett @@ -68,7 +68,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=5 # ANIMATION_JOERN1 is not set # ANIMATION_SNAKE is not set -SNAKE_CYCLE_DELAY=100 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=100 SNAKE_TERMINATION_DELAY=60 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/profiles/LoL-Shield_Leonardo b/profiles/LoL-Shield_Leonardo index a9ac512..050d78a 100644 --- a/profiles/LoL-Shield_Leonardo +++ b/profiles/LoL-Shield_Leonardo @@ -63,7 +63,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=5 ANIMATION_JOERN1=y ANIMATION_SNAKE=y -SNAKE_CYCLE_DELAY=100 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=100 SNAKE_TERMINATION_DELAY=60 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/profiles/LoL-Shield_Mega2560 b/profiles/LoL-Shield_Mega2560 index f6e9d40..0bd22c2 100644 --- a/profiles/LoL-Shield_Mega2560 +++ b/profiles/LoL-Shield_Mega2560 @@ -63,7 +63,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=5 ANIMATION_JOERN1=y ANIMATION_SNAKE=y -SNAKE_CYCLE_DELAY=100 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=100 SNAKE_TERMINATION_DELAY=60 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/profiles/LoL-Shield_Uno-Duemilanove-Diavolino b/profiles/LoL-Shield_Uno-Duemilanove-Diavolino index f8836f9..1782dcd 100644 --- a/profiles/LoL-Shield_Uno-Duemilanove-Diavolino +++ b/profiles/LoL-Shield_Uno-Duemilanove-Diavolino @@ -63,7 +63,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=5 ANIMATION_JOERN1=y ANIMATION_SNAKE=y -SNAKE_CYCLE_DELAY=100 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=100 SNAKE_TERMINATION_DELAY=60 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/profiles/borg-16 b/profiles/borg-16 index c8d11dd..c75a157 100644 --- a/profiles/borg-16 +++ b/profiles/borg-16 @@ -85,7 +85,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=5 ANIMATION_JOERN1=y ANIMATION_SNAKE=y -SNAKE_CYCLE_DELAY=100 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=100 SNAKE_TERMINATION_DELAY=60 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/profiles/borg-ancient b/profiles/borg-ancient index e62d820..414e68e 100644 --- a/profiles/borg-ancient +++ b/profiles/borg-ancient @@ -61,7 +61,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=20 ANIMATION_JOERN1=y ANIMATION_SNAKE=y -SNAKE_CYCLE_DELAY=100 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=100 SNAKE_TERMINATION_DELAY=60 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/profiles/borg-andre b/profiles/borg-andre index 9e4cba1..9da057d 100644 --- a/profiles/borg-andre +++ b/profiles/borg-andre @@ -82,7 +82,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=5 ANIMATION_JOERN1=y ANIMATION_SNAKE=y -SNAKE_CYCLE_DELAY=100 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=100 SNAKE_TERMINATION_DELAY=60 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/profiles/borg-ls b/profiles/borg-ls index 11dfe30..ee9390a 100644 --- a/profiles/borg-ls +++ b/profiles/borg-ls @@ -74,7 +74,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=5 ANIMATION_JOERN1=y ANIMATION_SNAKE=y -SNAKE_CYCLE_DELAY=50 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=50 SNAKE_TERMINATION_DELAY=60 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/profiles/borgjacke b/profiles/borgjacke index 3468712..40057cd 100644 --- a/profiles/borgjacke +++ b/profiles/borgjacke @@ -78,7 +78,8 @@ ANIMATION_SPIRAL=y SPIRAL_DELAY=5 ANIMATION_JOERN1=y ANIMATION_SNAKE=y -SNAKE_CYCLE_DELAY=100 +SNAKE_GAME_DELAY=200 +SNAKE_ANIM_DELAY=100 SNAKE_TERMINATION_DELAY=60 SNAKE_MAX_LENGTH=64 SNAKE_MAX_APPLES=10 diff --git a/src/animations/config.in b/src/animations/config.in index 2d21fdd..7f9d88c 100644 --- a/src/animations/config.in +++ b/src/animations/config.in @@ -9,7 +9,8 @@ comment "Animations" bool "Joern1" ANIMATION_JOERN1 dep_bool_menu "Snake" ANIMATION_SNAKE $RANDOM_SUPPORT - int "Snake Round Delay" SNAKE_CYCLE_DELAY 100 + int "Snake Game Round Delay" SNAKE_GAME_DELAY 200 + int "Snake Anim Round Delay" SNAKE_ANIM_DELAY 100 int "Snake Termination Delay" SNAKE_TERMINATION_DELAY 60 uint "Snake Max Length" SNAKE_MAX_LENGTH 64 int "Snake Max Apples" SNAKE_MAX_APPLES 10 diff --git a/src/games/snake/snake_game.c b/src/games/snake/snake_game.c index f89a445..9ba1a8d 100644 --- a/src/games/snake/snake_game.c +++ b/src/games/snake/snake_game.c @@ -51,9 +51,14 @@ game_descriptor_t snake_game_descriptor __attribute__((section(".game_descriptor #define SNAKE_MAX_APPLES 10 #endif -#if !defined SNAKE_CYCLE_DELAY || defined DOXYGEN +#if !defined SNAKE_GAME_DELAY || defined DOXYGEN /** Delay (in ms) between every state change. */ - #define SNAKE_CYCLE_DELAY 100 + #define SNAKE_GAME_DELAY 200 +#endif + +#if !defined SNAKE_ANIM_DELAY || defined DOXYGEN + /** Delay (in ms) between every state change. */ + #define SNAKE_ANIM_DELAY 100 #endif #if !defined SNAKE_TERMINATION_DELAY || defined DOXYGEN @@ -192,11 +197,21 @@ static snake_dir_t snake_queryJoystick(void) */ static void snake_initGameProtagonist(snake_protagonist_t *pprotSnake) { - pprotSnake->aSegments[0] = (pixel){NUM_COLS / 2, NUM_ROWS / 2}; - pprotSnake->aSegments[1] = (pixel){NUM_COLS / 2, NUM_ROWS / 2 - 1}; +#if NUM_ROWS > NUM_COLS + pprotSnake->aSegments[0] = + (pixel){(NUM_COLS - 2) / 2 + 1, (NUM_ROWS - 2) / 2 + 1}; + pprotSnake->aSegments[1] = + (pixel){(NUM_COLS - 2) / 2 + 1, (NUM_ROWS - 2) / 2}; + pprotSnake->dir = SNAKE_DIR_DOWN; +#else + pprotSnake->aSegments[0] = + (pixel){(NUM_COLS - 2) / 2 + 1, (NUM_ROWS - 2) / 2 + 1}; + pprotSnake->aSegments[1] = + (pixel){(NUM_COLS - 2) / 2 + 2, (NUM_ROWS - 2) / 2 + 1}; + pprotSnake->dir = SNAKE_DIR_RIGHT; +#endif pprotSnake->nTailIndex = 0; pprotSnake->nHeadIndex = 1; - pprotSnake->dir = SNAKE_DIR_UP; } #ifdef GAME_SNAKE @@ -403,7 +418,7 @@ void snake_engine(uint8_t bDemoMode) clear_screen(0); snake_drawBorder(); - for (uint8_t nAppleColor = 0; 1; nAppleColor ^= SNAKE_COLOR_APPLE) + for (uint8_t nTick = 0; 1; nTick ^= SNAKE_COLOR_APPLE) { // determine new direction #if defined ANIMATION_SNAKE && defined GAME_SNAKE @@ -415,48 +430,66 @@ void snake_engine(uint8_t bDemoMode) { snake_userControl(&protSnake, &dirLast); } + if (bDemoMode || nTick) { #elif defined ANIMATION_SNAKE snake_autoRoute(&protSnake, &apples); + { #else snake_userControl(&protSnake, &dirLast); + if (nTick) { #endif - // actually move head - pixel pxOldHead = protSnake.aSegments[protSnake.nHeadIndex]; - protSnake.nHeadIndex = (protSnake.nHeadIndex + 1u) % USNAKE_MAX_LENGTH; - protSnake.aSegments[protSnake.nHeadIndex] = - snake_nextDirection(pxOldHead, protSnake.dir); + // actually move head + pixel pxOldHead = protSnake.aSegments[protSnake.nHeadIndex]; + protSnake.nHeadIndex = (protSnake.nHeadIndex + 1u) % USNAKE_MAX_LENGTH; + protSnake.aSegments[protSnake.nHeadIndex] = + snake_nextDirection(pxOldHead, protSnake.dir); - // look if we have found an apple - if (!snake_checkForApple(&apples, - protSnake.aSegments[protSnake.nHeadIndex])) - { - // quit game if we hit something which is not an apple - if (get_pixel(protSnake.aSegments[protSnake.nHeadIndex])) + // look if we have found an apple + if (!snake_checkForApple(&apples, + protSnake.aSegments[protSnake.nHeadIndex])) { - snake_eliminateProtagonist(&protSnake); - return; + // quit game if we hit something which is not an apple + if (get_pixel(protSnake.aSegments[protSnake.nHeadIndex])) + { + snake_eliminateProtagonist(&protSnake); + return; + } + + // remove last segment + clearpixel(protSnake.aSegments[protSnake.nTailIndex]) + protSnake.nTailIndex = + (protSnake.nTailIndex + 1u) % USNAKE_MAX_LENGTH; + + // new apples + snake_spawnApples(&apples); } - - // remove last segment - clearpixel(protSnake.aSegments[protSnake.nTailIndex]) - protSnake.nTailIndex = - (protSnake.nTailIndex + 1u) % USNAKE_MAX_LENGTH; - - // new apples - snake_spawnApples(&apples); + // draw new head + setpixel(protSnake.aSegments[protSnake.nHeadIndex], + SNAKE_COLOR_PROTAGONIST); } - // draw new head - setpixel(protSnake.aSegments[protSnake.nHeadIndex], - SNAKE_COLOR_PROTAGONIST); // draw apples for (uint8_t i = apples.nAppleCount; i--;) { - setpixel(apples.aApples[i], nAppleColor); + // nTick also serves as blinking color + setpixel(apples.aApples[i], nTick); } - wait(SNAKE_CYCLE_DELAY); +#if defined ANIMATION_SNAKE && defined GAME_SNAKE + if (bDemoMode) + { + wait(SNAKE_ANIM_DELAY); + } + else + { + wait(SNAKE_GAME_DELAY / 2); + } +#elif defined ANIMATION_SNAKE + wait(SNAKE_ANIM_DELAY); +#else + wait(SNAKE_GAME_DELAY / 2); +#endif } } @@ -466,6 +499,9 @@ void snake_engine(uint8_t bDemoMode) void snake_game(void) { snake_engine(0); +#if defined GAME_SNAKE && defined SCROLLTEXT_SUPPORT + scrolltext("