Skip to content

Commit

Permalink
Setup handlers for brightness and speed
Browse files Browse the repository at this point in the history
  • Loading branch information
arosspope committed Oct 28, 2023
1 parent a759c9f commit a83b8ae
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 76 deletions.
1 change: 1 addition & 0 deletions sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=7000
# Workaround for https://github.com/espressif/esp-idf/issues/7631
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n
CONFIG_LWIP_LOCAL_HOSTNAME=ticker-tape-rs
68 changes: 39 additions & 29 deletions src/display.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
use anyhow::{bail, Error, Result};
use esp_idf_hal::gpio::{Gpio0, Gpio1, Gpio2, Output, PinDriver};
use font8x8::{UnicodeFonts, BASIC_FONTS};
use log::*;
use anyhow::{Result, Error, bail};
use esp_idf_hal::gpio::{
PinDriver,
Gpio0, Gpio1, Gpio2,
Output
};
use font8x8::{BASIC_FONTS, UnicodeFonts};
use max7219::{connectors::*, *};

pub type DisplayPins<'a> =
PinConnector<PinDriver<'a, Gpio0, Output>, PinDriver<'a, Gpio1, Output>, PinDriver<'a, Gpio2, Output>>;
pub type DisplayPins<'a> = PinConnector<
PinDriver<'a, Gpio0, Output>,
PinDriver<'a, Gpio1, Output>,
PinDriver<'a, Gpio2, Output>,
>;

pub struct DotDisplay<'a> {
display: MAX7219<DisplayPins<'a>>,
display_is_on: bool,
brightness: u8,
}

impl DotDisplay<'_> {
pub fn from(display: MAX7219<DisplayPins>) -> Result<DotDisplay<'_>, DataError> {
let mut controller = DotDisplay {
display,
display_is_on: true,
brightness: 0,
};

// Start the DotDisplay in a known state
Expand Down Expand Up @@ -83,6 +84,7 @@ impl DotDisplay<'_> {

let brightness = (brightness as f32 * 2.55) as u8;
self.display.set_intensity(0, brightness)?;
self.brightness = brightness;
Ok(())
}
}
Expand All @@ -101,8 +103,8 @@ impl Ticker<'_> {
shift: 0,
index: 0,
len: 0,
message: [0; 100],
display: display,
message: [0; 100],
display: display,
}
}

Expand All @@ -111,7 +113,7 @@ impl Ticker<'_> {
if message.len() > self.message.len() {
bail!("Message too long");
}

self.len = message.len();
self.message[..self.len].copy_from_slice(message.as_bytes().try_into()?);
Ok(())
Expand All @@ -123,18 +125,17 @@ impl Ticker<'_> {
let mut glyph = BASIC_FONTS.get(c).unwrap_or(unknown);

glyph.iter_mut().for_each(|x| {
*x = x.reverse_bits();
let mut y = *x as isize;

if shift < 0 {
y >>= shift.abs();
} else {
y <<= shift;
}

*x = y as u8;
*x = x.reverse_bits();
let mut y = *x as isize;

if shift < 0 {
y >>= shift.abs();
} else {
y <<= shift;
}
);

*x = y as u8;
});

glyph
}
Expand All @@ -145,17 +146,26 @@ impl Ticker<'_> {
self.index = (self.index + 1) % self.len;
}

let previous = if self.index > 0 {self.message[self.index - 1] as char} else {0 as char};
let previous = if self.index > 0 {
self.message[self.index - 1] as char
} else {
0 as char
};
let next = self.message[self.index] as char;

let mut previous_glyph = Ticker::glyph(previous, self.shift);
let next_glyph = Ticker::glyph(next, self.shift - 8);

// OR two glyphs together
previous_glyph.iter_mut().enumerate().for_each(|(index, el)| *el |= next_glyph[index]);
previous_glyph
.iter_mut()
.enumerate()
.for_each(|(index, el)| *el |= next_glyph[index]);

// Write to the display
self.display.write_display(&previous_glyph).expect("Failed to write dot-matrix");
self.display
.write_display(&previous_glyph)
.expect("Failed to write dot-matrix");
self.shift += 1;
}
}
}
7 changes: 4 additions & 3 deletions src/led.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use anyhow::Result; // TODO: why use anyhow?
use core::time::Duration;
use esp_idf_hal::{
gpio::OutputPin,
rmt::{config::TransmitConfig, FixedLengthSignal, PinState, Pulse, TxRmtDriver, RmtChannel}, peripheral::Peripheral,
peripheral::Peripheral,
rmt::{config::TransmitConfig, FixedLengthSignal, PinState, Pulse, RmtChannel, TxRmtDriver},
};

pub use rgb::RGB8; // TODO: Find a better way to expose this
Expand All @@ -15,8 +16,8 @@ impl<'d> WS2812RMT<'d> {
// Rust ESP Board gpio2, ESP32-C3-DevKitC-02 gpio8 TODO: This is the wrong LED / KIT reference code!!!
pub fn new(
led: impl Peripheral<P = impl OutputPin> + 'd,
channel: impl Peripheral<P = impl RmtChannel> + 'd,
)-> Result<Self> {
channel: impl Peripheral<P = impl RmtChannel> + 'd,
) -> Result<Self> {
let config = TransmitConfig::new().clock_divider(2);
let tx = TxRmtDriver::new(channel, led, &config)?;
Ok(Self { tx_rtm_driver: tx })
Expand Down
106 changes: 75 additions & 31 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use std::{str, sync::{Arc, Mutex}};
use esp_idf_hal::{
prelude::Peripherals,
gpio::PinDriver
use embedded_svc::{
http::{Headers, Method},
io::{Read, Write},
};
use embedded_svc::{http::{Method, Headers}, io::{Write, Read}};
use esp_idf_hal::{gpio::PinDriver, prelude::Peripherals};
use esp_idf_svc::http::server::{Configuration, EspHttpServer};
use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use log::*;
use max7219::*;
use serde::Serialize;
use std::{
str,
sync::{Arc, Mutex},
};

mod led;
use led::{RGB8, WS2812RMT};
Expand All @@ -27,7 +30,6 @@ pub struct Config {
wifi_psk: &'static str,
}


fn main() -> anyhow::Result<()> {
// It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
Expand All @@ -39,53 +41,72 @@ fn main() -> anyhow::Result<()> {
// The constant CONFIG is auto-generated by toml_config
let app_config = CONFIG;
let mut led = WS2812RMT::new(peripherals.pins.gpio18, peripherals.rmt.channel0)?;
led.set_pixel(RGB8::new(50, 50, 0))?;

led.set_pixel(RGB8::new(50, 50, 0))?; // TODO...

// Associate to network and obtain DHCP IP
info!("Loading with credentials, ssid:{:?} psk:{:?}", app_config.wifi_ssid, app_config.wifi_psk);
let mut wifi = Wifi::init(peripherals.modem, &app_config.wifi_ssid, &app_config.wifi_psk);
info!(
"Loading with credentials, ssid:{:?} psk:{:?}",
app_config.wifi_ssid, app_config.wifi_psk
);
let mut wifi = Wifi::init(
peripherals.modem,
&app_config.wifi_ssid,
&app_config.wifi_psk,
);
Wifi::start(&mut wifi)?;


// Setup for the MAX7219 display
// Setup for the Ticker display
let data = PinDriver::output(peripherals.pins.gpio0).unwrap();
let cs = PinDriver::output(peripherals.pins.gpio1).unwrap();
let sck = PinDriver::output(peripherals.pins.gpio2).unwrap();
let ticker_main = Arc::new(Mutex::new(Ticker::new(
DotDisplay::from(MAX7219::from_pins(1, data, cs, sck).unwrap()).unwrap(),
)));
let ticker = ticker_main.clone();
ticker.lock().unwrap().set_message("Hello world")?;
ticker.lock().unwrap().display.set_brightness(80).expect("Failed to set brightness");
let ticker_message_handler = ticker_main.clone();
let ticker_brightness_handler = ticker_main.clone();
ticker_main.lock().unwrap().set_message("Hello world")?;
ticker_main
.lock()
.unwrap()
.display
.set_brightness(80)
.expect("Failed to set brightness");

let tick_speed_ms = Arc::new(Mutex::new(70 as u64));
let tick_speed_handler = tick_speed_ms.clone();

// Set the HTTP server
let mut server = EspHttpServer::new(&Configuration::default())?;

// http://<sta ip>/ handler
server.fn_handler("/", Method::Get, |request| {
#[derive(Serialize)]
struct TickerConfig {
message: String,
speed: u16,
brightness: u8
brightness: u8,
}

let config = TickerConfig{speed: 0, message: String::default(), brightness: 0};
let config = TickerConfig {
speed: 0,
message: String::default(),
brightness: 0,
};
let mut response = request.into_ok_response()?;
response.write_all(serde_json::to_string(&config)?.as_bytes())?;
Ok(())
})?;

// Speed
server.fn_handler("/speed", Method::Put, |mut req| {
server.fn_handler("/speed", Method::Put, move |mut req| {
let len = req.content_len().unwrap_or(0) as usize;
let mut buf = vec![0; len];
req.read_exact(&mut buf)?;

if let Ok(as_str) = str::from_utf8(&buf) {
if let Ok(speed) = as_str.parse::<u16>() {
if let Ok(speed) = as_str.parse::<u64>() {
if speed <= 1000 {
// TODO....
info!("Set scroll speed to {:?}ms", speed);
*tick_speed_handler.lock().unwrap() = speed;
req.into_ok_response()?;
return Ok(());
}
Expand All @@ -96,8 +117,29 @@ fn main() -> anyhow::Result<()> {
})?;

// Brightness
server.fn_handler("/speed", Method::Put, |mut req| {
// TODO
server.fn_handler("/brightness", Method::Put, move |mut req| {
let len = req.content_len().unwrap_or(0) as usize;
let mut buf = vec![0; len];
req.read_exact(&mut buf)?;

if let Ok(as_str) = str::from_utf8(&buf) {
if let Ok(brightness) = as_str.parse::<u8>() {
match ticker_brightness_handler
.lock()
.unwrap()
.display
.set_brightness(brightness)
{
Ok(_) => {
info!("Set brightness to {:?}%", brightness);
req.into_ok_response()?;
return Ok(());
}
_ => (), // Fall through
}
}
}

Err(().into())
})?;

Expand All @@ -106,19 +148,19 @@ fn main() -> anyhow::Result<()> {
let len = req.content_len().unwrap_or(0) as usize;
let mut buf = vec![0; len];
req.read_exact(&mut buf)?;

if let core::result::Result::Ok(as_str) = str::from_utf8(&buf) {
// info!("Setting to {:?}", as_str);
ticker.lock().unwrap().set_message(as_str)?;
ticker_message_handler.lock().unwrap().set_message(as_str)?;
debug!("Setting ticker message to: {:?}", as_str);
req.into_ok_response()?;
return Ok(());
}

Err(().into())
})?;

let mut seed = 0;
loop {
loop {
ticker_main.lock().unwrap().tick();

seed += 1;
Expand All @@ -129,6 +171,8 @@ fn main() -> anyhow::Result<()> {
led.set_pixel(RGB8::new(0, 50, 0))?; // Green
}

std::thread::sleep(std::time::Duration::from_millis(70));
std::thread::sleep(std::time::Duration::from_millis(
*tick_speed_ms.lock().unwrap(),
));
}
}
30 changes: 17 additions & 13 deletions src/wifi.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use log::*;
use anyhow::{Result, Error};
use anyhow::{Error, Result};
use embedded_svc::wifi::{AuthMethod, ClientConfiguration, Configuration};
use esp_idf_hal::modem::Modem;
use esp_idf_svc::{eventloop::EspSystemEventLoop, nvs::EspDefaultNvsPartition, wifi::{EspWifi, BlockingWifi}};
use esp_idf_svc::{
eventloop::EspSystemEventLoop,
nvs::EspDefaultNvsPartition,
wifi::{BlockingWifi, EspWifi},
};
use log::*;

pub struct Wifi {
pub driver: BlockingWifi<EspWifi<'static>>,
Expand All @@ -11,18 +15,18 @@ pub struct Wifi {
impl Wifi {
pub fn init(modem: Modem, ssid: &'static str, psk: &'static str) -> Self {
let sysloop = EspSystemEventLoop::take().expect("Failed to take system event loop");
let esp_wifi = EspWifi::new(modem,
let esp_wifi = EspWifi::new(
modem,
sysloop.clone(),
Some(EspDefaultNvsPartition::take().expect("Failed to take default nvs partition")), // ? Necessary?
).expect("Failed to create esp wifi device");

let mut driver = BlockingWifi::wrap(
esp_wifi,
sysloop.clone()
).expect("Failed to intialise BlockingWifi object");
)
.expect("Failed to create esp wifi device");

let mut driver = BlockingWifi::wrap(esp_wifi, sysloop.clone())
.expect("Failed to intialise BlockingWifi object");

driver.wifi_mut()
driver
.wifi_mut()
.set_configuration(&Configuration::Client(ClientConfiguration {
ssid: ssid.into(),
password: psk.into(),
Expand All @@ -41,7 +45,7 @@ impl Wifi {

let ip = self.driver.wifi().sta_netif().get_ip_info()?;
info!("IP info: {:?}", ip);

Ok(())
}
}
}

0 comments on commit a83b8ae

Please sign in to comment.