#include "dosimeter.h" #include #include DosimeterType Dosimeter; static float getCalibrationFactor(int type) { switch(type) { case J305: case M4011: return 0.0065; break; default: return NAN; } } int type; volatile int buckets[BUCKETS_PER_MINUTE] = {0}; int last = 0; bool valid = false; bool measureDose = false; volatile float dose = 0; ESP8266Timer timer; static inline void clearISR() { unsigned long gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status); } static void ICACHE_RAM_ATTR geigerISR() { int next = (millis() / BUCKET_WIDTH_IN_MS) % BUCKETS_PER_MINUTE; if (last != next) { for (int i = (last + 1) % BUCKETS_PER_MINUTE; i != next; i = (i + 1) % BUCKETS_PER_MINUTE) { buckets[i] = 0; } buckets[next] = 1; last = next; } else { buckets[next]++; } clearISR(); } // timerISR gets called every minute static void ICACHE_RAM_ATTR timerISR() { if (measureDose && valid) { dose += Dosimeter.getEquivalentDoseRate() / 60; } } void DosimeterType::begin(int pin, int _type) { type = _type; pinMode(pin, INPUT); attachInterrupt(digitalPinToInterrupt(pin), geigerISR, RISING); timer.attachInterruptInterval(60l * 1000 * 1000, timerISR); } int DosimeterType::getCPM() { int result = 0; for (int i = 0; i < BUCKETS_PER_MINUTE; i++) { result += buckets[i]; } return result; } float DosimeterType::getEquivalentDoseRate() { return getCPM() * getCalibrationFactor(type); } float DosimeterType::getEquivalentDose() { if (measureDose) { return dose; } else { return NAN; } } bool DosimeterType::isValid() { if (valid) { return true; } else { valid = millis() > (60l * 1000); return valid; } } void DosimeterType::startRecording() { dose = 0; measureDose = true; } void DosimeterType::stopRecording() { measureDose = false; }