NetAgent

CM-5 Canton LED Display v2 Arduino Uno

Jun 13th, 2018
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.46 KB | None | 0 0
  1. // 64x32 LED display matrix
  2. // based upon original code from canton-electonics
  3. // Arduino 1.0.5 UNO R3
  4. // Credits go to those who did all the hard work at http://www.housedillon.com/?p=1272
  5. //#include <arv/pgmspace.h>
  6.  
  7. #define HEIGHT 16
  8. #define WIDTH 64
  9.  
  10. #define ROWCHANGE 4   //Rows change direction every X rows //default is 4
  11. #define INVERT 0      //LEDs will be lit in reverse order resulting in more LED active at once //default is 0
  12. #define MOVEDELAY 200 //How much delay should there be before the rows move //default is 131, CM5 rate is 200ms
  13.  
  14. // Connections to board
  15. const byte latchPin = 8;
  16. const byte clockPin = 12;
  17. const byte data_R1 = 11;
  18. const byte data_R2 = 10;
  19.  
  20. const byte en_74138 = 2;
  21. const byte la_74138 = 3;
  22. const byte lb_74138 = 4;
  23. const byte lc_74138 = 5;
  24. const byte ld_74138 = 6;
  25.  
  26. byte ScanRow = 0;
  27. unsigned long counter;
  28.  
  29. byte buffer[256] = { // Display buffer (which is scanned by the interrupt timer) of 8x32 bytes
  30.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  31.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  32.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  33.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  34.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  35.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  36.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  37.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  38.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  39.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  40.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  41.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  42.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  44.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  45.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  46. };
  47.  
  48. // set a single pixel on or off
  49. void HardwarePlot(byte x, byte y, byte z) {
  50.  
  51.   if (z == INVERT) {
  52.     //bitWrite(buffer[(y << 3) + (x >> 3)], 7 - (x & 7), 0x01);
  53.     bitWrite(buffer[(y * 8) + (x >> 3)], 7 - (x & 7), 0x01);
  54.   } else {
  55.     //bitWrite(buffer[(y << 3) + (x >> 3)], 7 - (x & 7), 0x00);
  56.     bitWrite(buffer[(y * 8) + (x >> 3)], 7 - (x & 7), 0x00);
  57.   }
  58. };
  59.  
  60. void shiftOut(byte row) { // fast routine to shove out 8 columns into two rows via board's shift registers
  61.   for (byte column = 0; column < 8; column++) {
  62.     byte index = column + (row << 3);
  63.     for (byte i = 0; i < 8; i++) {
  64.       PORTB &= ~(3 << (data_R1 - 8)); // data_R2 is LOW; data_R1 is LOW;
  65.       PORTB &= ~(1 << (clockPin - 8)); // digitalWrite(clockPin,LOW);
  66.       PORTB |= !((buffer[index] >> (7 - i)) & 0x01) << (data_R1 - 8); // top set of rows
  67.       PORTB |= !((buffer[index + 128] >> (7 - i)) & 0x01) << (data_R2 - 8); // bottom set of rows
  68.       PORTB |= 1 << (clockPin - 8); // digitalWrite(clockPin,HIGH);
  69.     };
  70.   };
  71. };
  72.  
  73. // Scan a pair of rows on to the display from "buffer" via the interrupt
  74. ISR(TIMER2_COMPA_vect) {
  75.   cli();
  76.   //digitalWrite(en_74138, HIGH); // Turn off display <-- causes issue with flickering
  77.   shiftOut(ScanRow); // Shift out 8 columns
  78.   digitalWrite(latchPin, LOW);
  79.   digitalWrite(latchPin, HIGH);
  80.   PORTD = (ScanRow << 3) | (PORTD & 0X87); // Highlight row: pins 3 4 5 6 (la_74138 lb_74138 lc_74138 ld_74138)
  81.   //digitalWrite(en_74138, LOW); // Turn on display <-- causes issue with flickering
  82.   ScanRow++; // Do the next pair of rows next time this routine is called
  83.   if (ScanRow == 16) ScanRow = 0;
  84.   sei();
  85. };
  86.  
  87. void setup() {
  88.  
  89.   // Set up Timer2 as the scanning interrupt timer
  90.   cli(); // clear interrupts
  91.   TCCR2A = 0; TCCR2B = 0; TCNT2 = 0;
  92.   TCCR2B |= (1 << CS12) | (1 << CS10); // Set 1024 prescaler
  93.   // 160Hz scan rate = 10 frames/second (16 pairs of rows)
  94.   OCR2A = 97; // 97 = (16,000,000 / (1024*160)) - 1
  95.   TCCR2A |= (1 << WGM21); TIMSK2 |= (1 << OCIE2A);
  96.  
  97.   pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT);
  98.   pinMode(data_R1, OUTPUT); pinMode(data_R2, OUTPUT);
  99.  
  100.   pinMode(en_74138, OUTPUT);
  101.   pinMode(la_74138, OUTPUT); pinMode(lb_74138, OUTPUT);
  102.   pinMode(lc_74138, OUTPUT); pinMode(ld_74138, OUTPUT);
  103.  
  104.   digitalWrite(en_74138, LOW);
  105.   digitalWrite(data_R1, HIGH); digitalWrite(data_R2, HIGH);
  106.   counter = millis();
  107.   sei(); //allow interrupts
  108. };
  109.  
  110.  
  111. // Note that there's no need to do anything with the screen in the main loop.
  112. // Whatever's in "buffer" is constantly scanned out.
  113. void loop() {
  114.  
  115.   cm5();
  116.  
  117. };
  118.  
  119. long long array[2][16];
  120.  
  121. byte getPixel(byte x, byte y, byte whichArray) {
  122.  
  123.   unsigned long long temp = (1ULL << y);
  124.   if (array[whichArray][x] & temp) {
  125.     return 1; //the yth bit was set, so return 1.
  126.   }
  127.   else {
  128.     return 0; //the yth bit was clear, so return 0;
  129.   }
  130. }
  131.  
  132. void setPixel(byte x, byte y, byte whichArray, byte pixel) {
  133.  
  134.   unsigned long long temp = (1ULL << y);
  135.   if (pixel) {
  136.     array[whichArray][x] |= temp;
  137.   }
  138.   else {
  139.     array[whichArray][x] &= ~temp;
  140.   }
  141. }
  142.  
  143.  
  144. void clearArray(byte no) {
  145.   byte i, j; for (j = 0; j < HEIGHT; j++) {
  146.     for (i = 0; i < WIDTH; i++ ) {
  147.       setPixel(i, j, no, 0);
  148.     }
  149.   }
  150. }
  151.  
  152. #define RNUM_SEED 0xBAD
  153. static uint16_t rnum = RNUM_SEED;
  154.  
  155. static uint16_t get_random_bit(void)
  156. {
  157. #define X rnum
  158.  
  159.   uint16_t lfsr_bit = ((X >> 0) ^ (X >> 1) ^ (X >> 3) ^ (X >> 12)) & 1;
  160.  
  161.   uint16_t rand_bit = (X | (X >> 2)) & 1;
  162.  
  163. #undef X
  164.  
  165.   rnum = (lfsr_bit << 15) | (rnum >> 1);
  166.  
  167.   return rand_bit;
  168.  
  169. }
  170.  
  171.  
  172. void paintCM5() {
  173.   int i, j; bool pixel;
  174.  
  175.   for (i = 0; i < 16; i++ ) {
  176.     for (j = 0; j < 32; j++) {
  177.  
  178.       pixel = getPixel(i, j, 0);
  179.  
  180.       if (j & 4) {
  181.         if (pixel == 1 ) {
  182.           HardwarePlot(j, i, 0);
  183.           HardwarePlot(j + 32, i, 0);
  184.         }
  185.         else {
  186.           HardwarePlot(j, i, 1);
  187.           HardwarePlot(j + 32, i, 1);
  188.         }
  189.       }
  190.       else if (pixel == 1 ) {
  191.         HardwarePlot(j, 15 - i, 0);
  192.         HardwarePlot(j + 32, 15 - i, 0);
  193.  
  194.       }
  195.       else {
  196.         HardwarePlot(j, 15 - i, 1);
  197.         HardwarePlot(j + 32, 15 - i, 1);
  198.       }
  199.  
  200.     }
  201.   }
  202. }
  203.  
  204.  
  205. void setPixelunsafe(byte x, byte y, byte whichArray, byte pixel) {
  206.  
  207.   unsigned long long temp = (1ULL << y);
  208.   if (pixel) {
  209.     array[whichArray][x] |= temp;
  210.   }
  211.   else {
  212.     array[whichArray][x] &= ~temp;
  213.   }
  214. }
  215.  
  216. void cm5() {
  217.  
  218.   int pixel, i, j;
  219.   int count = 0;
  220.   clearArray(0);
  221.   //cm5 mode 7
  222.   uint16_t gen_bit;
  223.  
  224.   uint16_t rnum = 1;
  225.  
  226.   while (count < 3080) {
  227.  
  228.     for (j = 31; j >= 0; j-- ) {
  229.  
  230.       uint16_t bit = get_random_bit();
  231.  
  232.       if (bit == 0) {
  233.         setPixelunsafe(16, j, 0, 1);
  234.       }
  235.     }
  236.  
  237.     for (j = 0; j < 32; j++) {
  238.       for (i = 0; i < 16 + 1; i++) {
  239.         pixel = getPixel(i + 1, j, 0); if (pixel == 1)setPixelunsafe(i, j, 0, 1); else setPixelunsafe(i, j, 0, 0);
  240.       }
  241.     }
  242.  
  243.     count++;
  244.  
  245.     if (count > 0) {
  246.       paintCM5();
  247.       delay(MOVEDELAY);
  248.     }
  249.   }
  250. }
Advertisement
Add Comment
Please, Sign In to add comment