Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8df7e693bf
|
||
|
|
0e1e40254b
|
||
|
|
daf220600e
|
||
|
|
465a17789d
|
+11
-2
@@ -1,4 +1,13 @@
|
|||||||
set(COMPONENT_SRCS "app_main.c" "nokia.c" "knob.c" "gui.c")
|
set(COMPONENT_SRCS
|
||||||
set(COMPONENT_ADD_INCLUDEDIRS "")
|
"app_main.c"
|
||||||
|
"nokia.c"
|
||||||
|
"knob.c"
|
||||||
|
"gui.c"
|
||||||
|
"analog.c"
|
||||||
|
"liquid/liquid.c"
|
||||||
|
"liquid/scene_root.c"
|
||||||
|
"liquid/scene_car.c"
|
||||||
|
)
|
||||||
|
set(COMPONENT_ADD_INCLUDEDIRS "liquid")
|
||||||
|
|
||||||
register_component()
|
register_component()
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include "analog.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "driver/adc.h"
|
||||||
|
#include "esp_adc_cal.h"
|
||||||
|
|
||||||
|
static esp_adc_cal_characteristics_t *adc_chars;
|
||||||
|
|
||||||
|
// 32-39
|
||||||
|
static const adc1_channel_t channel = ADC1_CHANNEL_4; //GPIO34 if ADC1, GPIO14 if ADC2
|
||||||
|
|
||||||
|
static float measurement_celsius;
|
||||||
|
static const adc_atten_t atten = ADC_ATTEN_DB_0;
|
||||||
|
static const adc_unit_t unit = ADC_UNIT_1;
|
||||||
|
|
||||||
|
static void analog_service(void *arg);
|
||||||
|
|
||||||
|
static TaskHandle_t hAnalog;
|
||||||
|
|
||||||
|
#define DEFAULT_VREF 1100
|
||||||
|
#define NO_OF_SAMPLES 64
|
||||||
|
|
||||||
|
void analog_init() {
|
||||||
|
printf("Analog init\n");
|
||||||
|
|
||||||
|
adc1_config_width(ADC_WIDTH_BIT_12);
|
||||||
|
adc1_config_channel_atten(channel, atten);
|
||||||
|
adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
|
||||||
|
esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
|
||||||
|
|
||||||
|
int rv = xTaskCreate(analog_service, "analog", 4096, NULL, 6, &hAnalog);
|
||||||
|
assert (rv == pdPASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void __attribute__((noreturn)) analog_service(void *arg) {
|
||||||
|
while (1) {
|
||||||
|
uint32_t adc_reading = 0;
|
||||||
|
//Multisampling
|
||||||
|
for (int i = 0; i < NO_OF_SAMPLES; i++) {
|
||||||
|
adc_reading += adc1_get_raw(channel);
|
||||||
|
}
|
||||||
|
adc_reading /= NO_OF_SAMPLES;
|
||||||
|
|
||||||
|
//Convert adc_reading to voltage in mV
|
||||||
|
uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
|
||||||
|
|
||||||
|
#define CORRECT -10;
|
||||||
|
voltage += CORRECT;
|
||||||
|
|
||||||
|
// printf("Raw: %d ... Voltage: %dmV ...", adc_reading, voltage);
|
||||||
|
|
||||||
|
float volts = voltage * 0.001f;
|
||||||
|
|
||||||
|
#define R1 4750
|
||||||
|
#define V1 3.3f
|
||||||
|
float r_pt100 = (volts * R1)/(V1 - volts);
|
||||||
|
float celsius = (r_pt100/100.0f - 1.0f) / 3.9083E-3f;
|
||||||
|
// printf("Rpt %.3f, Celsius: %.1f\n", r_pt100, celsius);
|
||||||
|
|
||||||
|
measurement_celsius = celsius;
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float analog_read() {
|
||||||
|
return measurement_celsius;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* TODO file description
|
||||||
|
*
|
||||||
|
* Created on 2020/01/03.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REFLOWER_ANALOG_H
|
||||||
|
#define REFLOWER_ANALOG_H
|
||||||
|
|
||||||
|
void analog_init();
|
||||||
|
|
||||||
|
float analog_read();
|
||||||
|
|
||||||
|
#endif //REFLOWER_ANALOG_H
|
||||||
+2
-1
@@ -14,6 +14,7 @@
|
|||||||
#include "nokia.h"
|
#include "nokia.h"
|
||||||
#include "knob.h"
|
#include "knob.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
#include "analog.h"
|
||||||
|
|
||||||
|
|
||||||
void __attribute__((noreturn)) app_main()
|
void __attribute__((noreturn)) app_main()
|
||||||
@@ -28,8 +29,8 @@ void __attribute__((noreturn)) app_main()
|
|||||||
|
|
||||||
|
|
||||||
gui_init();
|
gui_init();
|
||||||
|
|
||||||
knob_init();
|
knob_init();
|
||||||
|
analog_init();
|
||||||
|
|
||||||
bool level = 0;
|
bool level = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|||||||
+68
-37
@@ -1,11 +1,17 @@
|
|||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "nokia.h"
|
#include "nokia.h"
|
||||||
|
#include "analog.h"
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
|
#include <liquid.h>
|
||||||
|
#include <freertos/timers.h>
|
||||||
|
|
||||||
static void gui_thread(void *arg);
|
static void gui_thread(void *arg);
|
||||||
|
static void gui_tick(TimerHandle_t xTimer);
|
||||||
|
|
||||||
TaskHandle_t hGuiThread = NULL;
|
TaskHandle_t hGuiThread = NULL;
|
||||||
|
TimerHandle_t hTicker = NULL;
|
||||||
|
|
||||||
|
|
||||||
void gui_init() {
|
void gui_init() {
|
||||||
printf("GUI init\n");
|
printf("GUI init\n");
|
||||||
@@ -19,58 +25,83 @@ void gui_init() {
|
|||||||
|
|
||||||
int rv = xTaskCreate(gui_thread, "gui", 4096, NULL, 6, &hGuiThread);
|
int rv = xTaskCreate(gui_thread, "gui", 4096, NULL, 6, &hGuiThread);
|
||||||
assert (rv == pdPASS);
|
assert (rv == pdPASS);
|
||||||
|
|
||||||
|
hTicker = xTimerCreate(
|
||||||
|
"gui_tick", /* name */
|
||||||
|
pdMS_TO_TICKS(10), /* period/time */
|
||||||
|
pdTRUE, /* auto reload */
|
||||||
|
(void*)0, /* timer ID */
|
||||||
|
gui_tick); /* callback */
|
||||||
|
assert(hTicker != NULL);
|
||||||
|
|
||||||
|
xTimerStart(hTicker, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gui_tick(TimerHandle_t xTimer) {
|
||||||
|
xTaskNotify(hGuiThread, 0b10000, eSetBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification API:
|
||||||
|
*
|
||||||
|
* 0b1 - knob CW
|
||||||
|
* 0b10 - knowb CCW
|
||||||
|
* 0b100 - button released
|
||||||
|
* 0b1000 - button pressed
|
||||||
|
* 0b10000 - ticker event
|
||||||
|
*
|
||||||
|
* @param arg
|
||||||
|
*/
|
||||||
static void __attribute__((noreturn)) gui_thread(void *arg) {
|
static void __attribute__((noreturn)) gui_thread(void *arg) {
|
||||||
uint32_t pos = 20;
|
struct Liquid *liquid = Liquid_start();
|
||||||
bool btn = 0;
|
|
||||||
#define NMAX 60
|
uint32_t last_wheel_time = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
xTaskNotifyWait(0, ULONG_MAX, &value, portMAX_DELAY);
|
xTaskNotifyWait(0, ULONG_MAX, &value, pdMS_TO_TICKS(10));
|
||||||
|
|
||||||
|
bool want_repaint = false;
|
||||||
|
|
||||||
// printf("Knob event 0x%02x ", value);
|
// printf("Knob event 0x%02x ", value);
|
||||||
|
|
||||||
if (value & 0b1000) {
|
if (value & 0b10000) {
|
||||||
// printf("PUSH ");
|
// TICK
|
||||||
btn = 1;
|
want_repaint |= Liquid_handleTick(liquid);
|
||||||
} else if (value & 0b100) {
|
|
||||||
btn = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value & 0b1000) {
|
||||||
|
want_repaint |= Liquid_handleInput(liquid, InputEvent_Button(1));
|
||||||
|
} else if (value & 0b100) {
|
||||||
|
want_repaint |= Liquid_handleInput(liquid, InputEvent_Button(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value & 0b11) {
|
||||||
|
uint32_t time = xTaskGetTickCount();
|
||||||
|
uint32_t increment = 1;
|
||||||
|
if (last_wheel_time != 0) {
|
||||||
|
uint32_t ela = time - last_wheel_time;
|
||||||
|
if (ela < pdMS_TO_TICKS(20)) {
|
||||||
|
increment = 25;
|
||||||
|
} else if (ela < pdMS_TO_TICKS(35)) {
|
||||||
|
increment = 10;
|
||||||
|
} else if (ela < pdMS_TO_TICKS(75)) {
|
||||||
|
increment = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_wheel_time = time;
|
||||||
|
|
||||||
if (value & 0b01) {
|
if (value & 0b01) {
|
||||||
// printf("FWD ");
|
want_repaint |= Liquid_handleInput(liquid, InputEvent_Wheel(increment));
|
||||||
if (pos == NMAX) {
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pos += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value & 0b10) {
|
if (value & 0b10) {
|
||||||
// printf("BACK ");
|
want_repaint |= Liquid_handleInput(liquid, InputEvent_Wheel(-increment));
|
||||||
if (pos == 0) {
|
|
||||||
pos = NMAX;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pos--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LCD_setRect(0, 15, 83, 35, 1, 1);
|
if (want_repaint) {
|
||||||
char buf[10];
|
Liquid_paint(liquid);
|
||||||
sprintf(buf, "%3d %s", pos, btn?"BTN":"");
|
}
|
||||||
LCD_setStr(buf, 2, 17, 0);
|
|
||||||
LCD_updateDisplay();
|
|
||||||
|
|
||||||
// printf(">");
|
|
||||||
// for (int i=0; i<pos; i++) {
|
|
||||||
// printf(" ");
|
|
||||||
// }
|
|
||||||
// printf("#");
|
|
||||||
// for (int i=pos; i<NMAX; i++) {
|
|
||||||
// printf(" ");
|
|
||||||
// }
|
|
||||||
// printf("<\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-309
@@ -8,16 +8,8 @@ const int pushPin = 5;
|
|||||||
const int wheelPin1 = 18;
|
const int wheelPin1 = 18;
|
||||||
const int wheelPin2 = 23;
|
const int wheelPin2 = 23;
|
||||||
|
|
||||||
//const int sigPin1 = 12;
|
#define DEBOUNCE_WHEEL_MS 2
|
||||||
//const int sigPin2 = 14;
|
#define DEBOUNCE_BTN_MS 5
|
||||||
|
|
||||||
#define DEBOUNCE_WHEEL_MS 3
|
|
||||||
#define DEBOUNCE_BTN_MS 10
|
|
||||||
|
|
||||||
static void handle_pushbtn(void *arg);
|
|
||||||
static void handle_wheel(void *arg);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void debounce_service(void *arg);
|
static void debounce_service(void *arg);
|
||||||
static TaskHandle_t hDebouncer;
|
static TaskHandle_t hDebouncer;
|
||||||
@@ -25,330 +17,92 @@ static TaskHandle_t hDebouncer;
|
|||||||
void knob_init() {
|
void knob_init() {
|
||||||
printf("Knob init\n");
|
printf("Knob init\n");
|
||||||
|
|
||||||
// gpio_config_t cfgWheel = {
|
|
||||||
// .pin_bit_mask = (1 << wheelPin1) /*| (1 << wheelPin2)*/,
|
|
||||||
// .mode = GPIO_MODE_INPUT,
|
|
||||||
// .pull_up_en = 1,
|
|
||||||
// .intr_type = GPIO_INTR_NEGEDGE, // neg means active
|
|
||||||
// };
|
|
||||||
// gpio_config(&cfgWheel);
|
|
||||||
|
|
||||||
gpio_config_t cfgPush = {
|
gpio_config_t cfgPush = {
|
||||||
.pin_bit_mask = (1 << pushPin) | (1 << wheelPin1),
|
.pin_bit_mask = (1 << pushPin) | (1 << wheelPin1) | (1 << wheelPin2),
|
||||||
.mode = GPIO_MODE_INPUT,
|
.mode = GPIO_MODE_INPUT,
|
||||||
.pull_up_en = 1,
|
.pull_up_en = 1
|
||||||
.intr_type = GPIO_INTR_ANYEDGE, // neg means active
|
|
||||||
};
|
};
|
||||||
gpio_config(&cfgPush);
|
gpio_config(&cfgPush);
|
||||||
|
|
||||||
// wheel2 without itr
|
int rv = xTaskCreate(debounce_service, "debo", 4096, NULL, 6, &hDebouncer);
|
||||||
cfgPush.intr_type = GPIO_INTR_DISABLE;
|
|
||||||
cfgPush.pin_bit_mask = (1 << wheelPin2);
|
|
||||||
gpio_config(&cfgPush);
|
|
||||||
|
|
||||||
// gpio_config_t output = {
|
|
||||||
// .pin_bit_mask = (1<<sigPin1)|(1<<sigPin2),
|
|
||||||
// .mode = GPIO_MODE_OUTPUT
|
|
||||||
// };
|
|
||||||
// gpio_config(&output);
|
|
||||||
|
|
||||||
gpio_install_isr_service(0);
|
|
||||||
gpio_intr_enable(pushPin);
|
|
||||||
gpio_intr_enable(wheelPin1);
|
|
||||||
// gpio_intr_enable(wheelPin2);
|
|
||||||
|
|
||||||
gpio_isr_handler_add(pushPin, handle_pushbtn, (void *)0);
|
|
||||||
gpio_isr_handler_add(wheelPin1, handle_wheel, (void *)0);
|
|
||||||
//gpio_isr_handler_add(wheelPin2, handle_wheel, (void *)1);
|
|
||||||
|
|
||||||
|
|
||||||
int rv = xTaskCreate(debounce_service, "debo", 2048, NULL, 6, &hDebouncer);
|
|
||||||
assert (rv == pdPASS);
|
assert (rv == pdPASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
enum state {
|
|
||||||
S_11 = 0,
|
|
||||||
|
|
||||||
S_FWD_1_01 = 1,
|
|
||||||
S_FWD_2_00 = 2,
|
|
||||||
S_FWD_3_10 = 3,
|
|
||||||
|
|
||||||
S_BCK_1_10 = 4,
|
|
||||||
S_BCK_2_00 = 5,
|
|
||||||
S_BCK_3_01 = 6,
|
|
||||||
|
|
||||||
S_ILLEGAL = 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SW_FWD 0b10000000
|
|
||||||
#define SW_BCK 0b01000000
|
|
||||||
|
|
||||||
static enum state wheelState = S_11;
|
|
||||||
|
|
||||||
const uint8_t switch_table[28] = {
|
|
||||||
/* -- S_11 -- */
|
|
||||||
S_ILLEGAL, /* 00 ILLEGAL */
|
|
||||||
S_FWD_1_01, /* 01 ADVANCE */
|
|
||||||
S_BCK_1_10, /* 10 BACK */
|
|
||||||
S_11, /* 11 */
|
|
||||||
|
|
||||||
/* -- S_FWD_1_01 -- */
|
|
||||||
S_FWD_2_00, /* 00 ADVANCE */
|
|
||||||
S_FWD_1_01, /* 01 */
|
|
||||||
S_FWD_3_10, /* 10 ILLEGAL */
|
|
||||||
S_11, /* 11 ABORT */
|
|
||||||
|
|
||||||
/* -- S_FWD_2_00 -- */
|
|
||||||
S_FWD_2_00, /* 00 */
|
|
||||||
S_FWD_1_01, /* 01 ABORT */
|
|
||||||
S_FWD_3_10, /* 10 ADVANCE */
|
|
||||||
S_ILLEGAL, /* 11 ILLEGAL */
|
|
||||||
|
|
||||||
/* -- S_FWD_3_10 -- */
|
|
||||||
S_FWD_2_00, /* 00 ABORT */
|
|
||||||
S_FWD_1_01, /* 01 ILLEGAL */
|
|
||||||
S_FWD_3_10, /* 10 */
|
|
||||||
SW_FWD | S_11, /* 11 ADVANCE */
|
|
||||||
|
|
||||||
/* -- S_BCK_1_10 -- */
|
|
||||||
S_BCK_2_00, /* 00 ADVANCE */
|
|
||||||
S_BCK_3_01, /* 01 ILLEGAL */
|
|
||||||
S_BCK_1_10, /* 10 */
|
|
||||||
S_11, /* 11 ABORT */
|
|
||||||
|
|
||||||
/* -- S_BCK_2_00 -- */
|
|
||||||
S_BCK_2_00, /* 00 */
|
|
||||||
S_BCK_3_01, /* 01 */
|
|
||||||
S_BCK_1_10, /* 10 ABORT */
|
|
||||||
S_ILLEGAL, /* 11 */
|
|
||||||
|
|
||||||
/* -- S_BCK_3_01 -- */
|
|
||||||
S_BCK_2_00, /* 00 */
|
|
||||||
S_BCK_3_01, /* 01 */
|
|
||||||
S_BCK_1_10, /* 10 */
|
|
||||||
SW_BCK | S_11, /* 11 */
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t OldEnc = 0b00;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void handle_wheel(void *arg) {
|
|
||||||
static uint32_t negedge_time = 0;
|
|
||||||
static uint32_t posedge_time = 0;
|
|
||||||
static bool last_edge_level = 1;
|
|
||||||
static bool flipflop = 0;
|
|
||||||
|
|
||||||
const uint32_t inputs = gpio_input_get();
|
|
||||||
const bool a = 0 != (inputs & (1 << wheelPin1)); // neg = active
|
|
||||||
const bool b = 0 != (inputs & (1 << wheelPin2));
|
|
||||||
|
|
||||||
// This discards "false rising edge" when we get triggered by a rising edge
|
|
||||||
//
|
|
||||||
if (a == last_edge_level) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
last_edge_level = a;
|
|
||||||
|
|
||||||
const uint32_t time = xTaskGetTickCount();
|
|
||||||
|
|
||||||
flipflop ^= 1;
|
|
||||||
// gpio_set_level(sigPin2, flipflop);
|
|
||||||
|
|
||||||
int dir = 0;
|
|
||||||
if (!a) {
|
|
||||||
if ((time - posedge_time) > pdMS_TO_TICKS(DEBOUNCE_WHEEL_MS)) {
|
|
||||||
// negedge
|
|
||||||
negedge_time = time;
|
|
||||||
// gpio_set_level(sigPin1, 0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// posedge
|
|
||||||
if ((time - negedge_time) > pdMS_TO_TICKS(DEBOUNCE_WHEEL_MS)) {
|
|
||||||
posedge_time = time;
|
|
||||||
if (b) {
|
|
||||||
dir = -1;
|
|
||||||
} else {
|
|
||||||
dir = 1;
|
|
||||||
}
|
|
||||||
// gpio_set_level(sigPin1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
const uint32_t inputs = gpio_input_get();
|
|
||||||
bool a = 0 == (inputs & (1 << wheelPin1)); // neg = active
|
|
||||||
bool b = 0 == (inputs & (1 << wheelPin2));
|
|
||||||
|
|
||||||
#define ENCODER_POS1 1
|
|
||||||
#define ENCODER_POS2 2
|
|
||||||
#define ENCODER_POS3 3
|
|
||||||
#define ENCODER_POS0 0
|
|
||||||
|
|
||||||
uint8_t NewEnc = a | (b<<1);
|
|
||||||
if (NewEnc ^ OldEnc) { // Encoder value changed???
|
|
||||||
switch(NewEnc) {
|
|
||||||
case ENCODER_POS1 : // 01
|
|
||||||
if (OldEnc == ENCODER_POS0) // 00
|
|
||||||
dir--;
|
|
||||||
else
|
|
||||||
dir++;
|
|
||||||
break;
|
|
||||||
case ENCODER_POS3 : // 11
|
|
||||||
if (OldEnc == ENCODER_POS1) // 01
|
|
||||||
dir--;
|
|
||||||
else
|
|
||||||
dir++;
|
|
||||||
break;
|
|
||||||
case ENCODER_POS2 : // 10
|
|
||||||
if (OldEnc == ENCODER_POS3) // 11
|
|
||||||
dir--;
|
|
||||||
else
|
|
||||||
dir++;
|
|
||||||
break;
|
|
||||||
case ENCODER_POS0 : // 00
|
|
||||||
if (OldEnc == ENCODER_POS2) // 10
|
|
||||||
dir--;
|
|
||||||
else
|
|
||||||
dir++;
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
OldEnc = NewEnc;
|
|
||||||
}; // end if encoder value changed.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Omron version
|
|
||||||
int which = (int)arg;
|
|
||||||
|
|
||||||
const uint32_t inputs = gpio_input_get();
|
|
||||||
|
|
||||||
bool a = 0 == (inputs & (1 << wheelPin1)); // neg = active
|
|
||||||
bool b = 0 == (inputs & (1 << wheelPin2));
|
|
||||||
|
|
||||||
if (which == 0) { // itr from A
|
|
||||||
if (a) {
|
|
||||||
if (b) {
|
|
||||||
dir = -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dir = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // itr from B
|
|
||||||
if (b) {
|
|
||||||
if (a) {
|
|
||||||
dir = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dir = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Naive version
|
|
||||||
int which = arg;
|
|
||||||
|
|
||||||
const uint32_t inputs = gpio_input_get();
|
|
||||||
|
|
||||||
bool a = 0 == (inputs & (1 << wheelPin1)); // neg = active
|
|
||||||
bool b = 0 == (inputs & (1 << wheelPin2));
|
|
||||||
|
|
||||||
if (which == 0) { // itr from A
|
|
||||||
if (b) {
|
|
||||||
dir = -1;
|
|
||||||
} /*else {
|
|
||||||
dir = 1;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
else { // itr from B
|
|
||||||
if (a) {
|
|
||||||
dir = 1;
|
|
||||||
} /*else {
|
|
||||||
dir = -1;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// More complex version
|
|
||||||
const uint32_t inputs = gpio_input_get();
|
|
||||||
const uint8_t ab =
|
|
||||||
(((inputs >> wheelPin2) & 1) << 1) |
|
|
||||||
((inputs >> wheelPin1) & 1);
|
|
||||||
|
|
||||||
if (wheelState == S_ILLEGAL) {
|
|
||||||
if (ab != 0b11) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t next = switch_table[wheelState*4 + ab];
|
|
||||||
|
|
||||||
if (next & SW_FWD) dir = 1;
|
|
||||||
if (next & SW_BCK) dir = -1;
|
|
||||||
next &= ~(SW_FWD | SW_BCK);
|
|
||||||
|
|
||||||
wheelState = next;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dir != 0) {
|
|
||||||
BaseType_t higherWoken = 0;
|
|
||||||
xTaskNotifyFromISR(hGuiThread, dir == 1 ? 0b10 : 0b01, eSetBits, &higherWoken);
|
|
||||||
if (higherWoken) portYIELD_FROM_ISR();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((noreturn)) debounce_service(void *arg) {
|
static void __attribute__((noreturn)) debounce_service(void *arg) {
|
||||||
bool push_state = 0;
|
struct debo {
|
||||||
uint32_t push_change_time = 0;
|
bool state;
|
||||||
|
uint32_t start_time;
|
||||||
|
uint32_t debo_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct debo state[3] = {
|
||||||
|
{.debo_time = pdMS_TO_TICKS(DEBOUNCE_BTN_MS)}, // push
|
||||||
|
{.debo_time = pdMS_TO_TICKS(DEBOUNCE_WHEEL_MS), .state=1}, // wheel input 1
|
||||||
|
{.debo_time = pdMS_TO_TICKS(DEBOUNCE_WHEEL_MS), .state=1} // wheel input 2
|
||||||
|
};
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// uint32_t value = 0;
|
|
||||||
// xTaskNotifyWait(0, ULONG_MAX, &value, pdMS_TO_TICKS(1));
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1));
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
|
|
||||||
uint32_t now = xTaskGetTickCount();
|
uint32_t now = xTaskGetTickCount();
|
||||||
|
|
||||||
const uint32_t inputs = gpio_input_get();
|
const uint32_t inputs = gpio_input_get();
|
||||||
bool pushed = (inputs & (1 << pushPin)) == 0;
|
|
||||||
|
|
||||||
if (pushed) { // event "PUSHED"
|
bool input[3] = {
|
||||||
if (!push_state) {
|
(inputs & (1 << pushPin)) == 0,
|
||||||
if (push_change_time == 0) {
|
(inputs & (1 << wheelPin1)) != 0,
|
||||||
push_change_time = now;
|
(inputs & (1 << wheelPin2)) != 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum change {
|
||||||
|
CHG_NONE = 2,
|
||||||
|
CHG_SET = 1,
|
||||||
|
CHG_CLEAR = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum change changes[3] = {CHG_NONE, CHG_NONE, CHG_NONE};
|
||||||
|
|
||||||
|
for (int i=0; i<3;i++) {
|
||||||
|
if (input[i] == !state[i].state) {
|
||||||
|
// Change detected
|
||||||
|
if (state[i].start_time == 0) {
|
||||||
|
// start counting
|
||||||
|
state[i].start_time = now;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
push_change_time = 0;
|
if ((state[i].start_time != 0) && (now - state[i].start_time > state[i].debo_time)) {
|
||||||
|
state[i].state = !state[i].state;
|
||||||
|
changes[i] = state[i].state ? CHG_SET : CHG_CLEAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // event "RELEASED"
|
else {
|
||||||
if (push_state) {
|
// returned back to original, reset counter
|
||||||
if (push_change_time == 0) {
|
state[i].start_time = 0;
|
||||||
push_change_time = now;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
push_change_time = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((push_change_time != 0) && (now - push_change_time > pdMS_TO_TICKS(DEBOUNCE_BTN_MS))) {
|
uint32_t signal = 0;
|
||||||
push_state = !push_state;
|
|
||||||
|
// Wheel logic
|
||||||
|
if (changes[1] == CHG_SET) {
|
||||||
|
if (state[2].state) {
|
||||||
|
signal |= 0b01;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
signal |= 0b10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// knob
|
||||||
|
if (changes[0] != CHG_NONE) {
|
||||||
|
signal |= 0b100 << changes[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// send event to GUI
|
||||||
|
if (signal != 0) {
|
||||||
BaseType_t higherWoken = 0;
|
BaseType_t higherWoken = 0;
|
||||||
xTaskNotifyFromISR(hGuiThread, 0b100<<push_state, eSetBits, &higherWoken);
|
xTaskNotifyFromISR(hGuiThread, signal, eSetBits, &higherWoken);
|
||||||
if (higherWoken) portYIELD_FROM_ISR();
|
if (higherWoken) portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_pushbtn(void *arg) {
|
|
||||||
// const uint32_t inputs = gpio_input_get();
|
|
||||||
// bool pushed = (inputs & (1 << pushPin)) == 0;
|
|
||||||
//
|
|
||||||
// BaseType_t higherWoken = 0;
|
|
||||||
// xTaskNotifyFromISR(hDebouncer, 1<<pushed, eSetBits, &higherWoken);
|
|
||||||
// if (higherWoken) portYIELD_FROM_ISR();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#include "liquid.h"
|
||||||
|
#include "rom/queue.h"
|
||||||
|
#include "scenes.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
|
||||||
|
static const char *TAG = "Liquid";
|
||||||
|
|
||||||
|
struct RunningScene {
|
||||||
|
struct Scene *scene;
|
||||||
|
SLIST_ENTRY(RunningScene) next;
|
||||||
|
} cmd_item_t;
|
||||||
|
|
||||||
|
struct Liquid {
|
||||||
|
SLIST_HEAD(, RunningScene) stack; // stack with the topmost scene as the first element / head
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct SceneEvent Default_onChildReturn(struct Scene *scene, uint32_t tag, uint32_t status, void *data) {
|
||||||
|
if (data) free(data);
|
||||||
|
return SceneEvent_Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addChild(struct Liquid *container, struct Scene *child) {
|
||||||
|
struct RunningScene *elm = calloc(1, sizeof(struct RunningScene));
|
||||||
|
if (!child->onChildReturn) child->onChildReturn = Default_onChildReturn;
|
||||||
|
assert(child->paint != NULL);
|
||||||
|
elm->scene = child;
|
||||||
|
SLIST_INSERT_HEAD(&container->stack, elm, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Liquid *Liquid_start() {
|
||||||
|
struct Liquid *container = calloc(1, sizeof(struct Liquid));
|
||||||
|
|
||||||
|
addChild(container, NewScene_Root());
|
||||||
|
Liquid_paint(container);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct SceneEvent handleSceneEvent(struct Liquid *container, struct SceneEvent event) {
|
||||||
|
struct RunningScene *topmost = SLIST_FIRST(&container->stack);
|
||||||
|
switch (event.kind) {
|
||||||
|
case SceneEventKind_Close:
|
||||||
|
assert(SLIST_NEXT(topmost, next) != NULL);
|
||||||
|
SLIST_REMOVE_HEAD(&container->stack, next);
|
||||||
|
uint32_t tag = topmost->scene->tag;
|
||||||
|
|
||||||
|
if (topmost->scene->options) {
|
||||||
|
free(topmost->scene->options);
|
||||||
|
}
|
||||||
|
free(topmost->scene);
|
||||||
|
free(topmost);
|
||||||
|
|
||||||
|
topmost = SLIST_FIRST(&container->stack);
|
||||||
|
|
||||||
|
// this is always set.
|
||||||
|
return topmost->scene->onChildReturn(topmost->scene, tag, event.close.status, event.close.data);
|
||||||
|
|
||||||
|
case SceneEventKind_OpenChild:;
|
||||||
|
if (!event.open.scene) {
|
||||||
|
ESP_LOGE(TAG, "Attempt to open NULL scene!");
|
||||||
|
return SceneEvent_None();
|
||||||
|
}
|
||||||
|
struct Scene *newScene = event.open.scene;
|
||||||
|
newScene->tag = event.open.tag;
|
||||||
|
addChild(container, newScene);
|
||||||
|
return SceneEvent_Repaint();
|
||||||
|
|
||||||
|
case SceneEventKind_RequestRepaint:
|
||||||
|
case SceneEventKind_None:
|
||||||
|
default:
|
||||||
|
// this shouldn't get here
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool processReturnValue(struct Liquid *container, struct SceneEvent result) {
|
||||||
|
while (result.kind != SceneEventKind_None) {
|
||||||
|
if (result.kind == SceneEventKind_RequestRepaint) {
|
||||||
|
return 1; // repaint
|
||||||
|
}
|
||||||
|
result = handleSceneEvent(container, result);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Liquid_handleInput(struct Liquid *container, struct InputEvent event) {
|
||||||
|
struct RunningScene *topmost = SLIST_FIRST(&container->stack);
|
||||||
|
assert(topmost != NULL);
|
||||||
|
assert(topmost->scene != NULL);
|
||||||
|
if (topmost->scene->onInput) {
|
||||||
|
struct SceneEvent result = topmost->scene->onInput(topmost->scene, event);
|
||||||
|
return processReturnValue(container, result);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Liquid_handleTick(struct Liquid *container) {
|
||||||
|
struct RunningScene *topmost = SLIST_FIRST(&container->stack);
|
||||||
|
assert(topmost != NULL);
|
||||||
|
assert(topmost->scene != NULL);
|
||||||
|
if (topmost->scene->onTick) {
|
||||||
|
struct SceneEvent result = topmost->scene->onTick(topmost->scene);
|
||||||
|
return processReturnValue(container, result);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Liquid_paint(struct Liquid *container) {
|
||||||
|
struct RunningScene *topmost = SLIST_FIRST(&container->stack);
|
||||||
|
assert(topmost != NULL);
|
||||||
|
topmost->scene->paint(topmost->scene);
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
/**
|
||||||
|
* GUI framework
|
||||||
|
*
|
||||||
|
* Created on 2020/01/03.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REFLOWER_LIQUID_H
|
||||||
|
#define REFLOWER_LIQUID_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct Liquid;
|
||||||
|
|
||||||
|
enum InputEvent_Kind {
|
||||||
|
InputEventKind_Wheel,
|
||||||
|
InputEventKind_Button,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InputEvent {
|
||||||
|
enum InputEvent_Kind kind;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
// Wheel delta
|
||||||
|
int8_t delta;
|
||||||
|
} wheel;
|
||||||
|
struct {
|
||||||
|
// Button state
|
||||||
|
bool state;
|
||||||
|
} button;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#define InputEvent_Wheel(delta_) ((struct InputEvent) { \
|
||||||
|
.kind = InputEventKind_Wheel, \
|
||||||
|
.wheel = { .delta = delta_ } \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define InputEvent_Button(state_) ((struct InputEvent) { \
|
||||||
|
.kind = InputEventKind_Button, \
|
||||||
|
.button = { .state = state_ }, \
|
||||||
|
})
|
||||||
|
|
||||||
|
enum SceneEvent_Kind {
|
||||||
|
// Close this scene.
|
||||||
|
// The scene is responsible for cleaning up 'private'.
|
||||||
|
// 'options' and the scene itself will be freed by the GUI engine.
|
||||||
|
SceneEventKind_Close,
|
||||||
|
SceneEventKind_OpenChild,
|
||||||
|
SceneEventKind_RequestRepaint,
|
||||||
|
SceneEventKind_None,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SceneEvent {
|
||||||
|
enum SceneEvent_Kind kind;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
// Status code
|
||||||
|
uint32_t status;
|
||||||
|
// Return data on heap
|
||||||
|
void *data;
|
||||||
|
} close;
|
||||||
|
struct {
|
||||||
|
// Scene (initialized, with options loaded in through the constructor)
|
||||||
|
void *scene;
|
||||||
|
// Tag used by parent to identify the open child
|
||||||
|
uint32_t tag;
|
||||||
|
} open;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Scene;
|
||||||
|
|
||||||
|
#define SceneEvent_None() ((struct SceneEvent) { \
|
||||||
|
.kind = SceneEventKind_None\
|
||||||
|
})
|
||||||
|
|
||||||
|
#define SceneEvent_Repaint() ((struct SceneEvent) { \
|
||||||
|
.kind = SceneEventKind_RequestRepaint\
|
||||||
|
})
|
||||||
|
|
||||||
|
#define SceneEvent_OpenChild(child_, tag_) ((struct SceneEvent) { \
|
||||||
|
.kind = SceneEventKind_OpenChild,\
|
||||||
|
.open = { .scene = (child_), .tag=tag_ }, \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define SceneEvent_Close(status_, data_) ((struct SceneEvent) { \
|
||||||
|
.kind = SceneEventKind_Close,\
|
||||||
|
.close = { .status = (status_), .data=(data_) }, \
|
||||||
|
})
|
||||||
|
|
||||||
|
typedef struct SceneEvent (*Scene_onInput_t)(struct Scene *scene, struct InputEvent event);
|
||||||
|
typedef struct SceneEvent (*Scene_onChildReturn_t)(struct Scene *scene, uint32_t tag, uint32_t status, void *data);
|
||||||
|
typedef struct SceneEvent (*Scene_onTick_t)(struct Scene *scene);
|
||||||
|
typedef void (*Scene_repaint_t)(struct Scene *scene);
|
||||||
|
|
||||||
|
struct Scene {
|
||||||
|
uint32_t tag;
|
||||||
|
void *options;
|
||||||
|
void *private;
|
||||||
|
/** Handle input */
|
||||||
|
Scene_onInput_t onInput;
|
||||||
|
/** Handle child scene return */
|
||||||
|
Scene_onChildReturn_t onChildReturn;
|
||||||
|
/** Periodic tick */
|
||||||
|
Scene_onTick_t onTick;
|
||||||
|
/** Periodic tick */
|
||||||
|
Scene_repaint_t paint;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate scene and the inner private type.
|
||||||
|
*
|
||||||
|
* Requires <malloc.h>
|
||||||
|
*
|
||||||
|
* Must be used like:
|
||||||
|
*
|
||||||
|
* struct Scene *scene = SCENE_SAFE_ALLOC(struct private);
|
||||||
|
* scene->onInput = ...
|
||||||
|
* return scene;
|
||||||
|
*/
|
||||||
|
#define SCENE_SAFE_ALLOC(private_type) \
|
||||||
|
calloc(1, sizeof(struct Scene)); \
|
||||||
|
if (!scene) return NULL; \
|
||||||
|
scene->private = calloc(1, sizeof(private_type)); \
|
||||||
|
if (!scene->private) return NULL;
|
||||||
|
|
||||||
|
/** return 1 if repaint requested */
|
||||||
|
bool Liquid_handleInput(struct Liquid *container, struct InputEvent event);
|
||||||
|
|
||||||
|
/** return 1 if repaint requested */
|
||||||
|
bool Liquid_handleTick(struct Liquid *container);
|
||||||
|
|
||||||
|
void Liquid_paint(struct Liquid *container);
|
||||||
|
struct Liquid *Liquid_start();
|
||||||
|
|
||||||
|
#endif //REFLOWER_LIQUID_H
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include "scenes.h"
|
||||||
|
#include "liquid.h"
|
||||||
|
#include "../nokia.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
struct private {
|
||||||
|
int32_t pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct SceneEvent Car_onInput(struct Scene *scene, struct InputEvent event) {
|
||||||
|
struct private *priv = scene->private;
|
||||||
|
switch (event.kind) {
|
||||||
|
case InputEventKind_Wheel:
|
||||||
|
priv->pos += event.wheel.delta;
|
||||||
|
if (priv->pos < 0) priv->pos = 0;
|
||||||
|
if (priv->pos > LCD_WIDTH-21) priv->pos = LCD_WIDTH-21;
|
||||||
|
return SceneEvent_Repaint();
|
||||||
|
|
||||||
|
case InputEventKind_Button:
|
||||||
|
if (event.button.state) {
|
||||||
|
return SceneEvent_Close(0, NULL);
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
|
default:
|
||||||
|
return SceneEvent_None();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Car_paint(struct Scene *scene)
|
||||||
|
{
|
||||||
|
struct private *priv = scene->private;
|
||||||
|
|
||||||
|
LCD_clearDisplay(0);
|
||||||
|
LCD_setRect(priv->pos, LCD_HEIGHT/2-10, priv->pos+20,LCD_HEIGHT/2+10,0,1);
|
||||||
|
LCD_updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Scene *NewScene_Car(void) {
|
||||||
|
struct Scene *scene = SCENE_SAFE_ALLOC(struct private);
|
||||||
|
|
||||||
|
scene->onInput = Car_onInput;
|
||||||
|
scene->paint = Car_paint;
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
#include "scenes.h"
|
||||||
|
#include "liquid.h"
|
||||||
|
#include "../nokia.h"
|
||||||
|
#include "../analog.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct private {
|
||||||
|
int32_t pos;
|
||||||
|
uint32_t timer_phase;
|
||||||
|
uint32_t timer_prescale;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct SceneEvent Root_onInput(struct Scene *scene, struct InputEvent event) {
|
||||||
|
struct private *priv = scene->private;
|
||||||
|
switch (event.kind) {
|
||||||
|
case InputEventKind_Wheel:
|
||||||
|
priv->pos += event.wheel.delta;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputEventKind_Button:
|
||||||
|
if (event.button.state) {
|
||||||
|
return SceneEvent_OpenChild(NewScene_Car(), 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SceneEvent_Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct SceneEvent Root_onTick(struct Scene *scene) {
|
||||||
|
struct private *priv = scene->private;
|
||||||
|
priv->timer_prescale += 1;
|
||||||
|
|
||||||
|
if (priv->timer_prescale == 100) {
|
||||||
|
priv->timer_prescale = 0;
|
||||||
|
priv->timer_phase += 1;
|
||||||
|
priv->timer_phase = priv->timer_phase & 0b11; // 0..3
|
||||||
|
|
||||||
|
return SceneEvent_Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SceneEvent_None();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Root_paint(struct Scene *scene)
|
||||||
|
{
|
||||||
|
struct private *priv = scene->private;
|
||||||
|
|
||||||
|
LCD_clearDisplay(0);
|
||||||
|
const char *header = "???";
|
||||||
|
switch (priv->timer_phase) {
|
||||||
|
case 0:
|
||||||
|
header = "ICE";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
header = " COLD";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
header = "COCA";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
header = " COLA";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LCD_setStr(header, 20, 3, 1);
|
||||||
|
|
||||||
|
LCD_setRect(0, 15, 83, 35, 1, 1);
|
||||||
|
char buf[10];
|
||||||
|
sprintf(buf, "%3d", priv->pos);
|
||||||
|
LCD_setStr(buf, 2, 17, 0);
|
||||||
|
sprintf(buf, "%.0f C", analog_read());
|
||||||
|
LCD_setStr(buf, 2, 26, 0);
|
||||||
|
LCD_updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Scene *NewScene_Root(void) {
|
||||||
|
struct Scene *scene = SCENE_SAFE_ALLOC(struct private);
|
||||||
|
|
||||||
|
scene->onInput = Root_onInput;
|
||||||
|
scene->paint = Root_paint;
|
||||||
|
scene->onTick = Root_onTick;
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* TODO file description
|
||||||
|
*
|
||||||
|
* Created on 2020/01/03.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REFLOWER_SCENES_H
|
||||||
|
#define REFLOWER_SCENES_H
|
||||||
|
|
||||||
|
struct Scene *NewScene_Root(void);
|
||||||
|
struct Scene *NewScene_Car(void);
|
||||||
|
|
||||||
|
#endif //REFLOWER_SCENES_H
|
||||||
+1
-1
@@ -345,7 +345,7 @@ void LCD_setChar(char character, int x, int y, bool bw)
|
|||||||
// progressive coordinates until it's done.
|
// progressive coordinates until it's done.
|
||||||
// This function was grabbed from the SparkFun ColorLCDShield
|
// This function was grabbed from the SparkFun ColorLCDShield
|
||||||
// library.
|
// library.
|
||||||
void LCD_setStr(char *dString, int x, int y, bool bw)
|
void LCD_setStr(const char *dString, int x, int y, bool bw)
|
||||||
{
|
{
|
||||||
while (*dString != 0x00) // loop until null terminator
|
while (*dString != 0x00) // loop until null terminator
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -44,7 +44,7 @@ void LCD_setChar(char character, int x, int y, bool bw);
|
|||||||
// progressive coordinates until it's done.
|
// progressive coordinates until it's done.
|
||||||
// This function was grabbed from the SparkFun ColorLCDShield
|
// This function was grabbed from the SparkFun ColorLCDShield
|
||||||
// library.
|
// library.
|
||||||
void LCD_setStr(char * dString, int x, int y, bool bw);
|
void LCD_setStr(const char * dString, int x, int y, bool bw);
|
||||||
|
|
||||||
// This function clears the entire display either white (0) or
|
// This function clears the entire display either white (0) or
|
||||||
// black (1).
|
// black (1).
|
||||||
|
|||||||
Reference in New Issue
Block a user