/* Soil Sensor Firmware * Timekeeping * Sensiplicity Systems * * Copyright 2015 * * Department of Botany and Plant Pathology * Center for Genome Research and Biocomputing * Oregon State University * Corvallis, OR 97331 * * This program is not free software; you can not redistribute it and/or * modify it at all. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include "time.h" static volatile uint32_t Uptime; /* Initialize and start the uptime counter. */ void init_timer(void){ TCCR0B = _BV(CS02) | _BV(CS00); /* Set clk/1024. */ TIMSK0 = _BV(TOIE0); /* Enable overflow interrupt. */ } ISR(TIMER0_OVF_vect){ /* Due to the /1024 division factor, calculating when a second has elapsed * is a bit complicated. */ static uint32_t residual; residual += 262144; /* 1024 clock pulses * 256 timer counts. */ if(residual >= 2000000){ Uptime++; residual -= 2000000; } } /* Get the number of seconds since the system was powered on. */ uint32_t get_uptime(void){ uint32_t local_uptime; ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ local_uptime = Uptime; } return local_uptime; } /* Wait for a condition to become true, timing out after a given * time. The condition is defined by a value, mask, and polarity. * The mask is a bitmask that selects bit(s) in a value. If polarity * is not 0, the condition is true when any of the bits are 1. If * polarity is 0, the condition is true when all are 0. * * The timeout value is in milliseconds. The maximum timeout is 127 milliseconds. * * Returns 0 if the condition became true, -1 if a timeout occurred. */ int8_t wait_condition(volatile uint8_t *value, uint8_t mask, uint8_t polarity, uint8_t timeout_ms){ uint8_t count_orig = TCNT0; uint8_t wrap = 1; timeout_ms *= 2; /* Convert to 1/2 milliseconds. */ timeout_ms += count_orig; /* Get the value of TCNT0 ms from now. * This value can be less than or greater than the current * value, due to wrap-around. */ if(timeout_ms < count_orig){ wrap = 0; /* Wait for counter to wrap around before timing out. */ } while(1){ if(polarity){ if(*value & mask){ return 0; } } else { if(!(*value & mask)){ return 0; } } if(1 == wrap){ /* Counter can be compared. */ if(TCNT0 >= timeout_ms)return -1; } else { /* Counter must wrap around first. */ if(TCNT0 <= timeout_ms)wrap = 1; } } }