Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * SpeedTestSlave.c
- *
- * Created: 1/28/2013 9:53:06 PM
- * Author: grist.carrigafoyl
- A test bed for testing I2C comms under various conditions.
- */
- #define F_CPU 8000000UL // 8Mhz
- #include <avr/io.h>
- #include <util/delay.h>
- #include <avr/interrupt.h> // for I2C
- #include "usiTwiSlave.h" // Don Blake's library
- // The I2C address for this slave device
- #define SLAVE_ADDR 0x01
- #define PACKET_SIZE 16 // Max bytes to receive at a time
- #define END_MARKER 255 // Signals the end of transmission
- // Having a delay between displaying segments helps the persistence of vision and makes the segments brighter.
- // Much larger than this you will see noticeable flickering, much lower and you get dimmed segments.
- #define POV_DELAY 5 // ms delay for persistence of vision
- #define NUM_DIGITS 4 // How many digits on the display
- // Number bitmaps. Which LEDs to light up to represent each digit
- const uint8_t number_maps[10] = {
- //abcdefgp - 1 for on, 0 for off.
- 0b11111100, // 0
- 0b01100000, // 1
- 0b11011010, // 2
- 0b11110010, // 3
- 0b01100110, // 4
- 0b10110110, // 5
- 0b10111110, // 6
- 0b11100000, // 7
- 0b11111110, // 8
- 0b11110110, // 9
- };
- const uint8_t PATTERN_c = 0b00011010; // lower case 'c' for degrees display
- // Segment to pin mapping.
- enum SEGMENT_PINS {
- seg_a = _BV(PD0),
- seg_b = _BV(PD1),
- seg_c = _BV(PB6),
- seg_d = _BV(PB4),
- seg_e = _BV(PB3),
- seg_f = _BV(PB2),
- seg_g = _BV(PB1),
- seg_dp = _BV(PB0)
- };
- // Digit to pin mapping.
- enum DIGIT_PINS {
- d1 = _BV(PD3),
- d2 = _BV(PD4),
- d3 = _BV(PD5),
- d4 = _BV(PD6)
- };
- // The colon and degree indicator LEDs
- const uint8_t COLON_PIN = _BV(PA0);
- const uint8_t DEG_PIN = _BV(PA1); // degrees indicator (apostrophe)
- // Digit and segment pins
- uint8_t digits[4] = {d1,d2,d3,d4};
- // Segment pins are split over 2 ports as I2C needs 2 pins on PORTB
- uint8_t portb_segment_mask = (seg_c | seg_d | seg_e | seg_f | seg_g | seg_dp);
- uint8_t portd_segment_mask = (seg_a | seg_b);
- volatile uint8_t data[PACKET_SIZE]; // this will hold the data to be received
- // Function prototypes
- void displayNumber();
- void showPattern(uint8_t pattern);
- void showVerticalBar(uint8_t position);
- int main(void)
- {
- int total,i;
- int counter = 0;
- uint8_t temp = 0;
- // Set the pin modes for output
- DDRA |= (COLON_PIN | DEG_PIN);
- DDRB |= portb_segment_mask; // all pins except SDA & SCL (PB5 & 7) on PortB are output
- DDRD |= (d1 | d2 | d3 | d4 | portd_segment_mask ); // the digit selector pins & 2 of the segment pins
- //testDisplayNumber();
- // Initialise the I2C interface
- usiTwiSlaveInit(SLAVE_ADDR);
- // Enable global interrupts (required for I2C)
- sei();
- // main loop
- for(;;) { // forever
- // Check to see if there's data to read in
- if (usiTwiDataInReceiveBuffer()) {
- // get some bytes
- counter = 0;
- //while (usiTwiDataInReceiveBuffer()) {
- //for(counter=0;counter<PACKET_SIZE;counter++) {
- while(1) {
- temp = usiTwiReceiveByte();
- if (temp == END_MARKER) {
- break;
- } else {
- data[counter] = temp;
- counter++;
- }
- }
- // Add them up
- total = 0;
- for (i=0;i<counter;i++) {
- total += data[i];
- }
- // Displaying 4 digits takes 20ms. Display for 5 seconds.
- for(i=0;i<250;i++) {
- displayNumber(total);
- }
- }
- // show the waiting pattern
- showVerticalBar(counter++);
- counter %= 8;
- }
- }
- //----------------------------------------------------------------------------
- // Functions
- //----------------------------------------------------------------------------
- void testDisplayNumber()
- { // Testing displayNumber to make sure it works as intended
- int i;
- for(;;) {
- for (i=0;i<10000;i++) {
- displayNumber(i);
- }
- }
- }
- void displayNumber(int number) {
- // show the data on the display
- // Flags for various display options
- bool show_colon = false;
- bool show_apostrophe = false;
- uint8_t pattern[4] = {0,0,0,0}; // will hold the raw bitmap of the pattern to be shown on the display
- int temp = number;
- // Convert the 4 bytes to an integer, but current display can only show 9999 max
- temp %= 10000;
- // convert the integer to single digit patterns for display
- pattern[0] = number_maps[temp/1000];
- temp %= 1000;
- pattern[1] = number_maps[temp/100];
- temp %= 100;
- pattern[2] = number_maps[temp/10];
- temp %= 10;
- pattern[3] = number_maps[temp];
- // Time to display what we've got
- // set the colon and apostrophe as required
- if (show_colon == true) { PORTA |= COLON_PIN; } else { PORTA &= ~COLON_PIN; }
- if (show_apostrophe == true) { PORTA |= DEG_PIN; } else { PORTA &= ~DEG_PIN; }
- // // Now show the pattern.
- for (int d=0 ; d<NUM_DIGITS ; d++) {
- // Choose the digit to display by setting its pin HIGH and
- // all the other pins LOW.
- PORTD &= ~( d1 | d2 | d3 | d4);
- PORTD |= digits[d];
- showPattern(pattern[d]);//
- }
- }
- //----------------------------------------------------------------------------
- void showVerticalBar(uint8_t position)
- { // Show a vertical bar in the position. Each digit has 2 bars, and are numbered
- // left to right starting at 0. This doesn't have to be multiplexed as only 1
- // digit is ever displaying something at a time. Used as a simple idle indicator.
- #define bar1 0b00001100
- #define bar2 0b01100000
- uint8_t bar, digit;
- if ((float)position/2 == position/2) {
- bar = bar1;
- } else {
- bar = bar2;
- }
- digit = position/2;
- // Choose the digit to display by setting its pin HIGH and
- // all the other pins LOW.
- PORTD &= ~( d1 | d2 | d3 | d4);
- PORTD |= digits[digit];
- showPattern(bar);
- }
- //----------------------------------------------------------------------------
- void showPattern(uint8_t pattern)
- { // show the current pattern on the currently selected digit
- // First set all the digit pins HIGH to turn them off so the
- // previous digit doesn't get ghosted onto the new segment
- // Segments a & b are on PORTD, the rest are on PORTB
- PORTD |= (portd_segment_mask);
- PORTB |= (portb_segment_mask);
- // Have to manipulate the pins one at a time so as not to interfere with I2C
- // PORTD segments
- if ((pattern & 128) == 128) { PORTD &= ~seg_a; } else { PORTD |= seg_a; }
- if ((pattern & 64) == 64) { PORTD &= ~seg_b; } else { PORTD |= seg_b; }
- // PORTB segments
- if ((pattern & 32) == 32) { PORTB &= ~seg_c; } else { PORTB |= seg_c; }
- if ((pattern & 16) == 16) { PORTB &= ~seg_d; } else { PORTB |= seg_d; }
- if ((pattern & 8) == 8) { PORTB &= ~seg_e; } else { PORTB |= seg_e; }
- if ((pattern & 4) == 4) { PORTB &= ~seg_f; } else { PORTB |= seg_f; }
- if ((pattern & 2) == 2) { PORTB &= ~seg_g; } else { PORTB |= seg_g; }
- if ((pattern & 1) == 1) { PORTB &= ~seg_dp; } else { PORTB |= seg_dp; }
- // Delay so the image stays on the retina
- _delay_ms(POV_DELAY);
- }
- //----------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement