Skip to content

Commit

Permalink
Merge pull request #5 from vladkorotnev/develop
Browse files Browse the repository at this point in the history
v2.1
  • Loading branch information
vladkorotnev authored Jul 23, 2024
2 parents f0c06f1 + df57165 commit 600014d
Show file tree
Hide file tree
Showing 72 changed files with 3,592 additions and 275 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Personal Information System OS (formerly Plasma Information Screen OS).

A somewhat portable relatively-stylish pixel-art clock/weather station.

## System Requirements

The basic configuration without any bluetooth functionality (no Switchbot or Balance Board integration) seems to work just fine on an ESP32 WROOM. However to be less limited by RAM size in further features I've decided to make WROVER the requirement, so further versions are not guaranteed to run on WROOM.

## Predefined target devices

* `DEVICE_PLASMA_CLOCK`: a [clock](https://youtu.be/D4MiHmhhjeQ) that I built around a plasma screen from an old Japanese bus/train.
Expand All @@ -28,13 +32,13 @@ A somewhat portable relatively-stylish pixel-art clock/weather station.
### Software flags

* `HAS_WORDNIK_API`: compile with the Word Of The Day service using [Wordnik API](https://developer.wordnik.com/). This requires SSL, so bloats the firmware size significantly.
* `HAS_BLUETOOTH_LE`: automatically set on ESP32. Required for Switchbot-over-BLE. Uses [NimBLE](https://github.com/apache/mynewt-nimble), but still increases firmware size significantly.
* `HAS_BLUETOOTH_LE`: automatically set on ESP32. Required for Switchbot-over-BLE. Uses Arduino-BLE and increases firmware size significantly.
* `HAS_OTAFVU`: OTA updates via ArduinoOTA. Currently disabled due to partition size constraints from the above.

### Thermal sensors

* AM2322 over IIC ([driver](src/sensor/am2322.cpp), feature flag `HAS_TEMP_SENSOR`)
* Switchbot Meter over BLE (unstable, [driver](src/sensor/switchbot/api.cpp), feature flag `SWITCHBOT_METER_INTEGRATION`)
* Switchbot Meter over BLE (unstable, [driver](src/sensor/switchbot/api.cpp), feature flag `SWITCHBOT_METER_INTEGRATION`, needs extra ram of a WROVER module)

### Motion sensors

Expand All @@ -44,6 +48,15 @@ A somewhat portable relatively-stylish pixel-art clock/weather station.

* Opto-resistor in voltage divider mode ([driver](src/sensor/light.cpp), feature flag `HAS_LIGHT_SENSOR`)

### HID

* Keypad/D-Pad. Set feature flag `HAS_KEYPAD` and define `const keypad_definition_t HWCONF_KEYPAD` in the device definition. [Driver](src/input/keypad.cpp)
* Touch plane. E.g. a faceplate with touch sensitive arrow keys to work in place of a D-pad. Set feature flag `HAS_TOUCH_PLANE` and define `const touch_plane_definition_t HWCONF_TOUCH_PLANE` in the device definition. [Driver](src/input/touch_plane.cpp)

### Others

* Wii Balance Board. Set feature flag `HAS_BALANCE_BOARD_INTEGRATION`. [Driver](src/service/balance_board.cpp), based upon [code by Sasaki Takeru](https://github.com/takeru/Wiimote/tree/d81319c62ac5931da868cc289386a6d4880a4b15), requires WROVER module

## Morio Denki Plasma Display Info

**This display uses high voltage, which could be lethal!!**
Expand Down
Binary file modified helper/chimes/bouken.mid
Binary file not shown.
Binary file modified helper/chimes/caramelldansen.mid
Binary file not shown.
Binary file modified helper/chimes/duvet.mid
Binary file not shown.
Binary file added helper/chimes/eye_opener.mid
Binary file not shown.
Binary file added helper/chimes/gtrhero.mid
Binary file not shown.
Binary file modified helper/chimes/hishoku.mid
Binary file not shown.
Binary file modified helper/chimes/like_the_wind.mid
Binary file not shown.
Binary file added helper/chimes/mermgrl.mid
Binary file not shown.
Binary file added helper/chimes/steiner.mid
Binary file not shown.
Binary file added helper/chimes/syabon.mid
Binary file not shown.
Binary file added helper/chimes/towa.mid
Binary file not shown.
Binary file modified helper/chimes/truth.mid
Binary file not shown.
Binary file modified helper/chimes/when_present_is_past.mid
Binary file not shown.
22 changes: 19 additions & 3 deletions helper/midi_to_chime.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,42 @@

last_time = 0
evts = [] # of (freq in hz or 0, delay in ms)
ended = False

for msg in mid:
if msg.type == "note_on" or msg.type == "note_off":
print(msg)
if msg.time > 0 and len(evts) > 0 and evts[-1][1] == 0:
evts[-1][1] = int(msg.time * 1000)
if msg.type == "note_on" and msg.velocity > 0:
evts.append([int(freq_note_converter.from_note_index(msg.note).freq), 0])
evts.append([int(freq_note_converter.from_note_index(msg.note).freq), 0, ""])
else:
# note off
evts.append([0, 0])
evts.append([0, 0, ""])
elif msg.type == "end_of_track":
print(msg)
if ended:
raise Exception("WTF, already ended")
ended = True
if evts[-1][0] == 0:
# pause exists, just extend it
evts[-1][1] = int(msg.time * 1000)
else:
evts.append([0, int(msg.time*1000), ""])
elif msg.type == "marker":
evts[-1][2] = msg.text


print(evts)

print("static const melody_item_t "+name+"_data[] = {")
i = 0
while i < len(evts) - 1:
while i < len(evts):
if evts[i][0] != 0 or evts[i][1] != 0:
print(" {"+str(evts[i][0])+", "+str(evts[i][1])+"}, ")
if evts[i][2] != "":
print(" ")
print(" // " + evts[i][2])
i+=1
print("};")

Expand Down
1 change: 1 addition & 0 deletions include/app/alarm_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ class AppShimAlarmEditor: public ProtoShimNavMenu {
int current_editing_idx;
alarm_setting_t current_editing_setting;
AlarmEditorView * current_editor;
bool edit_flag;
};
29 changes: 29 additions & 0 deletions include/app/weighing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once
#include <device_config.h>
#include <sensor/sensor.h>
#include <views/framework.h>
#include <views/menu/menu.h>

#if HAS(BALANCE_BOARD_INTEGRATION)
class AppShimWeighing: public Composite {
public:
AppShimWeighing(SensorPool *);
~AppShimWeighing();

void prepare();
void render(FantaManipulator*);
void step();

private:
ViewMultiplexor * carousel;
SensorPool * sensors;
TickType_t lastActivity;
class WeighingView;
enum WeighingAppState {
NEED_CONNECT,
WAIT_CONNECT,
WEIGHING
};
void update_state(transition_type_t);
};
#endif
3 changes: 2 additions & 1 deletion include/device_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
// ---- SOFTWARE FEATURE FLAGS
#define HAS_WORDNIK_API
// #define HAS_OTAFVU
//#define HAS_SWITCHBOT_METER_INTEGRATION // <- low on RAM with the board used in big-clock: wait until they disable HTTPS enforcement, or buy bigger ESP board
// #define HAS_SWITCHBOT_METER_INTEGRATION
#define HAS_BALANCE_BOARD_INTEGRATION

// ---- HARDWARE

Expand Down
17 changes: 12 additions & 5 deletions include/devices/big_clock.h
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
#pragma once

#include <hal/gpio_hal.h>
#include <input/keypad.h>

#define HAS_OUTPUT_MD_PLASMA
#define HAS_VARYING_BRIGHTNESS
#define HAS_LIGHT_SENSOR
#define HAS_TEMP_SENSOR
#define HAS_MOTION_SENSOR
#define HAS_KEYPAD

// Plasma Information System OS (not DOS, there's no disk in it!)
#define PRODUCT_NAME "PIS-OS"
#define PRODUCT_VERSION "2.0"
#define PRODUCT_VERSION "2.1"

// ---- Connection to DISP BOARD ----
const gpio_num_t HWCONF_PLASMA_DATABUS_GPIOS[] = {
GPIO_NUM_15,
GPIO_NUM_2,
GPIO_NUM_0,
GPIO_NUM_4,
GPIO_NUM_16,
GPIO_NUM_17,
GPIO_NUM_32,
GPIO_NUM_33,
GPIO_NUM_5,
GPIO_NUM_18
};
Expand All @@ -46,5 +48,10 @@ const gpio_num_t HWCONF_LIGHTSENSE_GPIO = GPIO_NUM_35;
const gpio_num_t HWCONF_I2C_SDA_GPIO = GPIO_NUM_26;
const gpio_num_t HWCONF_I2C_SCL_GPIO = GPIO_NUM_25;

// ---- TBD: Connection of buttons ----
// Free GPIOS: 36, 39, 34, 27
// ---- Connection of buttons ----
const keypad_definition_t HWCONF_KEYPAD = {
{GPIO_NUM_27, KEY_LEFT},
{GPIO_NUM_39, KEY_RIGHT},
{GPIO_NUM_34, KEY_UP},
{GPIO_NUM_36, KEY_DOWN},
};
4 changes: 2 additions & 2 deletions include/devices/smol_clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

// Plasma Information System OS (not DOS, there's no disk in it!)
#define PRODUCT_NAME "microPIS-OS"
#define PRODUCT_VERSION "2.0"
#define PRODUCT_VERSION "2.1"

// ---- Connection to beeper ----
const gpio_num_t HWCONF_BEEPER_GPIO = GPIO_NUM_12;
Expand Down Expand Up @@ -39,7 +39,7 @@ const gpio_num_t HWCONF_WS0010_EN_GPIO = GPIO_NUM_18;
// ---- Connection to touch plane ----
const touch_plane_definition_t HWCONF_TOUCH_PLANE = {
// Screen panel
{/*GPIO_NUM_32*/ TOUCH_PAD_NUM9, {.key = KEY_RIGHT, .press_threshold = 7, .release_threshold = -3}},
{/*GPIO_NUM_32*/ TOUCH_PAD_NUM9, {.key = KEY_RIGHT, .press_threshold = 10, .release_threshold = -6}},
{/*GPIO_NUM_33*/ TOUCH_PAD_NUM8, {.key = KEY_UP, .press_threshold = 7, .release_threshold = -2}},
{/*GPIO_NUM_27*/ TOUCH_PAD_NUM7, {.key = KEY_DOWN, .press_threshold = 7, .release_threshold = -2}},
{/*GPIO_NUM_14*/ TOUCH_PAD_NUM6, {.key = KEY_LEFT, .press_threshold = 7, .release_threshold = -2}},
Expand Down
1 change: 1 addition & 0 deletions include/graphics/framebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <freertos/event_groups.h>
#include <math.h>

/// @brief A framebuffer for driving the plasma display
class DisplayFramebuffer {
Expand Down
7 changes: 4 additions & 3 deletions include/graphics/sprite.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ typedef uint8_t* fanta_buffer_t;
/// @note Unused pixels are filled with 0's. Transparency et al. should be handled by the drawing code.
extern fanta_buffer_t sprite_to_fanta(const sprite_t*);
extern fanta_buffer_t mask_to_fanta(const sprite_t*);
/// @brief Offset a raw Fanta buffer vertically. Negative is towards the top.
extern void fanta_offset_y(fanta_buffer_t,int,size_t);

/// @brief Initialize a playback context for an animated sprite
extern ani_sprite_state_t ani_sprite_prepare(const ani_sprite*);
/// @brief Get the current animation frame to be drawn for an animated sprite
extern sprite_t ani_sprite_frame(ani_sprite_state_t*);
extern sprite_t ani_sprite_frame(ani_sprite_state_t*);

/// Allocate memory in the fast space, for graphics use specifically
void* gralloc(const size_t);
7 changes: 7 additions & 0 deletions include/input/keypad.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once
#include "keys.h"
#include <vector>
#include "esp32-hal-gpio.h"

typedef std::vector<std::pair<const gpio_num_t, const key_id_t>> keypad_definition_t;
void keypad_start();
5 changes: 5 additions & 0 deletions include/sensor/sensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ typedef enum sensor_id {
/// @brief A sensor using Switchbot Meter broadcasts for humidity measurement
SENSOR_ID_SWITCHBOT_INDOOR_HUMIDITY,

/// @brief A sensor using a Balance Board for weight measurements, 100 units = 1kg
SENSOR_ID_BALANCE_BOARD_MILLIKILOS,
/// @brief A sensor triggering when a significant change of weight was detected on the Balance Board
SENSOR_ID_BALANCE_BOARD_STARTLED,

/// @brief A virtual sensor indicating whether the PMU has been startled (brought out of the low power mode) recently
VIRTSENSOR_ID_PMU_STARTLED,
/// @brief A virtual sensor indicating whether the HID has been startled recently
Expand Down
18 changes: 12 additions & 6 deletions include/service/alarm.h
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
#pragma once
#include "time.h"
#include <stdint.h>
#include <sensor/sensor.h>

#define ALARM_LIST_SIZE 9
#define ALARM_DAY_GLOBAL_ENABLE (1 << 7)
#define ALARM_DAY_OF_WEEK(d) (1 << d)
#define ALARM_DAY_OF_WEEK(d) (1 << (d))

#define ALARM_ON_DAY(a,d) (((a).days & ALARM_DAY_OF_WEEK(d)) != 0)
#define ALARM_IS_ENABLED(x) (((x).days & ALARM_DAY_GLOBAL_ENABLE) != 0)
#define ALARM_ON_DAY(a,d) (((a).days & ALARM_DAY_OF_WEEK((d))) != 0)

typedef struct alarm_setting {
typedef struct __attribute__((__packed__)) alarm_setting {
bool enabled : 1;
/// @brief LSB is Sunday, B1 is Monday, and so on. Disabled altogether when MSB not set..
uint8_t days;
uint8_t days : 7;

int hour;
int minute;
int melody_no;

bool smart : 1;
uint8_t smart_margin_minutes : 7;
} alarm_setting_t;

void alarm_init();
void alarm_init(SensorPool*);

const alarm_setting_t * get_alarm_list();
void set_alarm(uint8_t idx, alarm_setting_t setting);

const alarm_setting_t* get_triggered_alarm();
const alarm_setting_t* get_upcoming_alarm();
void clear_triggered_alarm();
17 changes: 17 additions & 0 deletions include/service/balance_board.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once
#include <sensor/sensor.h>
#include <device_config.h>

#if HAS(BALANCE_BOARD_INTEGRATION)

typedef enum BalanceBoardState {
BB_IDLE,
BB_SCANNING,
BB_CONNECTED
} balance_board_state_t;

void balance_board_start(SensorPool*);
void balance_board_scan(bool);
balance_board_state_t balance_board_state();
void balance_board_zero();
#endif
4 changes: 4 additions & 0 deletions include/service/prefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ static constexpr prefs_key_t PREFS_KEY_SCRN_TIME_REMOTE_WEATHER_SECONDS = "s_rem
static constexpr prefs_key_t PREFS_KEY_SCRN_TIME_OUTDOOR_SECONDS = "s_outside_s";
static constexpr prefs_key_t PREFS_KEY_SCRN_TIME_WORD_OF_THE_DAY_SECONDS = "s_wotd_s";
static constexpr prefs_key_t PREFS_KEY_SCRN_TIME_FOOBAR_SECONDS = "s_foo_s";
static constexpr prefs_key_t PREFS_KEY_SCRN_TIME_NEXT_ALARM_SECONDS = "s_alm_s";

static constexpr prefs_key_t PREFS_KEY_HOURLY_CHIME_ON = "h_chime_on";
static constexpr prefs_key_t PREFS_KEY_HOURLY_CHIME_START_HOUR = "h_chime_start";
Expand All @@ -74,10 +75,13 @@ static constexpr prefs_key_t PREFS_KEY_SWITCHBOT_EMULATES_LOCAL = "wos_emus";

static constexpr prefs_key_t PREFS_KEY_ALARM_LIST = "alarms";
static constexpr prefs_key_t PREFS_KEY_ALARM_SNOOZE_MINUTES = "snz_minutes";
static constexpr prefs_key_t PREFS_KEY_ALARM_MAX_DURATION_MINUTES = "alm_dur";

static constexpr prefs_key_t PREFS_KEY_TIMER_TIME_SECONDS = "timer_time";
static constexpr prefs_key_t PREFS_KEY_TIMER_MELODY = "timer_melo";

static constexpr prefs_key_t PREFS_KEY_BALANCE_BOARD_OFFSET = "bbrd_offs";

void prefs_force_save();

String prefs_get_string(prefs_key_t, String def = String());
Expand Down
9 changes: 9 additions & 0 deletions include/service/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ typedef struct tk_time_of_day {
int millisecond;
} tk_time_of_day_t;

static const tk_time_of_day_t ONE_HOUR = { .hour = 1, .minute = 0, .second = 0, .millisecond = 0 };

typedef struct tk_date {
int year;
int month;
Expand All @@ -32,3 +34,10 @@ tk_date_t get_current_date();
void set_current_time(tk_time_of_day_t);
/// @brief Set the current date without changing the timezone et al
void set_current_date(tk_date_t);

tk_time_of_day operator -(const tk_time_of_day_t& a, const tk_time_of_day_t& b);
bool operator==(const tk_time_of_day_t& a, const tk_time_of_day_t& b);
bool operator<(const tk_time_of_day_t& a, const tk_time_of_day_t& b);
bool operator<=(const tk_time_of_day_t& a, const tk_time_of_day_t& b);
bool operator>(const tk_time_of_day_t& a, const tk_time_of_day_t& b);
bool operator>=(const tk_time_of_day_t& a, const tk_time_of_day_t& b);
6 changes: 4 additions & 2 deletions include/sound/beeper.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@ typedef enum beeper_channels {
CHANNEL_SYSTEM = 7
} beeper_channel_t;

static const uint16_t DUTY_SQUARE = 0x1FF;

class Beeper {
public:
Beeper(gpio_num_t pin, uint8_t ledcChannel);
void set_channel_state(beeper_channel_t, bool);
bool is_channel_enabled(beeper_channel_t);

void start_tone(beeper_channel_t, uint);
void start_tone(beeper_channel_t, uint, uint16_t duty = DUTY_SQUARE);
void stop_tone(beeper_channel_t);

/// @brief Play a tone for a precise amount of milliseconds. Blocks the whole tasks and might block neighboring tasks, so use sparingly.
void beep_blocking(beeper_channel_t, uint freq, uint len);
void beep_blocking(beeper_channel_t, uint freq, uint len, uint16_t duty = DUTY_SQUARE);
private:
uint8_t channel_status;
int active_channel;
Expand Down
Loading

0 comments on commit 600014d

Please sign in to comment.