Newer
Older
SafeCrack / template.cpp
root on 10 May 2019 3 KB documentation
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <SoftwareSerial.h>

const int rx = -1;  // -1 = dont use
const int tx = 5;   // pin 5 for serial.print()
SoftwareSerial Serial(rx,tx);  // rx, tx pins

int enc1pinA = 2;     // Encoder pin A 
int enc1pinB = 3;     // Encoder pin B 
int counter = 0;      // could use a byte here?
byte enc1oldPins = 0; // will hold state of pins last time encoder was read
byte enc1newPins = 0; // will hold new encoder pin reading, to be compared with last time's pin states
byte enc1move = 0;    // when two encoders are used to control the same parameter, this will hold the combined deduced movement

const byte RotaryDecodeTable[4][4] = {
{B00, B10, B01, B11},
{B01, B00, B11, B10},
{B10, B11, B00, B01},
{B11, B01, B10, B00}
};

int bLed = 1;   // rotary encoder LED pin        
int rgLed = 4;  // red/green LED pin
int val = 0;    // rotary encoder current position

unsigned long lastCheck = 0;  // time (for sleep state)
bool sleepState = 0;          // sleep or awake

void setup() {
  pinMode(bLed, OUTPUT);
  pinMode(rgLed, INPUT);

  pinMode(enc1pinA, INPUT);         // configure the pin connections as inputs
  pinMode(enc1pinB, INPUT);
  pinMode(enc1pinA, INPUT_PULLUP);  // turn on internal pull-up resistor for each input
  pinMode(enc1pinB, INPUT_PULLUP);
  delay(1);                         // allow 1ms for encoder voltages to setle
  enc1oldPins = (digitalRead(enc1pinA)<<1|digitalRead(enc1pinB)); // read the initial state of encoder
  
  lastCheck = millis(); // for sleep state

  pinMode(rx,INPUT); // setup and print to serial
  pinMode(tx,OUTPUT);
  Serial.begin(9600);
  Serial.println("Running");
}

void green(int del){ // turn on green LED for delay()
  pinMode(rgLed, OUTPUT);
  analogWrite(rgLed, HIGH);
  delay(del);
  pinMode(rgLed, INPUT);
}
void red(int del){ // turn on red LED for delay()
  pinMode(rgLed, OUTPUT);
  analogWrite(rgLed, 255);
  delay(del);
  pinMode(rgLed, INPUT);
}

void keepAwake(int dir){ // runs every time rottary encoder is turned to keep deviec awake
  lastCheck = millis();
  if(sleepState == 1){
    sleepState = 0;
  }
}

void sleep(){
  println("Sleeping");
  sleepState = 1;
  analogWrite(bLed, LOW);

  GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
  PCMSK |= _BV(PCINT2);                   // Use pin 2 as interrupt pin
  PCMSK |= _BV(PCINT3);                   // Use pin 3 as interrupt pin
  PCMSK &= ~_BV(PCINT3);                  // Turn off pin 3 as interrupt pin
  ADCSRA &= ~_BV(ADEN);                   // ADC off
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement

  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                                  // Enable interrupts
  sleep_cpu();                            // sleep

  cli();                                  // Disable interrupts
  PCMSK &= ~_BV(PCINT3);                  // Turn off PB3 as interrupt pin
  sleep_disable();                        // Clear SE bit
  ADCSRA |= _BV(ADEN);                    // ADC on

  sei();                                  // Enable interrupts
} 

void loop(){
  enc1newPins = 0; // Empty byte ready to shift-in new pins
  enc1newPins = (digitalRead(enc1pinA)<<1|digitalRead(enc1pinB)); // read the current state of encoder1 pins
  enc1move = RotaryDecodeTable[enc1oldPins][enc1newPins]; // used RotaryDecodeTable to decide movement, if any
  enc1oldPins = enc1newPins; // update encoder1state to be current pin values
  if (enc1move == B01){ // if result was move right (CW), decrement counter
    counter--;
    keepAwake();
  }
  if (enc1move == B10){ // if result was move left (anti-CW), inrement counter
    counter++;  
    keepAwake();        
  }

  // inactive > 10 secs so go into sleep state
  if ( (millis() - lastCheck > 10000) && sleepState == 0 ) {    // 10000 == 10 secs
    sleep(); 
  }
}