Browse Source

drive the output pin with DDR and PORT operations to improve performances

master
Nicolas Massé 8 years ago
parent
commit
1869894ba6
  1. 146
      counter/counter.ino

146
counter/counter.ino

@ -36,12 +36,19 @@
/* /*
* The seven segment display has a common cathode for each digit * The seven segment display has a common cathode for each digit
*/ */
#define CATHODE_1000_PIN 1 #define CATHODE_1000_PIN B00000001
#define CATHODE_100_PIN 13 #define CATHODE_100_PIN B00000010
#define CATHODE_10_PIN 3 #define CATHODE_10_PIN B00000100
#define CATHODE_1_PIN 4 #define CATHODE_1_PIN B00001000
// The splitter is the colon between the second and third digit // The splitter is the colon between the second and third digit
#define CATHODE_SPLITTER_PIN 0 #define CATHODE_SPLITTER_PIN B00010000
/*
* All the cathodes are connected to PORTB's pins
*
*/
#define CATHODE_PORT PORTB
#define CATHODE_DDR DDRB
/* /*
* The anodes will light up a segment when it is LOW and the cathode is HIGH. * The anodes will light up a segment when it is LOW and the cathode is HIGH.
@ -49,13 +56,20 @@
* The anode numbering refers to the standard numbering: * The anode numbering refers to the standard numbering:
* https://en.wikipedia.org/wiki/Seven-segment_display * https://en.wikipedia.org/wiki/Seven-segment_display
*/ */
#define ANODE_A_PIN 11 #define ANODE_A_PIN B10000000
#define ANODE_B_PIN 10 #define ANODE_B_PIN B01000000
#define ANODE_C_PIN 9 #define ANODE_C_PIN B00100000
#define ANODE_D_PIN 8 #define ANODE_D_PIN B00010000
#define ANODE_E_PIN 7 #define ANODE_E_PIN B00001000
#define ANODE_F_PIN 6 // Yes, there is a gap since pin 2 is used for the button
#define ANODE_G_PIN 5 #define ANODE_F_PIN B00000010
#define ANODE_G_PIN B00000001
/*
* All the anodes are connected to PORTD's pins
*/
#define ANODE_PORT PORTD
#define ANODE_DDR DDRD
/* /*
* The number of milliseconds to wait in order to let the retinal persistence do its job. * The number of milliseconds to wait in order to let the retinal persistence do its job.
@ -75,32 +89,36 @@
#define DELAY_DEBUG #define DELAY_DEBUG
#endif #endif
// The state of each anode for each number between 0 and 9 /*
#define ANODE_A_STATE(x) (x != 4 && x != 1 ? LOW : HIGH) * Lookup table to drive the anode pins according to a digit between 0 and 9
#define ANODE_B_STATE(x) (x != 5 && x != 6 ? LOW : HIGH) */
#define ANODE_C_STATE(x) (x != 2 ? LOW : HIGH) byte digit[] = {
#define ANODE_D_STATE(x) (x != 1 && x != 4 && x != 7 ? LOW : HIGH) /* 0 */ ANODE_A_PIN|ANODE_B_PIN|ANODE_C_PIN|ANODE_D_PIN|ANODE_E_PIN|ANODE_F_PIN,
#define ANODE_E_STATE(x) (x != 0 && x != 2 && x != 6 && x != 8 ? HIGH : LOW) /* 1 */ ANODE_B_PIN|ANODE_C_PIN,
#define ANODE_F_STATE(x) (x != 1 && x != 2 && x != 3 && x != 7 ? LOW : HIGH) /* 2 */ ANODE_A_PIN|ANODE_B_PIN|ANODE_D_PIN|ANODE_E_PIN|ANODE_G_PIN,
#define ANODE_G_STATE(x) (x != 0 && x != 1 && x != 7 ? LOW : HIGH) /* 3 */ ANODE_A_PIN|ANODE_B_PIN|ANODE_C_PIN|ANODE_D_PIN|ANODE_G_PIN,
/* 4 */ ANODE_B_PIN|ANODE_C_PIN|ANODE_F_PIN|ANODE_G_PIN,
/* 5 */ ANODE_A_PIN|ANODE_C_PIN|ANODE_D_PIN|ANODE_F_PIN|ANODE_G_PIN,
/* 6 */ ANODE_A_PIN|ANODE_C_PIN|ANODE_D_PIN|ANODE_E_PIN|ANODE_F_PIN|ANODE_G_PIN,
/* 7 */ ANODE_A_PIN|ANODE_B_PIN|ANODE_C_PIN,
/* 8 */ ANODE_A_PIN|ANODE_B_PIN|ANODE_C_PIN|ANODE_D_PIN|ANODE_E_PIN|ANODE_F_PIN|ANODE_G_PIN,
/* 9 */ ANODE_A_PIN|ANODE_B_PIN|ANODE_C_PIN|ANODE_D_PIN|ANODE_F_PIN|ANODE_G_PIN
};
// All the cathodes // All the cathodes
const int cathodes[] = {CATHODE_1000_PIN, CATHODE_100_PIN, CATHODE_10_PIN, CATHODE_1_PIN, CATHODE_SPLITTER_PIN}; const byte cathodes = CATHODE_1000_PIN | CATHODE_100_PIN | CATHODE_10_PIN | CATHODE_1_PIN | CATHODE_SPLITTER_PIN;
// All the anodes // All the anodes
const int anodes[] = {ANODE_A_PIN, ANODE_B_PIN, ANODE_C_PIN, ANODE_D_PIN, ANODE_E_PIN, ANODE_F_PIN, ANODE_G_PIN}; const byte anodes = ANODE_A_PIN|ANODE_B_PIN|ANODE_C_PIN|ANODE_D_PIN|ANODE_E_PIN|ANODE_F_PIN|ANODE_G_PIN;
void setup() { void setup() {
// cathodes as output with default to LOW // initialize cathodes pins as output with default to LOW
for (int i = 0; i < sizeof(cathodes)/sizeof(cathodes[0]); i++) { CATHODE_DDR |= cathodes;
pinMode(cathodes[i], OUTPUT); CATHODE_PORT &= ~cathodes;
digitalWrite(cathodes[i], LOW);
} // initialize anodes pins as output with default to HIGH
// anodes as output with default to HIGH ANODE_DDR |= anodes;
for (int i = 0; i < sizeof(anodes)/sizeof(anodes[0]); i++) { ANODE_PORT |= anodes;
pinMode(anodes[i], OUTPUT);
digitalWrite(anodes[i], HIGH);
}
// Enable the button and register an interrupt // Enable the button and register an interrupt
pinMode(BUTTON_PIN, INPUT); pinMode(BUTTON_PIN, INPUT);
@ -108,43 +126,51 @@ void setup() {
} }
// the counter is later incremented by an interrupt // the counter is later incremented by an interrupt
volatile int counter = 0; volatile byte counter[] = {0,0,0,0};
void button_interrupt() { void button_interrupt() {
counter++; if (counter[0] >= 9) {
counter[0] = 0;
if (counter[1] >= 9) {
counter[1] = 0;
if (counter[2] >= 9) {
counter[2] = 0;
if (counter[3] >= 9) {
// Overflow
counter[3] = 0;
} else {
counter[3]++;
}
} else {
counter[2]++;
}
} else {
counter[1]++;
}
} else {
counter[0]++;
}
} }
const byte digit_cathodes[] = { CATHODE_1_PIN, CATHODE_10_PIN, CATHODE_100_PIN, CATHODE_1000_PIN };
void loop() { void loop() {
int n = counter; // Iterate over the four digits to display
for (byte c = 0; c < 4; c++) {
// Base 10 conversion // Set all cathodes pins to LOW
int n1 = n % 10; CATHODE_PORT &= ~(CATHODE_1_PIN|CATHODE_10_PIN|CATHODE_100_PIN|CATHODE_1000_PIN);
int n10 = ((n - n1) % 100) / 10;
int n100 = ((n - n1 - n10 * 10) % 1000) / 100;
int n1000 = ((n - n1 - n10 * 10 - n100 * 100) % 10000) / 1000;
int digits[] = { n1000, n100, n10, n1 };
for (int c = 0; c < 4; c++) {
int digit = digits[c];
digitalWrite(cathodes[c], HIGH);
DELAY_DEBUG
digitalWrite(ANODE_A_PIN, ANODE_A_STATE(digit));
DELAY_DEBUG
digitalWrite(ANODE_B_PIN, ANODE_B_STATE(digit));
DELAY_DEBUG
digitalWrite(ANODE_C_PIN, ANODE_C_STATE(digit));
DELAY_DEBUG DELAY_DEBUG
digitalWrite(ANODE_D_PIN, ANODE_D_STATE(digit));
DELAY_DEBUG // Drive the matching anodes of the digit (a segment is enabled when the matching pin is LOW)
digitalWrite(ANODE_E_PIN, ANODE_E_STATE(digit)); ANODE_PORT = ~digit[counter[c]];
DELAY_DEBUG DELAY_DEBUG
digitalWrite(ANODE_F_PIN, ANODE_F_STATE(digit));
// Set the selected cathode pin to HIGH to display to digit
CATHODE_PORT |= digit_cathodes[c];
DELAY_DEBUG DELAY_DEBUG
digitalWrite(ANODE_G_PIN, ANODE_G_STATE(digit));
// Let the persistence of vision do his job
delay(DELAY); delay(DELAY);
digitalWrite(cathodes[c], LOW);
DELAY_DEBUG
} }
} }

Loading…
Cancel
Save