#include "Arduino.h" #include "LowLevel.h" #include "SerialChannel.h" #define LEDPin 13 #define OWPin 2 #define InterruptNumber 0 // Must correspond to the OWPin to correctly detect state changes. On Arduino Uno, interrupt 0 is for digital pin 2 #define ResetMinDuration 480 #define ResetMaxDuration 900 #define PresenceWaitDuration 30 #define PresenceDuration 300 SerialChannel debug("debug"); Pin owPin(OWPin); Pin owOutTestPin(3); Pin led(LEDPin); void owPullLow() { owPin.outputMode(); owPin.writeLow(); owOutTestPin.writeLow(); } void owRelease() { owPin.inputMode(); owOutTestPin.writeHigh(); } void owWrite(bool value) { if (value) owRelease(); else owPullLow(); } unsigned long resetStart = (unsigned long)-1; void setup() { led.outputMode(); owPin.inputMode(); owOutTestPin.outputMode(); owOutTestPin.writeHigh(); led.writeLow(); cli(); // disable interrupts attachInterrupt(InterruptNumber,onewireInterrupt,CHANGE); // set timer0 interrupt at 250KHz (actually depends on compare match register OCR0A) // 4us between each tick TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; // initialize counter value to 0 //TCCR1B |= (1 << WGM12); // turn on CTC mode //TCCR1B |= (1 << CS11) | (1 << CS10); // Set 64 prescaler TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt sei(); // enable interrupts Serial.begin(400000); } //int count = 0; void loop() { //if ((count++) % 1000 == 0) // led.write(!led.read()); cli();//disable interrupts SerialChannel::swap(); sei();//enable interrupts SerialChannel::flush(); } void(*timerEvent)() = 0; void setTimerEvent(short microSecondsDelay, void(*event)()) { microSecondsDelay -= 10; // this seems to be the typical time taken to initialize the timer on Arduino Uno short skipTicks = (microSecondsDelay - 3) / 4; // round the micro seconds delay to a number of ticks to skip (4us per tick, so 4us must skip 0 tick, 8us must skip 1 tick, etc.) if (skipTicks < 1) skipTicks = 1; //debug.SC_APPEND_STR_INT("setTimerEvent", (long)skipTicks); TCNT1 = 0; OCR1A = skipTicks; timerEvent = event; TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // turn on CTC mode with 64 prescaler } void onewireInterrupt(void) { bool state = owPin.read(); unsigned long now = micros(); //led.write(state); if (!state) resetStart = now; if (state) { unsigned long resetDuration = resetStart == (unsigned long)-1 ? (unsigned long)-1 : now - resetStart; resetStart = (unsigned long)-1; if (resetDuration >= ResetMinDuration && resetDuration <= ResetMaxDuration) { //debug.SC_APPEND_STR_TIME("reset", now); setTimerEvent(PresenceWaitDuration - (micros() - now), &beginPresence); return; } } } void beginPresence() { //debug.SC_APPEND_STR("beginPresence"); owPullLow(); owOutTestPin.writeLow(); setTimerEvent(PresenceDuration, &endPresence); } void endPresence() { //debug.SC_APPEND_STR("endPresence"); owRelease(); } ISR(TIMER1_COMPA_vect) // timer1 interrupt { TCCR1B = 0; // disable clock void(*event)() = timerEvent; timerEvent = 0; if (event != 0) event(); }