sketch.ino 3.8 KB
#include <heisenwave.h>
#include <LCD.h>
#include <Time.h>

#define SIZE 256

// LCD stuff

char ino_alias[16];
uint8_t last_second = 0;
uint8_t lcd_swap = 0;
LCD lcd;

// ADC stuff

volatile uint8_t frame_1[SIZE];
volatile uint8_t frame_2[SIZE];
volatile uint8_t *buffer = frame_1;
volatile uint8_t *pc_buffer = frame_1;
volatile uint8_t index = 0;
volatile uint8_t pc_index = 0;
volatile bool transfer_active = false;
volatile bool transfer_ready = false;

// ISR routines

ISR(ADC_vect) {
  buffer[index++] = ADCH;

  if (index == 0) {
    buffer = (buffer == frame_1)? frame_2 : frame_1;
    pc_buffer = (buffer == frame_1)? frame_2 : frame_1;

    // will this double buffer system be enough?...
    // if transfer = true => not enough!...
    // we could disable interrupts while send_data...?

    transfer_ready = true;
  }
}

// Procedures && functions

void send_data() {
  if (transfer_active && transfer_ready) {
    Serial.write(HW_NEW_FRAME);

    for (int i = 0; i < SIZE; i++) {
      Serial.write(pc_buffer[i]);
    }

    transfer_ready = false;
  }
}

void print_time_lcd() {
  bool alias_turn;
  char buffer[4];
  lcd.clear_screen();

  if (++lcd_swap >= 10) {
    lcd_swap = 0;
  }

  if (lcd_swap < 5) {
    lcd.print(ino_alias);
  } else {
    lcd.set_cursor(3,1);
    lcd.print(dayShortStr(day()));
    lcd.print("/");
    lcd.print(monthShortStr(month()));
    lcd.print("/");
    sprintf(buffer, "%d", year());
    lcd.print(buffer);
  }

  lcd.set_cursor(5,2);

  sprintf(buffer, "%d", hour());
  if (strlen(buffer) < 2) lcd.print("0");
  lcd.print(buffer);lcd.print(":");
  sprintf(buffer, "%d", minute());
  if (strlen(buffer) < 2) lcd.print("0");
  lcd.print(buffer);lcd.print(":");
  sprintf(buffer, "%d", second());
  if (strlen(buffer) < 2) lcd.print("0");
  lcd.print(buffer);
}

void hardware_setup() {
  // Max Prescaler
  ADCSRA |= (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0) | (1<<ADATE) | (1<<ADEN) | (1<<ADIE);
  ADMUX |= (1<<REFS0) | (1<<ADLAR);
  ADMUX &= ~(1<<REFS1);
  ADCSRB &= ~((1<<ADTS2) | (1<<ADTS1) | (1<<ADTS0));
  ADCSRA |= (1<<ADSC);    
}

// Main

void setup() {
  hardware_setup();
  Serial.begin(115200);

  lcd.clear_screen();
  lcd.backlight(true);

  //Serial.write(HW_ACK);
  Serial.write("HW");
  Serial.write(HW_INO_VERSION_MAJOR);
  Serial.write(HW_INO_VERSION_MINOR);
}

void loop() {
  send_data();

  uint8_t current;
  if (current = second(), last_second != current) {
    print_time_lcd();
    last_second = current;
  }

  if (Serial.available() < 1) {
    switch (Serial.read()) {
      case HW_HELO:
        {
          while (Serial.available() < HW_HELO_SIZE);

          for (byte i = 0; i < HW_HELO_SIZE; i++) {
            ino_alias[i] = Serial.read();
          }

          Serial.write(HW_ACK);
        }
      case HW_SMPL_RATE:
        {
          // change register

          break;
        }
      case HW_DTIME_GET:
        {
          Serial.write(HW_ACK);
          Serial.write((byte *) now(), sizeof(uint32_t));

          break;
        }
      case HW_DTIME_SET:
        {
          while (Serial.available() < HW_DATE_SIZE);

          uint32_t unix_time = 0;
          for (uint8_t i = HW_DATE_SIZE-1; i >= 0; i--) {
            unix_time += Serial.read() << (8*i);
          }
          setTime(unix_time);

          Serial.write(HW_ACK);

          break;
        }
      case HW_SLEEP:
        {
          SMCR = 0; // (mode) low power reduction
          SMCR |= (1 << SE);
          asm volatile("sleep");

          // ZzZzZ

          SMCR = 0;

          break;
        }
      case HW_GET_DATA:
        {
          transfer_active = true;

          break;
        }
      case HW_STOP_DATA:
        {
          // Stop sending chunks?
          transfer_active = false;

          break;
        }
      default:
        // This should never happen, command ignored
        break;
    }
  }
}