Kamil Cukrowski / Mbed 2 deprecated STM32_Button_Interrupt_dla_taty

Dependencies:   mbed DS18B20 TextLCD

Files at this revision

API Documentation at this revision

Comitter:
KamilCuk
Date:
Thu Feb 13 16:27:38 2020 +0000
Child:
1:f8a4796e766e
Commit message:
Working version

Changed in this revision

DS18B20.lib Show annotated file Show diff for this revision Revisions of this file
DebounceIn.lib Show annotated file Show diff for this revision Revisions of this file
TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
atomic_flag.h Show annotated file Show diff for this revision Revisions of this file
flash.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DS18B20.lib	Thu Feb 13 16:27:38 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/rodolphemichel/code/DS18B20/#ddee20f8438d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DebounceIn.lib	Thu Feb 13 16:27:38 2020 +0000
@@ -0,0 +1,1 @@
+https://github.com/pilotak/DebounceIn/#7d408feeea3f141279e273990187e4dbff796140
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TextLCD.lib	Thu Feb 13 16:27:38 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/6CM8/code/TextLCD/#2db641efba7e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atomic_flag.h	Thu Feb 13 16:27:38 2020 +0000
@@ -0,0 +1,13 @@
+#include <mbed.h>
+
+class atomic_flag {
+    volatile core_util_atomic_flag _data;
+public:
+    atomic_flag() { clear(); }
+    atomic_flag( const atomic_flag& );
+    atomic_flag& operator=( const atomic_flag& );
+    atomic_flag& operator=( const atomic_flag& ) volatile;
+    void clear() { core_util_atomic_flag_clear(&_data); }
+    bool test_and_set() { return core_util_atomic_flag_test_and_set(&_data); }
+};
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash.h	Thu Feb 13 16:27:38 2020 +0000
@@ -0,0 +1,109 @@
+#ifndef FLASH_H
+#define FLASH_H
+
+#include "mbed.h"
+#include <cassert>
+#include <limits>
+
+void lcd_println(const char *fmt, ...);
+extern "C" void d(const char *fmt, ...);
+
+namespace flash {
+    static inline void _page_erase(uint32_t page) {
+        uint32_t page_error = 0;
+        FLASH_EraseInitTypeDef s_eraseinit;
+        s_eraseinit.TypeErase   = FLASH_TYPEERASE_PAGES;
+        s_eraseinit.PageAddress = page;
+        s_eraseinit.NbPages     = 1;
+        const HAL_StatusTypeDef status = 
+            HAL_FLASHEx_Erase(&s_eraseinit, &page_error);
+        if (status) d("ERR: HFP %d", status);
+    }
+    
+    static const uintptr_t _page = 0x0800F400;
+    static const uint16_t _mark = 0xbeef + 1;
+    
+    static inline void _write16(uintptr_t address, uint16_t val) {
+        // d("W %lx=%04x", _page + address, val);
+        const HAL_StatusTypeDef status = 
+            HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, _page + address * 2, val);
+        if (status) d("ERR: HFP %d", status);
+    }
+    
+    static inline uint16_t _read16(uintptr_t address) {
+        const uint16_t val = *(volatile uint16_t *)(_page + address * 2);
+        // d("RR %lx=%04x", _page + address, val);
+        return val;
+    }
+
+    static inline void write(const void *data, size_t len) {
+        assert(len < FLASH_PAGE_SIZE - 2);
+        assert(len < std::numeric_limits<uint16_t>::max());
+        HAL_FLASH_Unlock();
+        _page_erase(_page);
+        flash::_write16(0, _mark);
+        flash::_write16(1, len);
+        for (size_t i = 0; i < len; i += 2) {
+            uint16_t var = 0;
+            const size_t to_copy = 1 + (i + 2 < len);
+            memcpy(&var, data, to_copy);    
+            flash::_write16(2 + i / 2, var);
+            data = (const char*)data + to_copy;
+        }   
+        HAL_FLASH_Lock();
+    }
+    
+    static inline int read(void *data, size_t len) {
+        assert(len < FLASH_PAGE_SIZE - 2);
+        assert(len < std::numeric_limits<uint16_t>::max());
+        const uint16_t read_mark = flash::_read16(0);
+        if (read_mark != _mark) {
+            memset(data, '0', len);
+            return -1;
+        }
+        const uint16_t read_len = flash::_read16(1);
+        if (read_len != len) {
+            memset(data, '0', len);
+            return -2;
+        }
+        for (size_t i = 0; i < len; i += 2) {
+            const uint16_t var = flash::_read16(2 + i / 2);
+            const size_t to_copy = 1 + (i + 2 < len);
+            memcpy(data, &var, to_copy);
+            data = (char*)data + to_copy;
+        }
+        return 0;
+    }
+    
+    template<typename T>
+    static inline void write(const T &t) {
+        flash::write((const void*)&t, sizeof(t));
+    }
+    
+    template<typename T>
+    static inline int read(T &t) {
+        return flash::read((void*)&t, sizeof(t));
+    }
+        
+    static inline void test() {
+        lcd_println("testing flash");
+        lcd_println("testing flash 2");
+        wait(1);
+        
+        while (1) {
+            char buf[6] = {0};
+            const int e = flash::read(buf, 5);
+            int i = atoi(buf);
+            if (i == 0) i = 12345;
+            lcd_println("FR%d %d: %s", e, i, buf);
+            
+            snprintf(buf, sizeof(buf), "%d", i + 1);
+            lcd_println("FW: %s", buf);
+            flash::write(buf, 5);
+            
+            wait(1);
+        }        
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Feb 13 16:27:38 2020 +0000
@@ -0,0 +1,344 @@
+#include "mbed.h"
+#include "TextLCD.h"
+#include <atomic_flag.h>
+#include <string>
+#include <cstdio>
+#include <cassert>
+#include <cstdarg>
+#include <DS1820.h>
+#include <DebounceIn.h>
+#include <limits>
+#include <flash.h>
+#include <cassert>
+
+static DigitalOut led_on_board(PC_13);
+
+/* str --------------------------------------------- */
+
+void str_remove(char *str, const char *reject) {
+    while (1) {
+        const size_t s = strcspn(str, reject);
+        str += s;
+        if (str[0] == '\0') {
+            break;
+        }
+        memmove(str, str + 1, strlen(str + 1) + 1);
+    }
+}
+
+void str_pad_suffix(char *str, size_t len, char c) {
+    if (strlen(str) < len) {
+        memset(str + strlen(str), c, len - strlen(str));
+    }
+    str[len] = '\0';
+}
+
+char *str_filename(const char *file) {
+    return (char*)(strrchr(file, '/') ? strrchr(file, '/') + 1 : file);
+}
+
+/* lcd ------------------------------------------------- */
+
+static TextLCD& lcd() {
+    static TextLCD lcd(PB_15, PA_10, PB_3, PB_4, PB_5, PB_6, TextLCD::LCD16x2); // rs, e, d4-d7
+    // static TextLCD lcd(PA_0, PA_1, PA_2, PA_3, PA_4, PA_5, TextLCD::LCD16x2); // rs, e, d4-d7
+    return lcd;
+}
+
+void lcd_cls() {
+    lcd().cls();
+}
+
+void lcd_vprintln(const char *fmt, va_list va) {
+    char buf[20] = {0};
+    const size_t len = vsnprintf(buf, sizeof(buf), fmt, va);
+    str_remove(buf, "\r\n");
+    str_pad_suffix(buf, 16, ' ');
+    lcd().printf(buf);
+}
+
+__attribute__((__format__(__printf__, 1, 2)))
+void lcd_println(const char *fmt, ...) {
+    va_list va;
+    va_start(va, fmt);
+    lcd_vprintln(fmt, va);
+    va_end(va);
+}
+
+extern "C" {
+    void d(const char *fmt, ...) {
+        va_list va;
+        va_start(va, fmt);
+        lcd_vprintln(fmt, va);
+        va_end(va);
+        wait(1);
+    }
+}
+    
+/* system --------------------------------------------- */
+
+extern "C" void abort() {
+    for (int i = 0; i < 20 * 5; ++i) {
+        led_on_board = !led_on_board;
+        wait(0.05);
+    }
+    NVIC_SystemReset();
+}
+
+extern "C" void __assert_func(const char *file, int line, const char *func, const char *failedexpr) {
+  lcd_println("ASSERT %d", line);
+  lcd_println("%s", str_filename(file));
+  abort();
+}
+
+
+/* ds18b20 --------------------------------------------- */
+
+/**
+ * @return
+ *              0 - no errors ('temp' contains the temperature measured)
+ *              1 - sensor not present ('temp' is not updated)
+ *              2 - CRC error ('temp' is not updated)
+ */
+static int ds18b20_temp(float& temperature_f_C) {
+    static DS1820 probe('B', PB_1);
+    static Timer t;
+    static bool running = false;
+    
+    // start the conversion if not running
+    if (running == false) {
+        running = true;
+        probe.startConversion();
+        t.start();
+    }
+    
+    // wait for conversion end
+    const unsigned ms = t.read_ms();
+    const unsigned conversion_time_ms = 800;
+    if (ms < conversion_time_ms) {
+        wait((conversion_time_ms - ms) / 1000.0);
+    }
+    
+    // read temperature from buffer
+    temperature_f_C = -1000;
+    const uint8_t err = probe.read(temperature_f_C);
+    
+    // restart new conversion
+    probe.startConversion();
+    t.reset();
+    
+    return err;
+}
+
+/* output -------------------------------------------- */
+
+static DigitalOut output(PC_14);
+
+/* state --------------------------------------------- */
+
+struct state {
+    volatile int high;  // in Celcius
+    volatile int low;   // in Celcius
+    volatile bool inverted;
+    
+    state() : high(30), low(20) {}
+    
+    struct data {
+        static const int data_version = 0x11;
+        int version;
+        int high;
+        int low;
+        bool inverted : 1;
+        bool current : 1;
+        data() : version(data_version) {}
+        data(const state& s, const DigitalOut& o) : 
+            version(data_version),
+            high(s.high), 
+            low(s.low), 
+            inverted(s.inverted), 
+            current(output) 
+            {}
+        void put(state& s, DigitalOut& o) {
+            s.high = high;
+            s.low = low;
+            s.inverted = inverted;
+            o = current;
+        }
+    };
+    
+    static bool _low_high_valid(int high, int low) {
+        return -99 < high && high < 99 &&
+                -99 < low && low < 99 &&
+                low < high &&
+                low != high;
+    }
+    
+    void save() {
+        const struct data d(*this, output);
+        flash::write(d);
+    }
+    
+    void restore() {
+        struct data d;
+        const int e = flash::read(d);
+        if (e) {
+            lcd_println("New flash %d", e);
+            wait(1);
+            return;
+        }
+        if (!_low_high_valid(d.high, d.low)) {
+            lcd_println("Invalid flash vals");
+            lcd_println("%d %d", d.high, d.low);
+            wait(1);
+            return;
+        }
+        lcd_println("Flash load %d %d", d.high, d.low);
+        wait(1);
+        d.put(*this, output);
+    }
+    
+    void high_inc() { _inc_it(high, low); }
+    void high_dec() { _dec_it(high, low); }
+    void low_inc() { _inc_it(low, high); }
+    void low_dec() { _dec_it(low, high); }    
+    void invert_invert() {
+        inverted = !inverted;
+        save();
+    }
+    
+private:
+    void _inc_it(volatile int &val, volatile int &other) {
+        if (val + 1 == other) return;
+        if (val >= 99) return;
+        val++;
+        save();
+    }
+    void _dec_it(volatile int &val, volatile int &other) {
+        if (val - 1 == other) return;
+        if (val <= -99) return;
+        val--;
+        save();
+    }
+};
+
+static state state;
+
+
+/* buttons -------------------------------------------- */
+
+static DebounceIn button_h_inc(PA_6, PullDown);
+static DebounceIn button_h_dec(PA_5, PullDown);
+static DebounceIn button_l_inc(PA_4, PullDown);
+static DebounceIn button_l_dec(PA_3, PullDown);
+static DebounceIn button_inv(PA_2, PullDown);
+static DebounceIn button_refresh(PA_1, PullDown);
+
+static void button_h_inc_pressed() { state.high_inc(); }
+static void button_h_dec_pressed() { state.high_dec(); }
+static void button_l_inc_pressed() { state.low_inc(); }
+static void button_l_dec_pressed() { state.low_dec(); }
+static void button_inv_pressed() {
+    output = !output;
+    state.invert_invert();
+}
+
+static void button_init() {
+    const unsigned debounce_timeout_us = 200 * 1000;
+    button_h_inc.fall(button_h_inc_pressed, debounce_timeout_us);
+    button_h_dec.fall(button_h_dec_pressed, debounce_timeout_us);
+    button_l_inc.fall(button_l_inc_pressed, debounce_timeout_us);
+    button_l_dec.fall(button_l_dec_pressed, debounce_timeout_us);
+    button_inv.fall(button_inv_pressed, debounce_timeout_us * 2);
+}
+    
+
+static void button_check() {
+    while(1) {
+        DebounceIn *arr[6] = {
+            &button_h_inc,
+            &button_h_dec,
+            &button_l_inc,
+            &button_l_dec,
+            &button_inv,
+            &button_refresh
+        };
+        lcd_println("%d %d %d %d %d %d\n",
+            arr[0]->read(),
+            arr[1]->read(),
+            arr[2]->read(),
+            arr[3]->read(),
+            arr[4]->read(),
+            arr[5]->read());
+        lcd_println("");
+    }
+}
+
+/* main --------------------------- */
+
+static void setup() {    
+    // wait for voltage stability
+    wait(1);
+    // some info
+    lcd_cls();
+    lcd_println("Hello!");
+    lcd_println("clock=%ld", SystemCoreClock);
+    wait(1);
+    lcd_cls();
+    state.restore();
+    button_init();
+}
+
+static void loop() {
+    static bool alive;
+    alive = !alive;
+    
+    float temperature_f_C = 0;
+    const int ds18b20_err = ds18b20_temp(temperature_f_C);
+    
+    lcd_cls();
+    
+    char temperature_s[8] = "ERROR";
+    if (ds18b20_err == 0) {
+        const int temperature_dC = temperature_f_C * 10;
+        const int temperature_C = temperature_f_C;
+        
+        if (temperature_C < -100 || temperature_C > 100) {
+            snprintf(temperature_s, sizeof(temperature_s), "INVAL");
+        } else {
+                        
+            if (!output ^ state.inverted) {
+                if (temperature_C > state.high) {
+                    output = 1 ^ state.inverted;
+                }
+            } else {
+                if (temperature_C < state.low) {
+                    output = 0 ^ state.inverted;
+                }
+            }
+            
+            snprintf(temperature_s, sizeof(temperature_s), "%3d.%d'C", temperature_C, temperature_dC % 10);
+        }
+    }
+    
+    led_on_board = output;
+
+    lcd_println("%-7s %3s  %3s",
+            temperature_s,
+            state.inverted ? "INV" : "NOR",
+            output ? "ON" : "OFF"
+    );
+    lcd_println("H=%2d'C L=%2d'C %c%c", 
+            state.high,
+            state.low, 
+            !alive ? '\xff' : ' ',
+            alive ? '\xff' : ' '
+    );
+}
+
+int main() {
+    setup();
+    while (1) {
+        loop();
+    }
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Feb 13 16:27:38 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file