/* -------------------------------------------------------- eventsources.cpp Sourcecode Ereignisquellen (event-sources) fuer ein eventbasierendes System in Arduino OHNE Verwendung von Interrupts 04.05.2026 R. Seelig -------------------------------------------------------- */ #include "eventsources.h" /* ###################################################################### TIMERADC ###################################################################### */ TIMERADC::TIMERADC(uint8_t pin, uint8_t tevent) { adcpin = pin; event = tevent; minvalue= 40; adcdiv = 3; } /* ---------------------------------------------------------------------- TIMERADC::setstarttime erfasst, wann TimerA gestartet wurde ---------------------------------------------------------------------- */ void TIMERADC::setstarttime(void) { starttime = millis(); } /* ---------------------------------------------------------------------- TIMERADC::getadcmillis liest den ADC und berechnet daraus die Zeitbasis ---------------------------------------------------------------------- */ int TIMERADC::getadcmillis(void) { return ((analogRead(adcpin) / adcdiv) + minvalue); } /* ---------------------------------------------------------------------- TIMERADC::getstate stellt fest, ob Zeit abgelaufen ist ---------------------------------------------------------------------- */ uint8_t TIMERADC::getstate(void) { if (millis() - starttime > getadcmillis()) return event; else return 0x00; } /* ---------------------------------------------------------------------- TIMERADC::setMinvalue ---------------------------------------------------------------------- */ void TIMERADC::setminvalue(uint16_t value) { if (value > 2000) value = 2000; minvalue = value; } /* ---------------------------------------------------------------------- TIMERADC::setadcdiv ---------------------------------------------------------------------- */ void TIMERADC::setadcdiv(uint16_t value) { if (value == 0) value = 1; if (value > 100) value = 100; adcdiv = value; } /* ---------------------------------------------------------------------- TIMERADC::begin initialisiert GPIO-Pin als Eingang ---------------------------------------------------------------------- */ void TIMERADC::begin(void) { pinMode(adcpin, INPUT); } /* ###################################################################### TIMERSOFT ###################################################################### */ TIMERSOFT::TIMERSOFT(uint16_t ovf, uint8_t tevent) { overflow = ovf; event = tevent; } /* ---------------------------------------------------------------------- TIMERSOFT::setstarttime ---------------------------------------------------------------------- */ void TIMERSOFT::setstarttime(void) { starttime = millis(); } /* ---------------------------------------------------------------------- TIMERSOFT::getstate ---------------------------------------------------------------------- */ uint8_t TIMERSOFT::getstate(void) { if (millis() - starttime > overflow) return event; else return 0x00; } /* ---------------------------------------------------------------------- TIMERSOFT::setoverflow ---------------------------------------------------------------------- */ void TIMERSOFT::setoverflow(uint16_t ovf) { overflow = ovf; } /* ###################################################################### GPIOCHANGE ###################################################################### */ GPIOCHANGE::GPIOCHANGE(uint8_t gpiopin, uint8_t tevent) { iopin = gpiopin; state = 0; event = tevent; } /* ---------------------------------------------------------------------- GPIOCHANGE::read liest einen GPIO-Pin Rueckgabe: 0x00 .. 0x01 entsprechend des GPIO-Logiklevels ---------------------------------------------------------------------- */ uint8_t GPIOCHANGE::read(void) { uint8_t pinval = 0x00; if (digitalRead(iopin)) pinval = 0x01; return pinval; } /* ---------------------------------------------------------------------- GPIOCHANGE::getchange stellt fest, ob sich der Logikpegel des GPIO-Pins geaendert hat. Wenn ja, wird in state eingetragen und Event fuer getchange ausgeloest. Rueckgabe: 0x00: wenn GPIO unveraendert event: wenn GPIO veraendert ---------------------------------------------------------------------- */ uint8_t GPIOCHANGE::getChange(void) { uint8_t pinstate = read(); if (pinstate != state) { state = pinstate; return event; } return 0; } /* ---------------------------------------------------------------------- GPIOCHANGE::getstate liefert aktuell gespeicherten GPIO-Zustand ---------------------------------------------------------------------- */ uint8_t GPIOCHANGE::getState(void) { return state; } /* ---------------------------------------------------------------------- GPIOCHANGE::begin initialisiert GPIO-Pin als Eingang ---------------------------------------------------------------------- */ void GPIOCHANGE::begin(void) { pinMode(iopin, INPUT_PULLUP); state = read(); } /* ###################################################################### SYSTICKER ###################################################################### */ /* ------------------------------------------------------------- Konstruktor ------------------------------------------------------------- */ SYSTICKER::SYSTICKER(uint8_t tevent) { event = tevent; seconds = 0; lastmillis = millis(); remainder = 0; secondsflag = 0; } /* ------------------------------------------------------------- update berechnet aus dem Arduino-Systemticker millis() ueber Differenzbildung die abgelaufenen Sekunden seit dem letzten update-Aufruf. Nicht "Millisekundenreste" werden beim naechsten update beruecksichtigt ------------------------------------------------------------- */ void SYSTICKER::update() { uint32_t now; uint32_t diff; uint32_t total; uint32_t sec; now = millis(); diff = now - lastmillis; lastmillis = now; total = diff + remainder; sec = total / 1000; remainder = total % 1000; if(sec > 0) { seconds += sec; secondsflag = 1; } } /* ------------------------------------------------------------- getstate fuehrt eine Synchronisation (update) mittels millis() durch und gibt ein event zurueck, wenn seit dem letzten update eine Sekunde oder mehr vergangen ist ------------------------------------------------------------- */ uint8_t SYSTICKER::getstate() { update(); if(secondsflag) { return event; } return 0; } /* ###################################################################### DATETIME ###################################################################### */ /* ------------------------------------------------------------- Konstruktor ------------------------------------------------------------- */ DATETIME::DATETIME(uint8_t tevent) { event = tevent; } /* ------------------------------------------------------------- isschaltjahr Stellt fest, ob es ein Schaltjahr ist oder nicht. Rueckgabe: 1 : Schaltjahr 0 : kein Schaltjahr ------------------------------------------------------------- */ uint8_t DATETIME::isschaltjahr(int year) { // - Schaltjahr ist, wenn: // - durch 4 teilbar, aber nicht durch 100 // - durch 400 teilbar if ((year % 400) == 0) return 1; if ((year % 100) == 0) return 0; if ((year % 4) == 0) return 1; return 0; } /* ------------------------------------------------------------- monthlen Ermittelt die Anzahl Tage eines Monats fuer ein gegebenes Jahr Rueckgabe: Anzahl Tage ------------------------------------------------------------- */ uint8_t DATETIME::monthlen(int year, uint8_t month) { if (month == 2) return 28 + isschaltjahr(year); // Juli und August haben beide 31 Tage ( Knoechel einer Hand Regel :-) ) if (month > 7) month++; return 30 + (month & 1); } /* ------------------------------------------------------------- stamp2date Ermittelt aus dem Zeitstempel stamp (Sekunden die seit dem 01.01. des Jahres, die in yearofs angegeben sind, vergangen sind) das Datum und traegt diese in die entspr. Variable ein. ------------------------------------------------------------- */ void DATETIME::stamp2date(void) { uint32_t tmp = stamp; // <<< lokale Arbeitsvariable (wichtig!) year = yearofs; do { if (tmp >= (secPerYear + (secPerDay * isschaltjahr(year)))) { tmp -= (secPerYear + (secPerDay * isschaltjahr(year))); year++; } } while (tmp >= (secPerYear + (secPerDay * isschaltjahr(year)))); month = 1; do { if (tmp >= (secPerDay * monthlen(year, month))) { tmp -= (secPerDay * monthlen(year, month)); month++; } } while (tmp >= (secPerDay * monthlen(year, month))); day = 1; do { if (tmp >= secPerDay) { tmp -= secPerDay; day++; } } while (tmp >= secPerDay); hour = 0; do { if (tmp >= secPerHour) { tmp -= secPerHour; hour++; } } while (tmp >= secPerHour); minute = 0; do { if (tmp >= secPerMin) { tmp -= secPerMin; minute++; } } while (tmp >= secPerMin); second = tmp; } /* ------------------------------------------------------------- date2stamp Ermittelt aus dem Kalenderdatum der Klassenmember den Zeitstempel (vergangene Sekunden seit dem 01.01. des Jahres, das in yearofs angegeben ist) und traegt diesen in stamp ein ------------------------------------------------------------- */ void DATETIME::date2stamp(void) { uint32_t cnt1, cnt2; cnt1= 0; cnt2= 0; while (cnt1 + yearofs < year) { cnt2 += secPerYear + (secPerDay * isschaltjahr(cnt1 + yearofs)); cnt1++; } cnt1 = 1; while (cnt1 < month) { cnt2 += monthlen(year, cnt1) * secPerDay; cnt1++; } cnt1 = 1; while (cnt1 < day) { cnt2 += secPerDay; cnt1++; } cnt1 = 0; while (cnt1 < hour) { cnt2 += secPerHour; cnt1++; } cnt1 = 0; while (cnt1 < minute) { cnt2 += secPerMin; cnt1++; } cnt2 += second; stamp= cnt2; } /* ------------------------------------------------------------- getwtag Berechnet zu einem bestimmten Datum den Wochentag (nach Carl Friedrich Gauss): Rueckgabe: der Tag der Woche, beginnend ab Sonntag. Sonntag entspricht 0. Bsp.: 1719813788ul Mo: 01.07.2024 06:03.08 Rueckgabe: 1 ------------------------------------------------------------- */ char DATETIME::getwtag(void) { int w_tag; uint16_t y = year; uint8_t m = month; if (m < 3) { m = m + 12; y--; } w_tag = (day + 2 * m + (3 * m+3) / 5 + \ y + y/4 - y/100 + y/400 + 1) % 7 ; return w_tag; }