#![no_std]
#![no_main]
extern crate alloc;
use core::{mem::MaybeUninit, panic};
use hal::{psram, prelude::*, peripherals::Peripherals, spi, timer::TimerGroup, clock::{ClockControl, CpuClock}, Delay, Rtc, Rng, IO};
use embedded_io::blocking::*;
use embedded_svc::ipv4::Interface;
use embedded_svc::wifi::{AccessPointInfo, ClientConfiguration, Configuration, Wifi};
use esp_backtrace as _;
use esp_println::{print, println};
use esp_wifi::wifi::utils::create_network_interface;
use esp_wifi::wifi::{WifiError, WifiMode};
use esp_wifi::wifi_interface::WifiStack;
use esp_wifi::{current_millis, initialize, EspWifiInitFor};
use smoltcp::iface::SocketStorage;
use smoltcp::wire::IpAddress;
use smoltcp::wire::Ipv4Address;
use embedded_hal::blocking::delay::DelayMs;
use embedded_graphics::{
fonts::{Font24x32, Text},
prelude::*,
style::PrimitiveStyle,
text_style,
};
use ssd1680::prelude::*;
use ssd1680::color::{Black, White};
const SSID: &str = "Wokwi-GUEST";
const PASSWORD: &str = "";
#[global_allocator]
static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();
fn init_heap() {
const HEAP_SIZE: usize = 32 * 1024;
static mut HEAP: MaybeUninit<[u8; HEAP_SIZE]> = MaybeUninit::uninit();
unsafe {
ALLOCATOR.init(HEAP.as_mut_ptr() as *mut u8, HEAP_SIZE);
}
}
fn draw_text(display: &mut Display2in13, text: &str, x: i32, y: i32) {
let _ = Text::new(text, Point::new(x, y))
.into_styled(text_style!(
font = Font24x32,
text_color = Black,
background_color = White
))
.draw(display);
}
const fn buffer_len(width: usize, height: usize) -> usize {
(width + 7) / 8 * height
}
#[entry]
fn main() -> ! {
init_heap();
let peripherals = Peripherals::take();
let mut system = peripherals.DPORT.split();
let clocks = ClockControl::max(system.clock_control).freeze();
let timer = hal::timer::TimerGroup::new(
peripherals.TIMG1,
&clocks,
&mut system.peripheral_clock_control,
)
.timer0;
let init = initialize(
EspWifiInitFor::Wifi,
timer,
Rng::new(peripherals.RNG),
system.radio_clock_control,
&clocks,
)
.unwrap();
// Create an SPI interface and pins
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let mut delay = Delay::new(&clocks);
let busy = io.pins.gpio4.into_floating_input();
let rst = io.pins.gpio16.into_push_pull_output();
let mosi = io.pins.gpio23.into_push_pull_output();
// let miso = io.pins.gpio19.into_floating_input();
let sclk = io.pins.gpio18.into_push_pull_output();
let dc = io.pins.gpio17.into_push_pull_output();
let cs = io.pins.gpio5.into_push_pull_output();
delay.delay_ms(10u32);
let mut spi = spi::Spi::new_no_cs_no_miso(
peripherals.SPI3,
sclk,
mosi,
40u32.MHz(),
spi::SpiMode::Mode0,
&mut system.peripheral_clock_control,
&clocks,
);
let mut ssd1680 = Ssd1680::new(&mut spi, cs, busy, dc, rst, &mut delay).unwrap();
// Initialize ePaper display
ssd1680.clear_bw_frame(&mut spi).unwrap();
// // Allocate a buffer
// let buf_ptr = unsafe { alloc(layout) };
// let buf_array: &mut [u8; 4050] = unsafe {
// &mut *(buf_ptr as *mut [u8; 4050])
// };
// let mut nothing_array = alloc::vec![0u8; 500];
// println!("{:?}",nothing_array[0]);
let mut buf_array = alloc::vec![0u8; 4000];
// let first_element_ptr = &buf_array[0] as *const u8;
// println!("Memory address of first element: {:?}", first_element_ptr);
// loop that sets first 1000 bytes of buf_array to 255
for i in 0..4000 {
buf_array[i] = 255;
}
// print buf size for width 122 and height 250
// println!("buf size: {}", buffer_len(122, 250));
// // print size of buf_array
// println!("buf_array size: {}", buf_array.len());
// println!("buf_array: {:?}", buf_array);
println!("Creating display_bw");
// let mut display_bw = match buf_array.try_into() {
// Ok(buffer) => {
// println!("Buffer converted");
// let display = Display2in13::bw_with_buffer(buffer);
// println!("Display created");
// display
// }
// ,
// Err(e) => {
// // Log the error and handle it as appropriate for your application.
// println!("Error converting buf_array: {:?}", e);
// // Returning or handling the error further as needed
// panic!("Error converting buf_array: {:?}", e);
// }
// };
let mut display_bw = Display2in13::bw_with_buffer(buf_array.try_into().unwrap());
// let mut display_bw = Display2in13::bw();
println!("Drawing text");
// draw_text(&mut display_bw, "...", 0, 10); // Assuming draw_text function is defined
// match ssd1680.update_bw_frame(&mut spi, display_bw.buffer()) {
// Ok(_) => println!("Update frame success"),
// Err(e) => println!("Update frame error {:?}", e),
// }
// match ssd1680.display_frame(&mut spi, &mut delay) {
// Ok(_) => println!("Display frame success"),
// Err(e) => println!("Display frame error {:?}", e),
// }
println!("Initializing");
// Initialize WiFi
let (wifi, ..) = peripherals.RADIO.split();
println!("Allocating sockets");
let mut socket_set_entries: [SocketStorage; 5] = Default::default();
println!("Acquiring WiFi interface");
let (iface, device, mut controller, sockets) =
match create_network_interface(&init, wifi, WifiMode::Sta, &mut socket_set_entries)
{
Ok(val) => val,
Err(_) => {
let err_msg = "Network init failed";
// draw_text(&mut display_bw, err_msg, 0, 0); // Assuming draw_text function is defined
// ssd1680.update_bw_frame(&mut spi, display_bw.buffer()).unwrap();
// ssd1680.display_frame(&mut spi, &mut delay).unwrap();
// Log the error message to serial console or another debugging interface
print!("{}", err_msg);
loop {}
}
};
println!("Creating WifiStack");
let wifi_stack = WifiStack::new(iface, device, sockets, current_millis);
println!("Creating ClientConfiguration");
let client_config = Configuration::Client(ClientConfiguration {
ssid: SSID.into(),
password: PASSWORD.into(),
..Default::default()
});
println!("Setting configuration");
controller.set_configuration(&client_config).unwrap();
println!("Starting WiFi controller");
// println!("buf_array: {:?}", display_bw.buffer());
match controller.start() {
Ok(_) => println!("WiFi controller started"),
Err(e) => println!("WiFi controller error {:?}", e),
}
// println!("is wifi started: {:?}", controller.is_started());
// println!("Creating display_bw");
// let mut display_bw = match buf_array.try_into() {
// Ok(buffer) => {
// println!("Buffer converted");
// let display = Display2in13::bw_with_buffer(buffer);
// println!("Display created");
// display
// }
// ,
// Err(e) => {
// // Log the error and handle it as appropriate for your application.
// println!("Error converting buf_array: {:?}", e);
// // Returning or handling the error further as needed
// panic!("Error converting buf_array: {:?}", e);
// }
// };
// let mut display_bw = Display2in13::bw_with_buffer(buf_array.try_into().unwrap());
println!("Start Wifi Scan");
let res: Result<(heapless::Vec<AccessPointInfo, 10>, usize), WifiError> = controller.scan_n();
if let Ok((res, _count)) = res {
for ap in res {
println!("{:?}", ap);
}
}
println!("{:?}", controller.get_capabilities());
println!("wifi_connect {:?}", controller.connect());
// wait to get connected
println!("Wait to get connected");
loop {
let res = controller.is_connected();
match res {
Ok(connected) => {
if connected {
break;
}
}
Err(err) => {
println!("WiFi Error - {:?} - delay 1000 ms", err);
delay.delay_ms(1000u32);
controller.connect().unwrap();
}
}
}
println!("Is connected: {:?}", controller.is_connected());
// wait for getting an ip address
println!("Wait to get an ip address");
loop {
wifi_stack.work();
if wifi_stack.is_iface_up() {
println!("got ip {:?}", wifi_stack.get_ip_info());
delay.delay_ms(500u32);
break;
}
}
println!("Start busy loop on main");
let mut rx_buffer = [0u8; 1536];
let mut tx_buffer = [0u8; 1536];
let mut buffer = [0u8; 512];
let mut socket = wifi_stack.get_socket(&mut rx_buffer, &mut tx_buffer);
loop {
println!("Making HTTP request");
socket.work();
println!("Opening socket");
match socket.open(IpAddress::Ipv4(Ipv4Address::new(93, 99, 115, 9)), 80) {
Ok(_) => {
// Successfully opened the socket
// Continue with the next steps
},
Err(e) => {
println!("error{:?}", e);
loop{};
}
}
println!("Sendig GET request");
socket
.write(b"GET /info.txt HTTP/1.0\r\nHost: iot.georgik.rocks\r\n\r\n")
.unwrap();
socket.flush().unwrap();
let wait_end = current_millis() + 20 * 1000;
// A fixed-size buffer to hold the HTTP response.
let mut full_response = [0u8; 2048];
let mut full_len = 0;
println!("Reading response");
// Read the HTTP response into the buffer.
loop {
if let Ok(len) = socket.read(&mut buffer) {
// Copy the newly read bytes into `full_response`.
full_response[full_len..full_len + len].copy_from_slice(&buffer[0..len]);
full_len += len;
println!("Read {} bytes", len);
} else {
println!("Read error");
break;
}
if current_millis() > wait_end {
println!("Timeout");
break;
}
}
// Search for the double CRLF sequence to find the start of the HTTP body.
let mut body_start = 0;
for i in 0..(full_len - 3) {
if &full_response[i..i + 4] == b"\r\n\r\n" {
body_start = i + 4;
break;
}
}
if body_start != 0 {
let body = &full_response[body_start..full_len];
let to_print = unsafe { core::str::from_utf8_unchecked(body) };
draw_text(&mut display_bw, &to_print, 0, 10); // Assuming draw_text function is defined
print!("{}", to_print);
}
println!("Closing socket");
socket.disconnect();
println!("Updating frame");
ssd1680.update_bw_frame(&mut spi, display_bw.buffer()).unwrap();
println!("Updating display");
ssd1680.display_frame(&mut spi, &mut delay).unwrap();
println!("Sleeping");
// Delay before repeating
delay.delay_ms(10000u32);
println!("Waking up");
}
}