Advertisement
grist

I2C Test Slave II

Feb 11th, 2013
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.87 KB | None | 0 0
  1. /*
  2.  * SpeedTestSlave.c
  3.  *
  4.  * Created: 1/28/2013 9:53:06 PM
  5.  *  Author: grist.carrigafoyl
  6.  
  7.  A test bed for testing I2C comms under various conditions.
  8.  
  9.  */
  10. #define F_CPU 8000000UL  //  8Mhz
  11.  
  12. #include <avr/io.h>
  13. #include <util/delay.h>
  14. #include <avr/interrupt.h> // for I2C
  15. #include "usiTwiSlave.h" // Don Blake's library
  16.  
  17. // The I2C address for this slave device
  18. #define SLAVE_ADDR 0x01
  19. #define PACKET_SIZE 16 // Max bytes to receive at a time
  20. #define END_MARKER 255 // Signals the end of transmission
  21. // Having a delay between displaying segments helps the persistence of vision and makes the segments brighter.
  22. // Much larger than this you will see noticeable flickering, much lower and you get dimmed segments.
  23. #define POV_DELAY 5 // ms delay for persistence of vision
  24. #define NUM_DIGITS 4 // How many digits on the display
  25.  
  26. // Number bitmaps. Which LEDs to light up to represent each digit
  27. const uint8_t number_maps[10] = {
  28.     //abcdefgp - 1 for on, 0 for off.
  29.     0b11111100, // 0
  30.     0b01100000, // 1
  31.     0b11011010, // 2
  32.     0b11110010, // 3
  33.     0b01100110, // 4
  34.     0b10110110, // 5
  35.     0b10111110, // 6
  36.     0b11100000, // 7
  37.     0b11111110, // 8
  38.     0b11110110,  // 9
  39. };
  40. const uint8_t PATTERN_c = 0b00011010; // lower case 'c' for degrees display
  41.  
  42. // Segment to pin mapping.
  43. enum SEGMENT_PINS {
  44.     seg_a = _BV(PD0),
  45.     seg_b = _BV(PD1),
  46.     seg_c = _BV(PB6),
  47.     seg_d = _BV(PB4),
  48.     seg_e = _BV(PB3),
  49.     seg_f = _BV(PB2),
  50.     seg_g = _BV(PB1),
  51.     seg_dp = _BV(PB0)
  52. };
  53. // Digit to pin mapping.
  54. enum DIGIT_PINS {
  55.     d1 = _BV(PD3),
  56.     d2 = _BV(PD4),
  57.     d3 = _BV(PD5),
  58.     d4 = _BV(PD6)
  59. };
  60.  
  61. // The colon and degree indicator LEDs
  62. const uint8_t COLON_PIN = _BV(PA0);
  63. const uint8_t DEG_PIN = _BV(PA1); // degrees indicator (apostrophe)
  64.  
  65.  
  66. // Digit and segment pins
  67. uint8_t digits[4] = {d1,d2,d3,d4};
  68. // Segment pins are split over 2 ports as I2C needs 2 pins on PORTB
  69. uint8_t portb_segment_mask = (seg_c | seg_d | seg_e | seg_f | seg_g | seg_dp);
  70. uint8_t portd_segment_mask = (seg_a | seg_b);
  71. volatile uint8_t data[PACKET_SIZE]; // this will hold the data to be received
  72.  
  73. // Function prototypes
  74. void displayNumber();
  75. void showPattern(uint8_t pattern);
  76. void showVerticalBar(uint8_t position);
  77.  
  78. int main(void)
  79. {
  80.     int total,i;
  81.     int counter = 0;
  82.     uint8_t temp = 0;
  83.     // Set the pin modes for output
  84.     DDRA |= (COLON_PIN | DEG_PIN);
  85.     DDRB |= portb_segment_mask; // all pins except SDA & SCL (PB5 & 7) on PortB are output
  86.     DDRD |= (d1 | d2 | d3 | d4 | portd_segment_mask );  // the digit selector pins & 2 of the segment pins
  87.  
  88.     //testDisplayNumber();
  89.    
  90.     // Initialise the I2C interface
  91.     usiTwiSlaveInit(SLAVE_ADDR);
  92.     // Enable global interrupts (required for I2C)
  93.     sei();
  94.  
  95.     // main loop
  96.     for(;;) { // forever
  97.         // Check to see if there's data to read in
  98.         if (usiTwiDataInReceiveBuffer()) {
  99.             // get some bytes
  100.             counter = 0;
  101.             //while (usiTwiDataInReceiveBuffer()) {
  102.             //for(counter=0;counter<PACKET_SIZE;counter++) {
  103.             while(1) {
  104.                 temp = usiTwiReceiveByte();
  105.                 if (temp == END_MARKER) {
  106.                     break;
  107.                 } else {
  108.                     data[counter] = temp;
  109.                     counter++;
  110.                 }              
  111.             }
  112.             // Add them up
  113.             total = 0;
  114.             for (i=0;i<counter;i++) {
  115.                 total += data[i];
  116.             }
  117.  
  118.             // Displaying 4 digits takes 20ms. Display for 5 seconds.
  119.             for(i=0;i<250;i++) {
  120.                 displayNumber(total);
  121.             }          
  122.         }
  123.         // show the waiting pattern
  124.         showVerticalBar(counter++);
  125.         counter %= 8;
  126.     }
  127. }
  128.  
  129. //----------------------------------------------------------------------------
  130. // Functions
  131. //----------------------------------------------------------------------------
  132. void testDisplayNumber()
  133. { // Testing displayNumber to make sure it works as intended
  134.     int i;
  135.     for(;;) {
  136.         for (i=0;i<10000;i++) {
  137.             displayNumber(i);
  138.         }      
  139.     }
  140. }
  141.  
  142.  
  143. void displayNumber(int number) {
  144.     // show the data on the display
  145.    
  146.     // Flags for various display options
  147.     bool show_colon = false;
  148.     bool show_apostrophe = false;
  149.    
  150.     uint8_t pattern[4] = {0,0,0,0};  // will hold the raw bitmap of the pattern to be shown on the display
  151.     int temp = number;
  152.  
  153.     // Convert the 4 bytes to an integer, but current display can only show 9999 max
  154.  
  155.     temp %= 10000;
  156.     // convert the integer to single digit patterns for display
  157.     pattern[0] = number_maps[temp/1000];
  158.     temp %= 1000;
  159.     pattern[1] = number_maps[temp/100];
  160.     temp %= 100;
  161.     pattern[2] = number_maps[temp/10];
  162.     temp %= 10;
  163.     pattern[3] = number_maps[temp];
  164.    
  165.     // Time to display what we've got
  166.     // set the colon and apostrophe as required
  167.     if (show_colon == true) { PORTA |= COLON_PIN; } else {  PORTA &= ~COLON_PIN; }
  168.     if (show_apostrophe == true) { PORTA |= DEG_PIN; } else { PORTA &= ~DEG_PIN; }
  169.  
  170.     // // Now show the pattern.
  171.     for (int d=0 ; d<NUM_DIGITS ; d++) {
  172.         // Choose the digit to display by setting its pin HIGH and
  173.         // all the other pins LOW.
  174.         PORTD &= ~( d1 | d2 | d3 | d4);
  175.         PORTD |= digits[d];
  176.         showPattern(pattern[d]);//
  177.     }
  178.  
  179. }
  180. //----------------------------------------------------------------------------
  181. void showVerticalBar(uint8_t position)
  182. { // Show a vertical bar in the position. Each digit has 2 bars, and are numbered
  183.   // left to right starting at 0. This doesn't have to be multiplexed as only 1
  184.   // digit is ever displaying something at a time. Used as a simple idle indicator.
  185.     #define bar1 0b00001100
  186.     #define bar2 0b01100000
  187.     uint8_t bar, digit;
  188.    
  189.     if ((float)position/2 == position/2) {
  190.         bar = bar1;
  191.     } else {
  192.         bar = bar2;
  193.     }
  194.     digit = position/2;
  195.     // Choose the digit to display by setting its pin HIGH and
  196.     // all the other pins LOW.
  197.     PORTD &= ~( d1 | d2 | d3 | d4);
  198.     PORTD |= digits[digit];
  199.     showPattern(bar);
  200.  
  201.  
  202. }
  203. //----------------------------------------------------------------------------
  204. void showPattern(uint8_t pattern)
  205. {   // show the current pattern on the currently selected digit
  206.     // First set all the digit pins HIGH to turn them off so the
  207.     // previous digit doesn't get ghosted onto the new segment
  208.     // Segments a & b are on PORTD, the rest are on PORTB
  209.     PORTD |= (portd_segment_mask);
  210.     PORTB |= (portb_segment_mask);
  211.  
  212.     // Have to manipulate the pins one at a time so as not to interfere with I2C
  213.     // PORTD segments
  214.     if ((pattern & 128) == 128) { PORTD &= ~seg_a; } else { PORTD |= seg_a; }
  215.     if ((pattern & 64) == 64)   { PORTD &= ~seg_b; } else { PORTD |= seg_b; }
  216.     // PORTB segments
  217.     if ((pattern & 32) == 32)   { PORTB &= ~seg_c; } else { PORTB |= seg_c; }
  218.     if ((pattern & 16) == 16)   { PORTB &= ~seg_d; } else { PORTB |= seg_d; }
  219.     if ((pattern &  8) ==  8)   { PORTB &= ~seg_e; } else { PORTB |= seg_e; }
  220.     if ((pattern &  4) ==  4)   { PORTB &= ~seg_f; } else { PORTB |= seg_f; }
  221.     if ((pattern &  2) ==  2)   { PORTB &= ~seg_g; } else { PORTB |= seg_g; }
  222.     if ((pattern &  1) ==  1)   { PORTB &= ~seg_dp; } else { PORTB |= seg_dp; }
  223.     // Delay so the image stays on the retina
  224.     _delay_ms(POV_DELAY);
  225. }
  226. //----------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement