// This was a quick and dirty hack, because I wanted to build a segment display from scratch and figure out how to drive it.. // This was for learning, now for showing how beautiful I can make C look or how clever I could be (not very), anyhow, it served its purpose and I'm not going to clean it up. void setup() { // Anodes pinMode( 0, OUTPUT ); pinMode( 1, OUTPUT ); pinMode( 2, OUTPUT ); pinMode( 3, OUTPUT ); pinMode( 4, OUTPUT ); // Cathodes pinMode( 8, OUTPUT ); pinMode( 9, OUTPUT ); pinMode( 14, OUTPUT ); pinMode( 15, OUTPUT ); pinMode( 16, OUTPUT ); // Pushbutton pinMode( A2, INPUT ); digitalWrite( A2, HIGH); // Activate internal pullup, switch is wired between A2 and gnd. } // Describes port states to light up a segment // Segments are numbered starting from the top right going down and then left // 3 // 6 1 // 4 // 7 2 // 5 // I'm going to assume that fetching from this array would be faster than "calculating" the segment patterns with bit manipulation, could be rewritten, I chose to hardcode it in case I wired it up the wrong way. // Values here are interlaced, first value is for anode (portd) and next value is for cathode (portb) // See http://qqtrading.com.my/image/catalog/Products/Arduino/pro-micro/pro_micro_pinout_v1_0_blue.jpg in case you're wondering why the cathode is 1 bit offset. int m[] = { B00000001, B11111101, B00000010, B11111101, B00000100, B11111101, B00001000, B11111101, B00010000, B11111101, B00000001, B11111011, B00000010, B11111011, B00000100, B11111011, B00001000, B11111011, B00010000, B11111011, B00000001, B11110111, B00000010, B11110111, B00000100, B11110111, B00001000, B11110111, B00010000, B11110111, B00000001, B11101111, B00000010, B11101111, B00000100, B11101111, B00001000, B11101111, B00010000, B11101111, B00000001, B11011111, B00000010, B11011111, B00000100, B11011111, B00001000, B11011111, B00010000, B11011111, }; // Describes segments required to display a number // First (leftmost) bit is the first segment, the last bit is never used (7 segments, duh) int n[] = { B11101110, //0 B11000000, B10111010, B11111000, B11010100, B01111100, B01111110, B11100000, B11111110, B11111101 }; // Lazy void off() { PORTB = 0xFF; PORTD = 0x00; } // Laazy void led() { PORTD = m[21*2]; PORTB = m[21*2+1]; } // Display a value // If over > 0, the assume value is a single digit, and display it in that column (columns being 2,1,0 going from left to right), this means you can write a single digit anywhere, not only at the rightmost column. void disp( int val, int over ) { int v[3]; v[0] = val % 10; v[1] = val % 100 / 10; v[2] = val / 100; int on[3]; on[0]=0; on[1]=0; on[2]=0; if(!over) { on[0]=1; if(val > 9) { on[1] = 1; if(val > 90) { on[2] = 1; } } } else { v[0]=0; v[1]=0; v[2]=0; on[over]=1; v[over]=val; } for(int d = 0; d < 3; d++) { if(on[d]) { int offset = d * 7 * 2; int b = n[v[d]]; for(int s = 0; s < 7; s++) { if( b & ( B10000000 >>s) ) { PORTD = m[offset + s*2]; PORTB = m[offset +s*2+1]; } delayMicroseconds(100); } } } } // This will not debounce, as it also used for measuring, note the negation since the pullup is used. inline bool btn() { return !digitalRead(A2); } int ani[] = { 16, 19, 20, 18, 11, 4, 1, 0, 2, 9 }; void loop() { // Meaningless variable names are bad practice, don't do it! And especially don't reuse them for other stuff later.. // Spoiler: I'll do both, hah! int l=0; int f=0; // Blink and wait for button while(!btn()) { PORTD = m[ ani[f]*2 ]; PORTB = m[ ani[f]*2 +1 ]; delay(1); l++; if(l > 300) { l=0; f++; if(f == 10) { f=0; } } } while(btn()) { delay(100); } // Do a countdown.. l = 2000; while(l!=0) { disp(3, 0); l--; } l = 1500; while(l!=0) { disp(2, 1); l--; } l = 1000; while(l!=0) { disp(1, 2); l--; } // Clear the display and off(); // Wait for a random amount of time (yes, I know I didn't seed the rng, you be my guest and memorize the delays) int t=0; // Time, unless it's 1000, then it's OVERTIME ;) and if it's 2000, it's UNDERTIME hah! the madness! l = random(3000,10000); // ~ms, because logic happens in the loop, close enough, that's not where we're measuring.. while( l>0 ) { if(btn()) { t=2000; // Dude pressed while we were waiting. while(btn()) { delay(100); } break; } l--; delay(1); } // Turn on the LED led(); // Wait for dude to press, but only wait 1000 ms, otherwise it's too slow. while(t<1000) { if( btn() ) { while( btn() ) { delay(10); } break; } delay(1); t++; } delay(20); l=250; // Display value and wait for button to be pressed again. if(t < 1000) { while(!btn() || l > 0) { disp(t, 0); if(l>0) { l--; } } off(); while(btn()) { delay(100); } } else if(t==1000) { // Too slow, do falling bars thing.. PORTD = m[16*2]; PORTB = m[16*2+1]; delay(1000); PORTD = m[10*2]; PORTB = m[10*2+1]; delay(1000); PORTD = m[4*2]; PORTB = m[4*2+1]; delay(1000); off(); delay(500); } else { // Too fast, do the rising bar thing.. PORTD = m[18*2]; PORTB = m[18*2+1]; delay(1000); PORTD = m[10*2]; PORTB = m[10*2+1]; delay(1000); PORTD = m[2*2]; PORTB = m[4*2+1]; delay(1000); off(); delay(500); } // F.I.N. // Rinse // Repeat }