/*
 * Arduino
 *   board: MicroCore/attiny13 (https://github.com/MCUdude/MicroCore) v2.2.0
 *   clock: 1.2MHz
 *   brown out: 1.8V
 *   eeprom: retained
 *   micros: disabled
 *   
 * touchCount
 *    idle 870 + noise 3-4 -> threshold 5 ~= signal shift 0.6%
 *    lower noise with grounded case
 *  baseCount
 *    https://www.ti.com/lit/pdf/slaa521
 *    
 * power consumption:
 *    30uA Sleep
 *   110uA Sample
 *    70mA Led
 *   
 *  MCP1643
 *    Schottky diode at Vcc to have Vcc < Vled at full batteries
 *    both LEDs over shunt resistor, because at > 4.7 Ohm already at control limit
 *    designed for higher power -> efficiency here < 70%
 *      
 *  Icon
 *    https://www.flaticon.com/de/kostenloses-icon/die-gluhbirne_74072 512px copy into 600dpi picture and invert
 */
 
#include 
#include "ADCTouch.h" // = https://github.com/MCUdude/MicroCore/pull/133
//#include 
#include 

#define DEBUG_PRINT 1

#define PIN_RXD PIN_PB0
#define PIN_TXD PIN_PB1
#define PIN_UNUSED PIN_PB2
#define PIN_TOUCH A3 // = PB3
#define PIN_LED PIN_PB4

const uint16_t ADCTouch::samples = 8;
const int16_t  touchThreshold = 6;
      int16_t  touchBaseCount = 0;
const long     sleepMillis = 250; // sample each 1/4 sec

const int8_t   outOnSec = 15;
      int8_t   outOnTime = 0; // >0 time in 1/4sec unit, 0 calibrate, -1 sample
#if DEBUG_PRINT  
      int16_t  outOnCount = 0;
      int16_t  maxDiff = 0;
#endif

void setup() {
#if DEBUG_PRINT  
  // c:\Users\kai\AppData\Local\Arduino15\packages\MicroCore\hardware\avr\2.2.0\libraries\Serial_examples\examples\OscillatorCalibration\OscillatorCalibration.ino 
  // 0x3B-D      for 19200 baud @ 1.2MHz and 115000 baud @ 9.6MHz
  // 0x31;0x41   for 38400 baud @ 4.8MHz; n/a for 600KHz
  uint8_t cal = EEPROM.read(0);
  if (cal < 0x80)
    OSCCAL = cal;
#else
  pinMode(PIN_RXD, INPUT_PULLUP);
  pinMode(PIN_TXD, INPUT_PULLUP);
#endif    
  pinMode(PIN_UNUSED, INPUT_PULLUP);
  pinMode(PIN_LED, OUTPUT); 
  for(int i=0; i<6; i++) {
    ADCTouch::read(PIN_TOUCH); // fully discharge
    delay(250);
    PORTB = PORTB ^ _BV(PIN_LED);
  }
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
  sleep_enable();
  // outOnTime == 0 -> calibrate at first loop()
}

void loop() {
  digitalWrite(PIN_LED, outOnTime>0 ? HIGH : LOW);
  uint32_t m = millis();
  while (millis() - m < sleepMillis)
    sleep_mode(); // wake up each 16ms by watchdog timer

  //noInterrupts(); // no difference
  int16_t touchCount = ADCTouch::read(PIN_TOUCH);
  //interrupts();
  int16_t diff = touchCount - touchBaseCount;
  if(outOnTime == 0) { // voltage (and therefore ADC value) increases for older batteries after light off -> calibrate & skip 1 value
    diff = 0;
    touchBaseCount = touchCount;
    outOnTime--;
  }
  if(diff > 0) {
    touchBaseCount++;
  } else {
    touchBaseCount = (touchCount + touchBaseCount)/2;
  }
  if(diff >= touchThreshold) {
    if(outOnTime < 0)
      outOnCount++;
    outOnTime = 4 * outOnSec;
  }
  if(outOnTime > 0) {
    outOnTime--;
  }
#if DEBUG_PRINT  
  if(diff > maxDiff)
    maxDiff = diff; 
  Serial.print(outOnCount);
  Serial.print(' ');
  Serial.print(touchCount);
  Serial.print(' ');
  Serial.print(touchBaseCount);
  Serial.print(' ');
  Serial.print(diff);
  Serial.print(' ');
  Serial.print(maxDiff);
  Serial.print('\n');
 #endif
}