From 671c91aba7da81e1ae27f67d6e100c8d37a31d1f Mon Sep 17 00:00:00 2001 From: Ricardo Lanziano Date: Wed, 28 Feb 2024 09:05:46 -0500 Subject: [PATCH] Refactor screen usage and API Signed-off-by: Ricardo Lanziano --- src/c3card_screen.erl | 75 ++++++++++++------- src/c3card_screen_codebeam.erl | 9 ++- ...screen_date.erl => c3card_screen_demo.erl} | 10 +-- src/c3card_screen_sysinfo.erl | 23 ++++-- src/c3card_screen_temperature.erl | 22 ------ 5 files changed, 72 insertions(+), 67 deletions(-) rename src/{c3card_screen_date.erl => c3card_screen_demo.erl} (55%) delete mode 100644 src/c3card_screen_temperature.erl diff --git a/src/c3card_screen.erl b/src/c3card_screen.erl index 41b3489..24ce501 100644 --- a/src/c3card_screen.erl +++ b/src/c3card_screen.erl @@ -22,10 +22,10 @@ -export([draw_text/1, draw_text/2, clear/0, - default_screen/0, - available_screens/0, - switch_screen/1, - render_screen/2, + default_screen/0, + available_screens/0, + next_screen/0, + set_screen/1, start_link/1]). -export([init/1, @@ -41,11 +41,10 @@ -define(SCREEN_HEADER, "c3card on ~p~n---------------~n"). -define(AVAILABLE_SCREENS, [{1, c3card_screen_sysinfo}, - {2, c3card_screen_date}, - {3, c3card_screen_temperature}, - {4, c3card_screen_codebeam}]). + {2, c3card_screen_codebeam}, + {3, c3card_screen_demo}]). --callback draw(CardInfo :: map()) -> {ok, Text :: binary()} | {error, Reason :: term()}. +-callback draw() -> {ok, Text :: binary()} | {error, Reason :: term()}. -type screen_option() :: {i2c_bus, i2c_bus:i2c_bus()} @@ -70,27 +69,12 @@ default_screen() -> available_screens() -> ?AVAILABLE_SCREENS. --spec switch_screen(Screen :: screen()) -> screen(). -switch_screen({ScreenIdx, _ScreenMod}) when ScreenIdx >= 1, ScreenIdx =< 4 -> - case lists:keyfind(ScreenIdx + 1, 1, ?AVAILABLE_SCREENS) of - false -> {1, c3card_screen_sysinfo}; - ScreenInfo -> ScreenInfo - end. - -%% @doc Render a Screen providing the current card info. --spec render_screen(Screen :: screen(), CardInfo :: map()) -> ok | {error, Reason :: term()}. -render_screen({_ScreenIdx, ScreenMod}, CardInfo) -> - try - case ScreenMod:draw(CardInfo) of - {ok, Text} -> - draw_text(Text); - {error, _Reason} -> - ok - end - catch _C:E:_S -> - {error, E} - end. +-spec next_screen() -> screen(). +next_screen() -> + gen_server:call(?SERVER, next_screen). +set_screen(Screen) -> + gen_server:cast(?SERVER, {set_screen, Screen}). %% @doc Draw a string on the OLED screen -spec draw_text(Text :: bitstring()) -> ok | {error, Reason :: term()}. @@ -126,7 +110,8 @@ init(Config) -> ssd1306:set_contrast(SSD1306, 255), ?LOG_NOTICE("display started"), ssd1306:set_text(SSD1306, draw_header()), - {ok, #{display => SSD1306}}. + _Timer = timer_manager:send_after(100, self(), redraw), + {ok, #{display => SSD1306, screen => default_screen()}}. %% @private handle_call({draw_text, Text0, FormatOpts}, _From, #{display := SSD1306} = State) -> @@ -134,6 +119,11 @@ handle_call({draw_text, Text0, FormatOpts}, _From, #{display := SSD1306} = State Text = io_lib:format(Text0, FormatOpts), %%ssd1306:clear(SSD1306), {reply, ssd1306:set_text(SSD1306, erlang:iolist_to_binary([Header, Text])), State}; +handle_call(next_screen, _From, #{screen := CurrentScreen, display := SSD1306} = State) -> + ssd1306:clear(SSD1306), + NextScreen = switch_screen(CurrentScreen), + render_screen(SSD1306, NextScreen), + {reply, NextScreen, State#{screen => NextScreen}}; handle_call(clear, _From, #{display := SSD1306} = State) -> Header = draw_header(), ssd1306:clear(SSD1306), @@ -142,10 +132,18 @@ handle_call(_Msg, _From, State) -> {reply, ok, State}. %% @private +handle_cast({set_screen, Screen}, #{display := SSD1306} = State) -> + ssd1306:clear(SSD1306), + render_screen(SSD1306, Screen), + {reply, ok, State#{screen => Screen}}; handle_cast(_Msg, State) -> {noreply, State}. %% @private +handle_info(redraw, #{screen := Screen, display := SSD1306} = State) -> + render_screen(SSD1306, Screen), + _Timer = timer_manager:send_after(100, self(), redraw), + {noreply, State}; handle_info(_Msg, State) -> {noreply, State}. @@ -154,3 +152,22 @@ handle_info(_Msg, State) -> %% @hidden draw_header() -> io_lib:format(?SCREEN_HEADER, [atomvm:platform()]). + +%% @hidden +render_screen(Display, {_ScreenIdx, ScreenMod}) -> + case ScreenMod:draw() of + {ok, Text0} -> + Header = draw_header(), + Text = io_lib:format(Text0, []), + ssd1306:set_text(Display, erlang:iolist_to_binary([Header, Text])); + {error, Reason} = Err -> + ?LOG_ERROR("failed to draw: ~p", [Reason]), + Err + end. + +%% @hidden +switch_screen({ScreenIdx, _ScreenMod}) -> + case lists:keyfind(ScreenIdx + 1, 1, ?AVAILABLE_SCREENS) of + false -> default_screen(); + ScreenInfo -> ScreenInfo + end. diff --git a/src/c3card_screen_codebeam.erl b/src/c3card_screen_codebeam.erl index 0167f3f..d005f45 100644 --- a/src/c3card_screen_codebeam.erl +++ b/src/c3card_screen_codebeam.erl @@ -7,9 +7,12 @@ -behaviour(c3card_screen). --export([draw/1]). +-export([draw/0]). %% Callbacks -draw(_CardInfo) -> - {ok, "Hello codebeam"}. +draw() -> + CurrentTurn = c3card_codebeam:candy_turn(), + CandyInfo = io_lib:format("Get your candy!~n~nturn: ~p", + [CurrentTurn]), + {ok, CandyInfo}. diff --git a/src/c3card_screen_date.erl b/src/c3card_screen_demo.erl similarity index 55% rename from src/c3card_screen_date.erl rename to src/c3card_screen_demo.erl index 7595bf3..303cfea 100644 --- a/src/c3card_screen_date.erl +++ b/src/c3card_screen_demo.erl @@ -1,15 +1,15 @@ %%%------------------------------------------------------------------- -%% @doc `c3card_screen_date' screen info. +%% @doc `c3card_screen_demo' screen info. %% @end %%%------------------------------------------------------------------- --module(c3card_screen_date). +-module(c3card_screen_demo). -behaviour(c3card_screen). --export([draw/1]). +-export([draw/0]). %% Callbacks -draw(_CardInfo) -> - {ok, "Hello date"}. +draw() -> + {ok, io_lib:format("~n~n~nHello CodeBEAM!~n", [])}. diff --git a/src/c3card_screen_sysinfo.erl b/src/c3card_screen_sysinfo.erl index 375e6d9..d024f2a 100644 --- a/src/c3card_screen_sysinfo.erl +++ b/src/c3card_screen_sysinfo.erl @@ -7,16 +7,23 @@ -behaviour(c3card_screen). --export([draw/1]). +-export([draw/0]). %% Callbacks -draw(CardInfo) -> +draw() -> + {ok, #{aht20 := [ + #{data := Hum, type := humidity}, + #{data := RelHum, type := relative_humidity}, + #{data := Temp, type := temperature} + ]}} = c3card_sensor:read_sensors(), + #{process_count := ProcessCount} = c3card_system:info(), {{Year, Month, Day}, _} = erlang:universaltime(), - #{system_info := #{atom_count := AtomCount, - process_count := ProcessCount, - system_architecture := SystemArch}} = CardInfo, - SysInfo = io_lib:format("~p~n~natoms: ~p~nprocesses: ~p~n~ndate: ~p/~p/~p~n", - [SystemArch, AtomCount, ProcessCount, - Year, Month, Day]), + CurrentTurn = c3card_codebeam:candy_turn(), + SysInfo = + io_lib:format( + "AHT10:~n ~pC, ~p%, ~pRH~nprocesses: ~p~nturn: ~p~ndate: ~p/~p/~p", + [trunc(Temp), trunc(Hum), trunc(RelHum), + ProcessCount, CurrentTurn, Year, Month, Day] + ), {ok, SysInfo}. diff --git a/src/c3card_screen_temperature.erl b/src/c3card_screen_temperature.erl deleted file mode 100644 index 8c7e967..0000000 --- a/src/c3card_screen_temperature.erl +++ /dev/null @@ -1,22 +0,0 @@ -%%%------------------------------------------------------------------- -%% @doc `c3card_screen_temperature' screen info. -%% @end -%%%------------------------------------------------------------------- - --module(c3card_screen_temperature). - --behaviour(c3card_screen). - --export([draw/1]). - -%% Callbacks - -draw(CardInfo) -> - #{readings := #{aht20 := Readings}} = CardInfo, - [#{data := Hum, type := humidity}, - #{data := RelHum, type := relative_humidity}, - #{data := Temp, type := temperature} - ] = Readings, - SensorInfo = io_lib:format("AHT10:~n~pC, ~p%, ~pRH", - [trunc(Temp), trunc(Hum), trunc(RelHum)]), - {ok, SensorInfo}.