Advertisement
hemalchevli

64pixels.c

Sep 19th, 2013
379
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.75 KB | None | 0 0
  1. /* -----------------------------------------------------------------------
  2.  * Title:    8x8 LED dot matrix animations
  3.  * Author:   Alexander Weber alex@tinkerlog.com
  4.  * Date:     21.12.2008
  5.  * Hardware: ATtiny2313V
  6.  * Software: AVRMacPack
  7.  *
  8.  */
  9.  
  10. #include <inttypes.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <avr/io.h>
  14. #include <avr/interrupt.h>
  15. #include <avr/eeprom.h>
  16. #include <util/delay.h>
  17. #include <avr/pgmspace.h>
  18. #include "font.h"
  19.  
  20. // Change these values to adjust scroll speeds and animation iterations
  21. #define ANIMATION_SCROLL_SPEED 80  // how fast to scroll the animations
  22. #define TEXT_SCROLL_SPEED 120      // how fast to scrill the text
  23. #define REPEAT_ANIMATION 10        // how often to repeat the animation if in cycling mode
  24. #define REPEAT_TEXT 5              // how often to repeat the text if in cycling mode
  25.  
  26. // How to add a new message:
  27. // * add the new message (only upper case, see font.h)
  28. // * adjust MAX_MESSAGES
  29. // * add the new message to messages
  30. // NOTE: messages may not be longer than 59 chars. Otherwise they will not fit in the buffer.
  31. //                                              123456789012345678901234567890123456789012345678901234567890
  32. const prog_char PROGMEM message_00[] PROGMEM = "   WTF!?! ";
  33. const prog_char PROGMEM message_01[] PROGMEM = "   I AM NO BOMB! ";
  34. const prog_char PROGMEM message_02[] PROGMEM = "   5   4   3   2   1  ...  BOOM! ";
  35. const prog_char PROGMEM message_03[] PROGMEM = "   I'M SORRY DAVE, I'M AFRAID I CAN'T DO THAT.  ";
  36. const prog_char PROGMEM message_04[] PROGMEM = "   NOW BYE ME A SOLDERING STATION ";
  37. const prog_char PROGMEM message_05[] PROGMEM = "   MAKE STUFF ";
  38. const prog_char PROGMEM message_06[] PROGMEM = "   IF YOU CAN'T OPEN IT, YOU DON'T OWN IT ";
  39. const prog_char PROGMEM message_07[] PROGMEM = "   1337 3L3X7RON!C5 !1!! ";
  40. const prog_char PROGMEM message_08[] PROGMEM = "   MY KUNG FU IS BETTER THAN YOURS ";
  41. const prog_char PROGMEM message_09[] PROGMEM = "   SUDO MAKE ME A SANDWICH ";
  42. const prog_char PROGMEM message_10[] PROGMEM = "   ZOMBIES AHEAD ";
  43. const prog_char PROGMEM message_11[] PROGMEM = "   HTTP://TINKERLOG.COM ";
  44.  
  45. #define MAX_MESSAGES 12
  46. PGM_P PROGMEM messages[] = {
  47.   message_00
  48.   ,message_01
  49.   ,message_02
  50.   ,message_03
  51.   ,message_04
  52.   ,message_05
  53.   ,message_06
  54.   ,message_07
  55.   ,message_08
  56.   ,message_09
  57.   ,message_10
  58.   ,message_11
  59. };
  60.  
  61. #define MAX_ANIMATIONS 3
  62. const prog_uint8_t PROGMEM sprite_00[] =
  63.   {
  64.     0x18,    // ___XX___
  65.     0x3C,    // __XXXX__
  66.     0x7E,    // _XXXXXX_
  67.     0xDB,    // X_XXXX_X
  68.     0xFF,    // XXXXXXXX
  69.     0x24,    // __X__X__
  70.     0x5A,    // _X_XX_X_
  71.     0xA5     // X_X__X_X
  72.   };
  73.  
  74. const prog_uint8_t PROGMEM sprite_01[8] =
  75.   {
  76.     0x18,    // ___XX___
  77.     0x3C,    // __XXXX__
  78.     0x7E,    // _XXXXXX_
  79.     0xDB,    // X_XXXX_X
  80.     0xFF,    // XXXXXXXX
  81.     0x24,    // __X__X__
  82.     0x42,    // _X____X_
  83.     0x24     // __X__X__
  84.   };
  85.  
  86. const prog_uint8_t PROGMEM sprite_02[8] =
  87.   {
  88.     0x00,    // ________
  89.     0x00,    // ________
  90.     0x14,    // ___X_X__
  91.     0x3E,    // __XXXXX_
  92.     0x3E,    // __XXXXX_
  93.     0x1C,    // ___XXX__
  94.     0x08,    // ____X___
  95.     0x00     // ________
  96.   };
  97.  
  98. const prog_uint8_t PROGMEM sprite_03[8] =
  99.   {
  100.     0x00,    // ________
  101.     0x66,    // _XX__XX_
  102.     0xFF,    // XXXXXXXX
  103.     0xFF,    // XXXXXXXX
  104.     0xFF,    // XXXXXXXX
  105.     0x7E,    // _XXXXXX_
  106.     0x3C,    // __XXXX__
  107.     0x18     // ___XX___
  108.   };
  109.  
  110. const prog_uint8_t PROGMEM sprite_04[8] =
  111.   {
  112.     0x24,    // __X__X__
  113.     0x7E,    // _XXXXXX_
  114.     0xDB,    // XX_XX_XX
  115.     0xFF,    // XXXXXXXX
  116.     0xA5,    // X_X__X_X
  117.     0x99,    // X__XX__X
  118.     0x81,    // X______X
  119.     0xC3     // XX____XX
  120.   };
  121.  
  122. const prog_uint8_t PROGMEM sprite_05[8] =
  123.   {
  124.     0x24,    // __X__X__
  125.     0x18,    // ___XX___
  126.     0x7E,    // X_XXXX_X
  127.     0xDB,    // XX_XX_XX
  128.     0xFF,    // XXXXXXXX
  129.     0xDB,    // X_XXXX_X
  130.     0x99,    // X__XX__X
  131.     0xC3     // XX____XX
  132.   };
  133.  
  134.  
  135.  
  136. uint8_t mode_ee EEMEM = 0;                      // stores the mode in eeprom
  137. static uint8_t screen_mem[8];           // screen memory
  138. static uint8_t active_row;          // active row
  139. static uint8_t buffer[60];                      // stores the active message or sprite
  140. static uint8_t message_ptr = 0;                 // points to the active char in the message
  141. static uint8_t message_displayed = 0;           // how often has the message been displayed?
  142. static uint8_t active_char = 0;                 // stores the active char
  143. static uint8_t message_length = 0;              // stores the length of the active message
  144. static uint8_t char_ptr = 0;                    // points to the active col in the char
  145. static uint8_t char_length = 0;                 // stores the length of the active char
  146. static volatile uint16_t counter = 0;           // used for delay function
  147.  
  148. // prototypes
  149. void delay_ms(uint16_t delay);
  150. void copy_to_display(int8_t x, int8_t y, uint8_t sprite[]);
  151. void display_active_row(void);
  152. void show_char();
  153. void clear_screen(void);
  154. void copy_to_buffer(const prog_uint8_t sprite[8]);
  155. void scroll_animation(const prog_uint8_t sprite_1[], const prog_uint8_t sprite_2[]);
  156.  
  157.  
  158.  
  159. /*
  160.  * ISR TIMER0_OVF_vect
  161.  * Handles overflow interrupts of timer 0.
  162.  *
  163.  * 4MHz
  164.  * ----
  165.  * Prescaler 8 ==> 1953.1 Hz
  166.  * Complete display = 244 Hz
  167.  *
  168.  */
  169. ISR(TIMER0_OVF_vect) { 
  170.   display_active_row();
  171.   counter++;
  172. }
  173.  
  174.  
  175.  
  176. /*
  177.  * delay_ms
  178.  * Uses the counter that is incremented by the ISR.
  179.  * Max delay is 32767ms.
  180.  */
  181. void delay_ms(uint16_t delay) {
  182.   while (!(PIND & (1 << PD6))) {}   // used to stop the animation when PD6 goes LOW
  183.   uint16_t t = delay * 2;
  184.   counter = 0;
  185.   while (counter < t) {}
  186. }
  187.  
  188.  
  189.  
  190. /*
  191.  * copy_to_display
  192.  * Copies sprite data to the screen memory at the given position.
  193.  */
  194. void copy_to_display(int8_t x, int8_t y, uint8_t sprite[8]) {
  195.   int8_t i, t;
  196.   uint8_t row;
  197.   for (i = 0; i < 8; i++) {
  198.     t = i-y;
  199.     row = ((t >= 0) && (t < 8)) ? sprite[t] : 0x00;
  200.     row = (x >= 0) ? (row >> x) : (row << -x);
  201.     screen_mem[i] = row;
  202.   }
  203. }
  204.  
  205.  
  206.  
  207. /*
  208.  * display_active_col
  209.  * Deactivates the active column and displays the next one.
  210.  * Data is read from screen_mem.
  211.  *
  212.  *      ATtiny2313
  213.  * 16 - PD0    PB7 - 1
  214.  * 15 - PD1    PB6 - 2
  215.  * 14 - PA1    PB5 - 3
  216.  * 13 - PA0    PB4 - 4
  217.  * 12 - PD2    PB3 - 5
  218.  * 11 - PD3    PB2 - 6
  219.  * 10 - PD4    PB1 - 7
  220.  *  9 - PD5    PB0 - 8
  221.  *
  222.  * NFM-12883 common anode          |
  223.  *     A0B5B4D4B2D3D1D0      +-----+
  224.  * PD5 o o o o o o o o       |     |
  225.  * PA1 o o o o o o o o      _+_    |
  226.  * PB0 o o o o o o o o      \ /    |
  227.  * PD2 o o o o o o o o     __V__   |
  228.  * PB7 o o o o o o o o       |     |
  229.  * PB1 o o o o o o o o    ---+-----C---
  230.  * PB6 o o o o o o o o             |
  231.  * PB3 o o o o o o o o
  232.  *
  233.  */
  234. void display_active_row(void) {
  235.  
  236.   uint8_t row;
  237.  
  238.   // shut down all rows and columns
  239.   PORTA = (0 << PA0) | (1 << PA1);
  240.   PORTB = (0 << PB5) | (0 << PB4) | (0 << PB2) | (1 << PB0) |
  241.           (1 << PB7) | (1 << PB1) | (1 << PB6) | (1 << PB3);
  242.   PORTD = (0 << PD4) | (0 << PD3) | (0 << PD1) | (0 << PD0) |
  243.           (1 << PD5) | (1 << PD2) | (1 << PD6);
  244.  
  245.   // next row
  246.   active_row = (active_row+1) % 8;
  247.   row = screen_mem[active_row];
  248.  
  249.   // output all columns, switch leds on.
  250.   // column 1
  251.   if ((row & 0x80) == 0x80) {
  252.     PORTA |= (1 << PA0);    
  253.   }
  254.   // column 2
  255.   if ((row & 0x40) == 0x40) {
  256.     PORTB |= (1 << PB5);    
  257.   }
  258.   // column 3
  259.   if ((row & 0x20) == 0x20) {
  260.     PORTB |= (1 << PB4);    
  261.   }
  262.   // column 4
  263.   if ((row & 0x10) == 0x10) {
  264.     PORTD |= (1 << PD4);    
  265.   }
  266.   // column 5
  267.   if ((row & 0x08) == 0x08) {
  268.     PORTB |= (1 << PB2);    
  269.   }
  270.   // column 6
  271.   if ((row & 0x04) == 0x04) {
  272.     PORTD |= (1 << PD3);    
  273.   }
  274.   // column 7
  275.   if ((row & 0x02) == 0x02) {
  276.     PORTD |= (1 << PD1);    
  277.   }
  278.   // column 8
  279.   if ((row & 0x01) == 0x01) {
  280.     PORTD |= (1 << PD0);    
  281.   }
  282.  
  283.   // activate row
  284.   switch (active_row) {
  285.   case 0:
  286.     PORTD &= ~(1 << PD5);
  287.     break;
  288.   case 1:
  289.     PORTA &= ~(1 << PA1);
  290.     break;
  291.   case 2:
  292.     PORTB &= ~(1 << PB0);
  293.     break;
  294.   case 3:
  295.     PORTD &= ~(1 << PD2);
  296.     break;
  297.   case 4:
  298.     PORTB &= ~(1 << PB7);
  299.     break;
  300.   case 5:
  301.     PORTB &= ~(1 << PB1);
  302.     break;
  303.   case 6:
  304.     PORTB &= ~(1 << PB6);
  305.     break;
  306.   case 7:
  307.     PORTB &= ~(1 << PB3);
  308.     break;
  309.   }
  310.  
  311. }
  312. /*
  313.  * Use this method, if you have a common cathode matrix.
  314.  */
  315. /*
  316. void display_active_row(void) {
  317.  
  318.   uint8_t row;
  319.  
  320.   // shut down all rows and columns
  321.   PORTB = 0x34;
  322.   PORTD = 0x1B;
  323.   PORTA = 0x01;
  324.  
  325.   // next row
  326.   active_row = (active_row+1) % 8;
  327.   row = screen_mem[active_row];
  328.  
  329.   // output all columns, switch leds on.
  330.   // column 1
  331.   if ((row & 0x80) == 0x80) {
  332.     PORTA &= ~(1 << PA0);    
  333.   }
  334.   // column 2
  335.   if ((row & 0x40) == 0x40) {
  336.     PORTB &= ~(1 << PB5);    
  337.   }
  338.   // column 3
  339.   if ((row & 0x20) == 0x20) {
  340.     PORTB &= ~(1 << PB4);    
  341.   }
  342.   // column 4
  343.   if ((row & 0x10) == 0x10) {
  344.     PORTD &= ~(1 << PD4);    
  345.   }
  346.   // column 5
  347.   if ((row & 0x08) == 0x08) {
  348.     PORTB &= ~(1 << PB2);    
  349.   }
  350.   // column 6
  351.   if ((row & 0x04) == 0x04) {
  352.     PORTD &= ~(1 << PD3);    
  353.   }
  354.   // column 7
  355.   if ((row & 0x02) == 0x02) {
  356.     PORTD &= ~(1 << PD1);    
  357.   }
  358.   // column 8
  359.   if ((row & 0x01) == 0x01) {
  360.     PORTD &= ~(1 << PD0);    
  361.   }
  362.  
  363.   // activate row
  364.   switch (active_row) {
  365.   case 0:
  366.     PORTD |= (1 << PD5);
  367.     break;
  368.   case 1:
  369.     PORTA |= (1 << PA1);
  370.     break;
  371.   case 2:
  372.     PORTB |= (1 << PB0);
  373.     break;
  374.   case 3:
  375.     PORTD |= (1 << PD2);
  376.     break;
  377.   case 4:
  378.     PORTB |= (1 << PB7);
  379.     break;
  380.   case 5:
  381.     PORTB |= (1 << PB1);
  382.     break;
  383.   case 6:
  384.     PORTB |= (1 << PB6);
  385.     break;
  386.   case 7:
  387.     PORTB |= (1 << PB3);
  388.     break;
  389.   }
  390.  
  391. }
  392. */
  393.  
  394.  
  395. /*
  396.  * show_char
  397.  * Displays the actual message.
  398.  * Scrolls the screen to the left and draws new pixels on the right.
  399.  */
  400. void show_char() {
  401.   uint8_t i;
  402.   uint8_t b;
  403.  
  404.   // blit the screen to the left
  405.   for (i = 0; i < 8; i++) {
  406.     screen_mem[i] <<= 1;
  407.   }
  408.   // advance a char if needed
  409.   if (char_ptr == char_length) {
  410.     message_ptr++;
  411.     if (message_ptr == message_length) {
  412.       message_ptr = 0;
  413.       message_displayed++;
  414.     }
  415.     active_char = buffer[message_ptr] - CHAR_OFFSET;
  416.     char_length = pgm_read_byte(&font[active_char * 4 + 3]);
  417.     char_ptr = 0;
  418.     return; // this makes the space between two chars
  419.   }
  420.   // read pixels for current column of char
  421.   b = pgm_read_byte(&font[active_char * 4 + char_ptr++]);
  422.   // write pixels into screen memory
  423.   for (i = 0; i < 7; i++) {
  424.     if ((b & (1 << i)) == (1 << i)) {
  425.       screen_mem[i+1] |= 0x01;
  426.     }
  427.   }
  428. }
  429.  
  430.  
  431.  
  432. /*
  433.  * clear_screen
  434.  */
  435. void clear_screen(void) {
  436.   uint8_t i;
  437.   for (i = 0; i < 8; i++) {
  438.     screen_mem[i] = 0x00;
  439.   }
  440. }
  441.  
  442.  
  443.  
  444. /*
  445.  * copy_to_buffer
  446.  * Copies the given sprite from PROGMEM to RAM.
  447.  */
  448. void copy_to_buffer(const prog_uint8_t sprite[8]) {
  449.   memcpy_P(buffer, sprite, 8);
  450. }
  451.  
  452.  
  453.  
  454. /*
  455.  * scroll_animation
  456.  * Uses sprite_1 and sprite_2 to draw a simple animation.
  457.  */
  458. void scroll_animation(const prog_uint8_t sprite_1[8], const prog_uint8_t sprite_2[8]) {
  459.   uint8_t i;
  460.   int8_t x;
  461.   for (i = 0; i < REPEAT_ANIMATION; i++) {
  462.     copy_to_buffer(sprite_1);
  463.     for (x = -8; x <= 0; x++) {
  464.       copy_to_display(x, 0, buffer);
  465.       delay_ms(ANIMATION_SCROLL_SPEED);
  466.     }
  467.     delay_ms(200);
  468.     copy_to_buffer(sprite_2);
  469.     copy_to_display(0, 0, buffer);
  470.     delay_ms(200);
  471.     copy_to_buffer(sprite_1);
  472.     copy_to_display(0, 0, buffer);
  473.     delay_ms(200);
  474.     copy_to_buffer(sprite_2);
  475.     copy_to_display(0, 0, buffer);
  476.     delay_ms(200);
  477.     copy_to_buffer(sprite_1);
  478.     for (x = 0; x < 8; x++) {
  479.       copy_to_display(x, 0, buffer);
  480.       delay_ms(ANIMATION_SCROLL_SPEED);
  481.     }
  482.   }
  483. }
  484.  
  485.  
  486.  
  487. int main(void) {
  488.  
  489.   uint8_t i = 0;
  490.   uint8_t mode = 0;
  491.   uint8_t cycle = 0;
  492.  
  493.   // timer 0 setup, prescaler 8
  494.   TCCR0B |= (1 << CS01);
  495.  
  496.   // enable timer 0 interrupt
  497.   TIMSK |= (1 << TOIE0);   
  498.  
  499.   // define outputs
  500.   DDRA |= 0x03;  
  501.   DDRB |= 0xFF;
  502.   DDRD |= 0x3F;
  503.  
  504.   // shut down all rows and columns, enable column 1
  505.   PORTA = (1 << PA0) | (1 << PA1);
  506.   PORTB = (0 << PB5) | (0 << PB4) | (0 << PB2) | (1 << PB0) |
  507.           (1 << PB7) | (1 << PB1) | (1 << PB6) | (1 << PB3);
  508.   PORTD = (0 << PD4) | (0 << PD3) | (0 << PD1) | (0 << PD0) |
  509.           (1 << PD5) | (1 << PD2);
  510.  
  511.   // enable pull ups
  512.   PORTD |= (1 << PD6);
  513.  
  514.   // say hello, toggle row 1 (pixel 0,0)
  515.   for (i = 0; i < 5; i++) {
  516.     PORTD &= ~(1 << PD5);
  517.     _delay_ms(50);
  518.     PORTD |= (1 << PD5);
  519.     _delay_ms(50);
  520.   }
  521.  
  522.   // read last mode from eeprom
  523.   // 0 mean cycle through all modes and messages
  524.   mode = eeprom_read_byte(&mode_ee);
  525.   if ((mode == 0) || (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1))) {
  526.     mode = 1;
  527.     cycle = 1;
  528.   }
  529.   eeprom_write_byte(&mode_ee, mode + 1);  
  530.  
  531.   sei();
  532.  
  533.   while (1) {
  534.  
  535.     switch (mode) {
  536.     case 1:
  537.       scroll_animation(sprite_00, sprite_01);
  538.       break;
  539.     case 2:
  540.       for (i = 0; i < REPEAT_ANIMATION; i++) {
  541.         copy_to_buffer(sprite_03);
  542.         copy_to_display(0, 0, buffer);
  543.         delay_ms(750);
  544.         copy_to_buffer(sprite_02);        
  545.         copy_to_display(0, 0, buffer);
  546.         delay_ms(180);
  547.       }
  548.       break;
  549.     case 3:
  550.       scroll_animation(sprite_04, sprite_05);
  551.       break;
  552.     default:
  553.       strcpy_P(buffer, (uint8_t*)pgm_read_word(&(messages[mode - (MAX_ANIMATIONS+1)])));
  554.       message_length = strlen(buffer);
  555.       while (message_displayed < REPEAT_TEXT) {
  556.         show_char();
  557.         delay_ms(TEXT_SCROLL_SPEED);
  558.       }
  559.       message_displayed = 0;
  560.       break;
  561.     }
  562.  
  563.     // cycle through all modes
  564.     if (cycle) {
  565.       mode++;
  566.       clear_screen();
  567.       if (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1)) {
  568.         mode = 1;
  569.       }
  570.     }
  571.  
  572.   }
  573.  
  574.   return 0;
  575.  
  576. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement