View difference between Paste ID: 5Zv4ACai and 96emhzKi
SHOW: | | - or go back to the newest paste.
1
/*
2-
 * FourDigitSevenSegmentDisplayDriver.c
2+
  Testing I2C comms to my ATtiny2313
3-
 *
3+
4-
 * Created: 1/31/2012 1:09:17 AM
4+
5-
 *  Author: grist.carrigafoyl
5+
#include <Wire.h>
6-
 
6+
7-
Code to turn an ATtiny2313 into a 4 digit 7 segment display driver. This will
7+
// local LED pins
8-
allow offloading multiplexing a typical LED display to a slave chip and
8+
#define LED1 8
9-
let the main CPU get on with whatever it's doing. The driver displays
9+
#define LED2 9
10-
whatever is in its data register until it receives new data over the
10+
#define LED3 10
11-
serial lines.
11+
#define LED4 11
12
13-
Employs a 5 byte protocol with the first byte containing flags that control
13+
// Array to hold the led pin numbers
14-
the colon and degrees indication and also how the data is displayed
14+
int LEDS[4] = {LED1, LED2, LED3, LED4};
15-
and the other 4 bytes contain the data to be displayed.
15+
const int SLAVE_ADDRESS = 0x01;// this must match the address assigned to the ATtiny in its code or they won't talk
16
17-
Using Don Blake's translation of the Atmel I2C (TWI) library.
17+
// setup
18
void setup() {
19-
First byte
19+
 Wire.begin(); 
20-
First 4 bits are format related
20+
 for (byte i=0;i<4;i++) {
21-
1 (128) - bit 1 of format
21+
   pinMode(LEDS[i], OUTPUT);
22-
2 (64) - bit 2 of format
22+
 }
23-
3 (32) - bit 1 of format params
23+
24-
4 (16) - bit 2 of format params
24+
25-
Second 4 bits are display option related (not implemented for now)
25+
// Main
26-
5 (8) - flashing (not implemented)
26+
void loop () {
27-
6 (4) - scrolling (not implemented)
27+
  
28-
7 (2) - bit 1 of display option params
28+
  // Demonstrate each of the display modes available
29-
8 (1) - bit 2 of display option params
29+
  delay(1000);
30
  testRaw();
31
  delay(1000);
32
  testTime();
33-
#define F_CPU 8000000UL  //  8Mhz
33+
  delay(1000);
34
  testDegrees();
35-
#define NUM_DIGITS 4
35+
  delay(1000);
36-
#define NUM_SEGMENTS 8 // a 7 segment display has 8 segments. #8 is the decimal point
36+
  testDecimal();
37-
#define NUM_BYTES_IN_PROTOCOL 5 // how many bytes to read at a time
37+
  delay(1000);
38
39-
#include <avr/io.h>
39+
40-
#include <util/delay.h>
40+
41-
#include <avr/interrupt.h> // for I2C
41+
//-------------------------------------------------------------------
42
// Functions
43-
#include "usiTwiSlave.h" // Don Blake's library
43+
//-------------------------------------------------------------------
44
void testRaw() {
45-
// The TWI address for this slave device
45+
  // test the raw mode
46-
const uint8_t TWI_SLAVE_ADDRESS = 0x01;
46+
47
  // A simple set of patterns to display.
48-
// Constants for option byte bitmapping. First 4 bits are for the display format
48+
  byte number_maps[15] = {
49-
const uint8_t FORMAT_MASK =		0b11000000;
49+
      //abcdefgp - 1 for on, 0 for off.
50-
const uint8_t FORMAT_OPTION_MASK = 0b00110000;
50+
      B11000111,
51-
// RAW format masks
51+
      B00111010,
52-
const uint8_t FORMAT_RAW =		0b00000000; // Param bits are colon & apostrophe
52+
      B11000110, 
53-
const uint8_t RAW_OPTION_COLON = 0b00100000;
53+
      B00111010, 
54-
const uint8_t RAW_OPTION_APOSTROPHE = 0b00010000;
54+
      B11000110, 
55-
// TIME format masks
55+
      B00111010, 
56-
const uint8_t FORMAT_TIME =		0b10000000; // (could have param for 24 hr? indicated by dot in pos 1)
56+
      B11000110,
57-
const uint8_t TIME_OPTION_HHMM = 0b00100000;
57+
      B00111010,
58-
const uint8_t TIME_OPTION_MMSS = 0b00010000;
58+
      B11000110,
59-
const uint8_t TIME_OPTION_SECONDS = 0b00110000;
59+
      B00111010,
60-
// DEGREES format masks
60+
  };
61-
const uint8_t FORMAT_DEGREES =	0b11000000; // Param bits are point position indicator, 0 or 1 are off, only positions 2 & 3 are valid)
61+
62-
const uint8_t DEGREES_DOT_POS_MASK = 0b00110000;
62+
  byte option_byte = B00110000; // turn the colon & apostrophe on
63-
// DECIMAL format masks
63+
  for (int i=0;i<3;i++){
64-
const uint8_t FORMAT_DECIMAL =	0b01000000; // Param bits are point postion indicator 0 is off, 123 count from right)
64+
    for (byte i = 0; i<10; i++) {
65-
const uint8_t DECIMAL_DOT_POS_MASK = 0b00110000;
65+
      displayData(i); // show the current data on the locallly connected LEDs
66
  
67-
// Now the display options in the last 4 bits. Not implemented as yet.
67+
      Wire.beginTransmission(SLAVE_ADDRESS);
68-
const uint8_t OPTION_FLASHING =	0b00001000; // delay as 2 bit param. Not implemented yet
68+
      Wire.write(option_byte);
69-
const uint8_t OPTION_SCROLLING = 0b00000100; // 2 bit param for direction. Not implemented yet
69+
      for (int x=0;x<4;x++) {
70-
const uint8_t OPTION_PARAM0 = 0b00000000;
70+
        Wire.write(number_maps[((i+x) % 10)]);
71-
const uint8_t OPTION_PARAM1 = 0b00010000; 
71+
      }
72-
const uint8_t OPTION_PARAM2 = 0b00100000;
72+
      Wire.endTransmission();
73-
const uint8_t OPTION_PARAM3 = 0b00110000;
73+
      delay(100);
74
    }
75-
// Number bitmaps. Which LEDs to light up to represent each digit
75+
    //delay(250);
76-
const uint8_t number_maps[10] = {
76+
  }
77-
    //abcdefgp - 1 for on, 0 for off.
77+
78-
    0b11111100, // 0
78+
//-------------------------------------------------------------------
79-
    0b01100000, // 1
79+
void testTime() {
80-
    0b11011010, // 2
80+
  // test the time mode
81-
    0b11110010, // 3
81+
  // slave is only reading mm:ss for now
82-
    0b01100110, // 4
82+
  char option_byte = B10000000;
83-
    0b10110110, // 5
83+
  for (byte m=5;m<15;m++) {
84-
    0b10111110, // 6
84+
    for (byte s=0;s<60;s++) {
85-
    0b11100000, // 7
85+
      Wire.beginTransmission(SLAVE_ADDRESS);
86-
    0b11111110, // 8
86+
      Wire.write(option_byte);
87-
    0b11110110,  // 9
87+
      Wire.write((char)B00000001); // hours ignored for now
88-
};
88+
      Wire.write((char)m);
89-
const uint8_t PATTERN_c = 0b00011010; // lower case 'c' for degrees display
89+
      Wire.write((char)s);
90
      Wire.write((char)B00000100); // 10th seconds ignored for now
91
      Wire.endTransmission();
92-
// Segment to pin mapping. 
92+
      delay(20);
93-
enum SEGMENT_PINS {
93+
94-
	seg_a = _BV(PD0),
94+
  }  
95-
	seg_b = _BV(PD1),
95+
96-
	seg_c = _BV(PB6),
96+
//-------------------------------------------------------------------
97-
	seg_d = _BV(PB4),
97+
void testDegrees() {
98-
	seg_e = _BV(PB3),
98+
  // test the degrees mode
99-
	seg_f = _BV(PB2),
99+
100-
	seg_g = _BV(PB1),
100+
  byte option_byte= B11100000;
101-
	seg_dp = _BV(PB0)
101+
  // just whole numbers for now. hacking 4 bytes together. If your temp
102-
};
102+
  // will never exceed 255 you can just send 3 zeros and the raw temp.
103-
// Digit to pin mapping.
103+
  for (int x=0; x<2 ; x++ ) {
104-
enum DIGIT_PINS {
104+
    for (int y=200; y<256 ; y++ ) { // cut down range for testing
105-
	d1 = _BV(PD3),
105+
      Wire.beginTransmission(SLAVE_ADDRESS);
106-
	d2 = _BV(PD4),
106+
      Wire.write(option_byte);
107-
	d3 = _BV(PD5),
107+
      Wire.write((byte)0);
108-
	d4 = _BV(PD6)
108+
      Wire.write((byte)0);
109-
};
109+
      Wire.write((byte)x);
110
      Wire.write((byte)y);
111-
// The colon and degree indicator LEDs
111+
      Wire.endTransmission();
112-
const uint8_t COLON_PIN = _BV(PA0);
112+
      delay(100);
113-
const uint8_t DEG_PIN = _BV(PA1); // degrees indicator (apostrophe)
113+
114
  }
115-
// Having a delay between displaying segments helps the persistence of vision and makes the segments brighter.
115+
  
116-
// Much larger than this you will see noticeable flickering, much lower and you get dimmed segments.
116+
  
117-
const int POV_DELAY = 5; // ms delay for persistence of vision
117+
118
//-------------------------------------------------------------------
119-
// Digit and segment pins
119+
void testDecimal() {
120-
uint8_t digits[4] = {d1,d2,d3,d4};
120+
  // test the decimal mode
121-
// Segment pins are split over 2 ports as I2C needs 2 pins on PORTB
121+
  int temp;
122-
uint8_t portb_segment_mask = (seg_c | seg_d | seg_e | seg_f | seg_g | seg_dp);
122+
  for (int i=500;i<2000;i++) {
123-
uint8_t portd_segment_mask = (seg_a | seg_b);
123+
    temp = i;
124-
volatile uint8_t data[NUM_BYTES_IN_PROTOCOL] = {0,255,255,255,255}; // this will hold the data to be displayed
124+
    Wire.beginTransmission(SLAVE_ADDRESS);
125
    Wire.write((byte)B01110000); //option byte
126-
// Function prototypes
126+
    // the number is broken into 4 bytes. Most significant byte first.
127-
void displayData();
127+
    // Quick and dirty hack with constants.
128-
void showPattern(uint8_t pattern);
128+
    Wire.write((byte)(temp/16777216));
129
    temp %= 16777216;
130-
int main(void)
130+
    Wire.write((byte)(temp/65536));
131-
{
131+
    temp %= 65536;
132-
	// Set the pin modes for output
132+
    Wire.write((byte)(temp/256));
133-
	DDRA |= (COLON_PIN | DEG_PIN);
133+
    temp %= 256;
134-
	DDRB |= portb_segment_mask; // all pins except SDA & SCL (PB5 & 7) on PortB are output
134+
    Wire.write((byte)temp);
135-
	DDRD |= (d1 | d2 | d3 | d4 | portd_segment_mask );  // the digit selector pins & 2 of the segment pins
135+
    Wire.endTransmission();
136-
	
136+
    delay(20);
137-
	// Initialise the I2C interface
137+
  }
138-
	usiTwiSlaveInit(TWI_SLAVE_ADDRESS);
138+
139-
	// Enable global interrupts (required for I2C)
139+
//-------------------------------------------------------------------
140-
	sei();
140+
void displayData(byte pattern) {
141
 // show the current data on this device's leds.
142-
	// main loop
142+
 // first blank out the leds
143-
	for(;;) { // forever
143+
   for (byte i=0;i<4;i++) {
144-
		// Check to see if there's data to read in
144+
     digitalWrite(LEDS[i], LOW);
145-
		if (usiTwiDataInReceiveBuffer()) {
145+
   } 
146-
			// get some bytes
146+
   byte pat = pattern;
147-
			for (int i=0;i<NUM_BYTES_IN_PROTOCOL;i++) {
147+
   byte i = 0;
148-
				data[i] = usiTwiReceiveByte(); 
148+
   while (pat > 0 && i < 4) {
149-
			}
149+
     if ((pat % 2) == 1) {
150-
		}
150+
       digitalWrite(LEDS[i], HIGH);
151-
		// show the current data
151+
     }
152-
		displayData();  
152+
       pat = pat / 2;   
153
       i++;
154
   }
155
}