/*
|
|
* Computer Switchboard
|
|
*
|
|
* Because interfacing with computers should be fun
|
|
* and a keyboard is not enough.
|
|
*
|
|
* Let's turn a computer into an airplane (interface wise).
|
|
*
|
|
*/
|
|
|
|
//todo: debounce, see neotimer
|
|
|
|
//makes serial slower so it can be read
|
|
#define DEBUGMODE 0
|
|
|
|
#include <avr/io.h>
|
|
#include <avr/interrupt.h>
|
|
|
|
|
|
|
|
/* SevenSegmentLEDdisplay102a.ino
|
|
* 2017-02-20
|
|
* Mel Lester Jr.
|
|
* Simple example of using Shift Register with a
|
|
* Single Digit Seven Segment LED Display
|
|
*/
|
|
// Globals
|
|
const int dataPin = 4; // blue wire to 74HC595 pin 14
|
|
const int latchPin = 7; // green to 74HC595 pin 12
|
|
const int clockPin = 8; // yellow to 74HC595 pin 11
|
|
|
|
/* uncomment one of the following lines that describes your display
|
|
* and comment out the line that does not describe your display */
|
|
const char common = 'a'; // common anode
|
|
//const char common = 'c'; // common cathode
|
|
|
|
bool decPt = true; // decimal point display flag
|
|
|
|
|
|
//switch
|
|
|
|
// digital pin 9 has a pushbutton attached to it. Give it a name:
|
|
int pushButton = 9;
|
|
|
|
|
|
//rotary
|
|
|
|
// -----
|
|
// SimplePollRotator.ino - Example for the RotaryEncoder library.
|
|
// This class is implemented for use with the Arduino environment.
|
|
// Copyright (c) by Matthias Hertel, http://www.mathertel.de
|
|
// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
|
|
// More information on: http://www.mathertel.de/Arduino
|
|
// -----
|
|
// 18.01.2014 created by Matthias Hertel
|
|
// -----
|
|
|
|
// This example checks the state of the rotary encoder in the loop() function.
|
|
// The current position is printed on output when changed.
|
|
|
|
// Hardware setup:
|
|
// Attach a rotary encoder with output pins to A2 and A3.
|
|
// The common contact should be attached to ground.
|
|
|
|
#include <RotaryEncoder.h>
|
|
|
|
// Setup a RoraryEncoder for pins A2 and A3:
|
|
//RotaryEncoder encoder(A2, A1);
|
|
RotaryEncoder encoder(A1, A2);
|
|
int difference = 0;
|
|
|
|
|
|
|
|
uint8_t segdisp = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Timer
|
|
//http://maxembedded.com/2011/06/avr-timers-timer1/
|
|
|
|
// global variable to count the number of overflows
|
|
volatile uint8_t tot_overflow;
|
|
|
|
volatile uint8_t ClearTimer = 0;
|
|
|
|
uint8_t buttonpressed = 0;
|
|
|
|
// TIMER1 overflow interrupt service routine
|
|
// called whenever TCNT1 overflows
|
|
ISR(TIMER1_OVF_vect)
|
|
{
|
|
// keep a track of number of overflows
|
|
tot_overflow++;
|
|
//Serial.println("Timer works!1");
|
|
|
|
// check for number of overflows here itself
|
|
// 61 overflows = 2 seconds delay (approx.) //EDIT: NO it's not in atmega328p nano.
|
|
|
|
//if (tot_overflow >= 2) // NOTE: '>=' used instead of '=='
|
|
if (tot_overflow >= 100) // NOTE: '>=' used instead of '=='
|
|
{
|
|
buttonpressed = 0;
|
|
//PORTC ^= (1 << 0); // toggles the led
|
|
// no timer reset required here as the timer
|
|
// is reset every time it overflows
|
|
|
|
if(DEBUGMODE){
|
|
Serial.println("Timer works!2");
|
|
}
|
|
tot_overflow = 0; // reset overflow counter
|
|
|
|
ClearTimer = 1; //clear interrupts / timer outside of interrupt
|
|
delay(10);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void setup() {
|
|
// initialize I/O pins
|
|
pinMode(dataPin, OUTPUT);
|
|
pinMode(latchPin, OUTPUT);
|
|
pinMode(clockPin, OUTPUT);
|
|
|
|
Serial.begin(9600);
|
|
|
|
pinMode(pushButton, INPUT_PULLUP);
|
|
|
|
timer1_init();
|
|
|
|
|
|
}
|
|
|
|
void loop() {
|
|
|
|
if (ClearTimer == 1){
|
|
cli();
|
|
|
|
if(DEBUGMODE){
|
|
Serial.println("Ready"); //this doesn't print correctly unless you remove ClearTimer to zero below.
|
|
delay(50);
|
|
}
|
|
else{
|
|
//Serial.println("Ready"); //this doesn't print correctly unless you remove ClearTimer to zero below.
|
|
delay(50);
|
|
ClearTimer = 0; //comment this, and uncomment ready for debugging.
|
|
}
|
|
}
|
|
|
|
//decPt = !decPt; // display decimal point every other pass through loop
|
|
|
|
// generate characters to display for hexidecimal numbers 0 to F
|
|
/* for (int i = 0; i <= 15; i++) {
|
|
byte bits = myfnNumToBits(i) ;
|
|
if (decPt) {
|
|
bits = bits | B00000001; // add decimal point if needed
|
|
}
|
|
myfnUpdateDisplay(bits); // display alphanumeric digit
|
|
delay(500); // pause for 1/2 second
|
|
}*/
|
|
|
|
byte bits = myfnNumToBits(segdisp);
|
|
if (decPt) {
|
|
bits = bits | B00000001; // add decimal point if switch high
|
|
}
|
|
|
|
myfnUpdateDisplay(bits);
|
|
|
|
|
|
|
|
|
|
//ROTARY
|
|
|
|
static uint8_t pos = 0;
|
|
encoder.tick();
|
|
|
|
uint8_t newPos = encoder.getPosition();
|
|
if (pos != newPos) {
|
|
difference = pos - newPos;
|
|
|
|
|
|
//Serial.print(newPos);
|
|
//Serial.println();
|
|
//Serial.println(difference);
|
|
pos = newPos;
|
|
|
|
segdisp = (segdisp + difference);
|
|
segdisp = segdisp & B00000111;//only give me the last three bits
|
|
//if there is anything there, so and.
|
|
//gives me 0-7
|
|
|
|
//Serial.println(segdisp);
|
|
|
|
}
|
|
|
|
|
|
|
|
//BUTTONS
|
|
|
|
int resultb = 0;
|
|
resultb = PINB;
|
|
delay(100);
|
|
if (resultb == 0 && buttonpressed == 0){
|
|
// turn on ~3 second delay, for debounce
|
|
|
|
decPt = 1;
|
|
buttonpressed = 1;
|
|
Serial.print("User Pressed button: ");
|
|
Serial.println(segdisp);
|
|
delay(50); // delay to cheat interrupts stopping me.
|
|
sei();
|
|
delay(100);
|
|
}
|
|
else{
|
|
decPt = 0;
|
|
}
|
|
// too fast, print serial when checking switch only
|
|
// Serial.println(resultb,BIN); // noisy, but reads 0 when low.
|
|
}
|
|
|
|
|
|
|
|
void myfnUpdateDisplay(byte eightBits) {
|
|
if (common == 'a') { // using a common anonde display?
|
|
eightBits = eightBits ^ B11111111; // then flip all bits using XOR
|
|
}
|
|
digitalWrite(latchPin, LOW); // prepare shift register for data
|
|
shiftOut(dataPin, clockPin, LSBFIRST, eightBits); // send data
|
|
digitalWrite(latchPin, HIGH); // update display
|
|
}
|
|
|
|
byte myfnNumToBits(int someNumber) {
|
|
switch (someNumber) {
|
|
case 0:
|
|
return B11111100;
|
|
break;
|
|
case 1:
|
|
return B01100000;
|
|
break;
|
|
case 2:
|
|
return B11011010;
|
|
break;
|
|
case 3:
|
|
return B11110010;
|
|
break;
|
|
case 4:
|
|
return B01100110;
|
|
break;
|
|
case 5:
|
|
return B10110110;
|
|
break;
|
|
case 6:
|
|
return B10111110;
|
|
break;
|
|
case 7:
|
|
return B11100000;
|
|
break;
|
|
case 8:
|
|
return B11111110;
|
|
break;
|
|
case 9:
|
|
return B11110110;
|
|
break;
|
|
case 10:
|
|
return B11101110; // Hexidecimal A
|
|
break;
|
|
case 11:
|
|
return B00111110; // Hexidecimal B
|
|
break;
|
|
case 12:
|
|
return B10011100; // Hexidecimal C or use for Centigrade
|
|
break;
|
|
case 13:
|
|
return B01111010; // Hexidecimal D
|
|
break;
|
|
case 14:
|
|
return B10011110; // Hexidecimal E
|
|
break;
|
|
case 15:
|
|
return B10001110; // Hexidecimal F or use for Fahrenheit
|
|
break;
|
|
default:
|
|
return B10010010; // Error condition, displays three vertical bars
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initialize timer, interrupt and variable
|
|
void timer1_init()
|
|
{
|
|
// set up timer with prescaler
|
|
TCCR1B |= (1 << CS10);
|
|
TCCR1B |= (1 << CS11);
|
|
|
|
// initialize counter
|
|
TCNT1 = 0;
|
|
|
|
// enable overflow interrupt
|
|
// TIMSK |= (1 << TOIE1); //doesn't work, not in atmega328p
|
|
// but data sheet has...
|
|
// in section 12 (why the f, isn't there a table of contents in my data sheet?)
|
|
TIMSK1 |= (1 << TOIE1);
|
|
|
|
// enable global interrupts
|
|
// I'll do this when a button pressed
|
|
// sei();
|
|
|
|
// initialize overflow counter variable
|
|
tot_overflow = 0;
|
|
}
|
|
|
|
|