Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed DS18B20 TextLCD
Revision 0:55c37ea095b0, committed 2020-02-13
- Comitter:
- KamilCuk
- Date:
- Thu Feb 13 16:27:38 2020 +0000
- Child:
- 1:f8a4796e766e
- Commit message:
- Working version
Changed in this revision
--- /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