Compare commits
2 Commits
main
...
pico-light
Author | SHA1 | Date | |
---|---|---|---|
ca0bc90e85 | |||
f951518b57 |
pico-st7789/src
@ -8,6 +8,8 @@
|
||||
// e c
|
||||
// d d d
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::font::{Font, Glyph};
|
||||
|
||||
pub struct RGB {
|
||||
@ -18,10 +20,15 @@ pub struct RGB {
|
||||
|
||||
pub trait Canvas {
|
||||
fn set_pixel(&mut self, x: usize, y: usize, color: &RGB);
|
||||
fn buf(&self) -> &[u8];
|
||||
fn partial(&self, x1: usize, y1: usize, x2: usize, y2: usize) -> impl Iterator<Item = &[u8]>;
|
||||
fn clean(&mut self);
|
||||
fn dirty(&self) -> Option<(usize, usize, usize, usize)>;
|
||||
fn width(&self) -> usize;
|
||||
|
||||
fn fill(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: &RGB) {
|
||||
for x in x1..x2 + 1 {
|
||||
for y in y1..y2 + 1 {
|
||||
for x in x1..x2 {
|
||||
for y in y1..y2 {
|
||||
self.set_pixel(x, y, color);
|
||||
}
|
||||
}
|
||||
|
42
pico-st7789/src/light_sensor.rs
Normal file
42
pico-st7789/src/light_sensor.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use embedded_hal::i2c::{I2c, Error};
|
||||
|
||||
const ADDR: u8 = 0x39;
|
||||
|
||||
pub struct LightSensor<I2C> {
|
||||
i2c: I2C
|
||||
}
|
||||
|
||||
impl <I2C: I2c> LightSensor<I2C> {
|
||||
pub fn new(i2c: I2C) -> Self {
|
||||
Self { i2c }
|
||||
}
|
||||
|
||||
pub fn control(&mut self) -> Result<u8, I2C::Error> {
|
||||
let mut ctrl = [0];
|
||||
self.i2c.write_read(ADDR, &[0x80], &mut ctrl)?;
|
||||
Ok(ctrl[0])
|
||||
}
|
||||
|
||||
pub fn power_up(&mut self) -> Result<(), I2C::Error> {
|
||||
self.i2c.write(ADDR, &[0x80, 0x03])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_full_spectrum(&mut self) -> Result<u16, I2C::Error> {
|
||||
let mut light_parts = [0, 0];
|
||||
self.i2c.write_read(ADDR, &[0xAC], &mut light_parts)?;
|
||||
let ll: u16 = light_parts[0].into();
|
||||
let lh: u16 = light_parts[1].into();
|
||||
let light: u16 = 256 * lh + ll;
|
||||
Ok(light)
|
||||
}
|
||||
|
||||
pub fn read_ir(&mut self) -> Result<u16, I2C::Error> {
|
||||
let mut light_parts = [0, 0];
|
||||
self.i2c.write_read(ADDR, &[0xAE], &mut light_parts)?;
|
||||
let ll: u16 = light_parts[0].into();
|
||||
let lh: u16 = light_parts[1].into();
|
||||
let light: u16 = 256 * lh + ll;
|
||||
Ok(light)
|
||||
}
|
||||
}
|
@ -3,23 +3,38 @@
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::fmt::format;
|
||||
use alloc::{
|
||||
fmt::format,
|
||||
vec::{self, Vec},
|
||||
};
|
||||
use embedded_alloc::LlffHeap as Heap;
|
||||
use embedded_hal::{delay::DelayNs, digital::OutputPin};
|
||||
use fugit::RateExtU32;
|
||||
use light_sensor::LightSensor;
|
||||
use panic_halt as _;
|
||||
use rp_pico::{
|
||||
entry,
|
||||
hal::{clocks::init_clocks_and_plls, spi::Spi, Clock, Sio, Timer, Watchdog},
|
||||
hal::{
|
||||
clocks::init_clocks_and_plls,
|
||||
gpio::{
|
||||
bank0::{Gpio20, Gpio21},
|
||||
FunctionI2C, Pin, PullUp,
|
||||
},
|
||||
i2c::I2C,
|
||||
spi::Spi,
|
||||
Clock, Sio, Timer, Watchdog,
|
||||
},
|
||||
pac, Pins,
|
||||
};
|
||||
|
||||
mod canvas;
|
||||
use canvas::{Canvas, RGB, print};
|
||||
use canvas::{print, Canvas, RGB};
|
||||
|
||||
mod font;
|
||||
use font::{BitmapFont, Font, Glyph, SevenSegmentFont, SixteenSegmentFont};
|
||||
|
||||
mod light_sensor;
|
||||
|
||||
mod st7789;
|
||||
use st7789::{ST7789Display, SETUP_PROGRAM};
|
||||
|
||||
@ -36,6 +51,7 @@ static mut BUF: [u8; 163200] = [0; 163200];
|
||||
|
||||
pub struct FrameBuf {
|
||||
pub buf: &'static mut [u8; 163200],
|
||||
pub dirty: Option<(usize, usize, usize, usize)>,
|
||||
pub width: usize,
|
||||
}
|
||||
|
||||
@ -43,6 +59,7 @@ impl FrameBuf {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
buf: unsafe { &mut BUF },
|
||||
dirty: None,
|
||||
width: 170,
|
||||
}
|
||||
}
|
||||
@ -50,9 +67,51 @@ impl FrameBuf {
|
||||
|
||||
impl Canvas for FrameBuf {
|
||||
fn set_pixel(&mut self, x: usize, y: usize, color: &RGB) {
|
||||
self.buf[(y * self.width + x) * 3 + 0] = color.r << 2;
|
||||
self.buf[(y * self.width + x) * 3 + 1] = color.g << 2;
|
||||
self.buf[(y * self.width + x) * 3 + 2] = color.b << 2;
|
||||
let addr = y * self.width + x;
|
||||
self.buf[addr * 3 + 0] = color.r << 2;
|
||||
self.buf[addr * 3 + 1] = color.g << 2;
|
||||
self.buf[addr * 3 + 2] = color.b << 2;
|
||||
|
||||
if let Some((ref mut x1, ref mut y1, ref mut x2, ref mut y2)) = self.dirty {
|
||||
if x < *x1 {
|
||||
*x1 = x
|
||||
}
|
||||
if y < *y1 {
|
||||
*y1 = y
|
||||
}
|
||||
if x > *x2 {
|
||||
*x2 = x
|
||||
}
|
||||
if y > *y2 {
|
||||
*y2 = y
|
||||
}
|
||||
} else {
|
||||
self.dirty = Some((x, y, x, y));
|
||||
}
|
||||
}
|
||||
|
||||
fn buf(&self) -> &[u8] {
|
||||
self.buf
|
||||
}
|
||||
|
||||
fn partial(&self, x1: usize, y1: usize, x2: usize, y2: usize) -> impl Iterator<Item = &[u8]> {
|
||||
(y1..y2 + 1).map(move |y| {
|
||||
let start = (y * self.width + x1) * 3;
|
||||
let end = (y * self.width + x2) * 3;
|
||||
&self.buf[start..end]
|
||||
})
|
||||
}
|
||||
|
||||
fn clean(&mut self) {
|
||||
self.dirty = None;
|
||||
}
|
||||
|
||||
fn dirty(&self) -> Option<(usize, usize, usize, usize)> {
|
||||
self.dirty
|
||||
}
|
||||
|
||||
fn width(&self) -> usize {
|
||||
self.width
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,6 +175,9 @@ unsafe fn main() -> ! {
|
||||
let mut data_command = pins.gpio15.into_function();
|
||||
let mut reset = pins.gpio14.into_function();
|
||||
|
||||
let i2c_clk: Pin<Gpio21, FunctionI2C, PullUp> = pins.gpio21.reconfigure();
|
||||
let i2c_sdo: Pin<Gpio20, FunctionI2C, PullUp> = pins.gpio20.reconfigure();
|
||||
|
||||
let _ = reset.set_low();
|
||||
let _ = board_select.set_high();
|
||||
let _ = data_command.set_high();
|
||||
@ -132,6 +194,17 @@ unsafe fn main() -> ! {
|
||||
embedded_hal::spi::MODE_3,
|
||||
);
|
||||
|
||||
let i2c = I2C::i2c0(
|
||||
peripherals.I2C0,
|
||||
i2c_sdo,
|
||||
i2c_clk,
|
||||
400.kHz(),
|
||||
&mut peripherals.RESETS,
|
||||
125_000_000.Hz(),
|
||||
);
|
||||
|
||||
let mut light_sensor = LightSensor::new(i2c);
|
||||
|
||||
let mut display = ST7789Display::new(board_select, data_command, spi);
|
||||
|
||||
let _ = reset.set_high();
|
||||
@ -148,37 +221,124 @@ unsafe fn main() -> ! {
|
||||
let mut canvas = Canvas::new(&mut framebuf, COLUMNS);
|
||||
*/
|
||||
let mut canvas = FrameBuf::new();
|
||||
let white = RGB { r: 63, g: 63, b: 63 };
|
||||
let white = RGB {
|
||||
r: 63,
|
||||
g: 63,
|
||||
b: 63,
|
||||
};
|
||||
let mut count = 0;
|
||||
|
||||
loop {
|
||||
canvas.fill(0, 10, 170, 20, &RGB{r: 0, g: 0, b: 0 });
|
||||
print(&mut canvas, &font_bitmap, 1, 10, &format(format_args!("COUNT: {:03}", count)), &RGB{ r: 32, g: 32, b: 63 });
|
||||
print(&mut canvas, &font_bitmap, 1, 200, " !\"#$%&'<>*+,-./", &RGB{ r: 63, g: 63, b: 63 });
|
||||
print(&mut canvas, &font_bitmap, 1, 220, "0123456789|: = ?", &RGB{ r: 63, g: 63, b: 63 });
|
||||
print(&mut canvas, &font_bitmap, 1, 240, "@ABCDEFGHIJKLMNO", &RGB{ r: 63, g: 63, b: 63 });
|
||||
print(&mut canvas, &font_bitmap, 1, 260, "PQRSTUVWXYZ[\\]^_", &RGB{ r: 63, g: 63, b: 63 });
|
||||
print(&mut canvas, &font_bitmap, 1, 280, "`abcdefghijklmno", &RGB{ r: 63, g: 63, b: 63 });
|
||||
print(&mut canvas, &font_bitmap, 1, 300, "pqrstuvwxyz{|}", &RGB{ r: 63, g: 63, b: 63 });
|
||||
light_sensor.power_up();
|
||||
match light_sensor.control() {
|
||||
Ok(v) if v == 0 => print(
|
||||
&mut canvas,
|
||||
&font_bitmap,
|
||||
0,
|
||||
0,
|
||||
&format(format_args!("POWER_DOWN")),
|
||||
&RGB {
|
||||
r: 63,
|
||||
g: 16,
|
||||
b: 16,
|
||||
},
|
||||
),
|
||||
Ok(_) => {}
|
||||
Err(err) => print(
|
||||
&mut canvas,
|
||||
&font_bitmap,
|
||||
0,
|
||||
0,
|
||||
&format(format_args!("ERROR: {:?}", err)),
|
||||
&RGB {
|
||||
r: 63,
|
||||
g: 16,
|
||||
b: 16,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
// canvas.square(10, 70, 160, 310, &white);
|
||||
{
|
||||
let display = display.acquire();
|
||||
display.blit_frame(&canvas);
|
||||
}
|
||||
|
||||
loop {
|
||||
canvas.fill(0, 0, 170, 60, &RGB { r: 0, g: 0, b: 0 });
|
||||
if let Some((x1, y1, x2, y2)) = canvas.dirty() {
|
||||
print(
|
||||
&mut canvas,
|
||||
&font_bitmap,
|
||||
0,
|
||||
0,
|
||||
&format(format_args!("{} {} {} {}", x1, y1, x2, y2)),
|
||||
&RGB {
|
||||
r: 63,
|
||||
g: 63,
|
||||
b: 63,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
match light_sensor.read_full_spectrum() {
|
||||
Ok(full) => print(
|
||||
&mut canvas,
|
||||
&font_bitmap,
|
||||
0,
|
||||
20,
|
||||
&format(format_args!("FULL: {}", full)),
|
||||
&RGB {
|
||||
r: 63,
|
||||
g: 63,
|
||||
b: 63,
|
||||
},
|
||||
),
|
||||
Err(err) => print(
|
||||
&mut canvas,
|
||||
&font_bitmap,
|
||||
0,
|
||||
20,
|
||||
&format(format_args!("FULL: {:?}", err)),
|
||||
&RGB {
|
||||
r: 63,
|
||||
g: 16,
|
||||
b: 16,
|
||||
},
|
||||
),
|
||||
}
|
||||
match light_sensor.read_ir() {
|
||||
Ok(ir) => print(
|
||||
&mut canvas,
|
||||
&font_bitmap,
|
||||
0,
|
||||
40,
|
||||
&format(format_args!("IR: {}", ir)),
|
||||
&RGB {
|
||||
r: 63,
|
||||
g: 63,
|
||||
b: 63,
|
||||
},
|
||||
),
|
||||
Err(err) => print(
|
||||
&mut canvas,
|
||||
&font_bitmap,
|
||||
0,
|
||||
40,
|
||||
&format(format_args!("IR: {:?}", err)),
|
||||
&RGB {
|
||||
r: 63,
|
||||
g: 16,
|
||||
b: 16,
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
{
|
||||
let display = display.acquire();
|
||||
let _ = led.set_high();
|
||||
timer.delay_ms(100);
|
||||
display.send_buf(canvas.buf);
|
||||
display.blit_dirty(&canvas);
|
||||
let _ = led.set_low();
|
||||
}
|
||||
count = count + 1;
|
||||
/*
|
||||
for x in 80..90 {
|
||||
for y in 155..165 {
|
||||
draw_pixel(&mut frame, x, y, (0, 0, 63));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
timer.delay_ms(1000);
|
||||
timer.delay_ms(100);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ use rp_pico::hal::{
|
||||
Spi, Timer,
|
||||
};
|
||||
|
||||
use crate::canvas::Canvas;
|
||||
|
||||
pub struct Step {
|
||||
param_cnt: usize,
|
||||
command: u8,
|
||||
@ -185,14 +187,52 @@ impl<BoardSelectId: PinId, DataCommandId: PinId, D: SpiDevice, Pinout: ValidSpiP
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_buf(&mut self, frame: &[u8]) {
|
||||
pub fn blit_frame(&mut self, frame: &impl Canvas) {
|
||||
// let _ = DISPOFF.send_command(&mut self.spi, &mut self.data_command);
|
||||
let _ = self.data_command.set_low();
|
||||
let _ = self.spi.write(&[RAMWR]);
|
||||
let _ = self.data_command.set_high();
|
||||
let _ = self.spi.write(&frame);
|
||||
let _ = self.spi.write(frame.buf());
|
||||
// let _ = DISPON.send_command(&mut self.spi, &mut self.data_command);
|
||||
}
|
||||
|
||||
pub fn blit_dirty(&mut self, frame: &impl Canvas) {
|
||||
if let Some((start_x, start_y, end_x, end_y)) = frame.dirty() {
|
||||
let end_y = end_y + 60;
|
||||
Step {
|
||||
param_cnt: 4,
|
||||
command: 0x30,
|
||||
params: [
|
||||
(start_y >> 8 & 0xff) as u8,
|
||||
(start_y & 0xff) as u8,
|
||||
(end_y >> 8 & 0xff) as u8,
|
||||
(end_y & 0xff) as u8,
|
||||
],
|
||||
delay: None,
|
||||
}
|
||||
.send_command(&mut self.spi, &mut self.data_command);
|
||||
Step {
|
||||
param_cnt: 0,
|
||||
command: 0x12,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: None,
|
||||
}
|
||||
.send_command(&mut self.spi, &mut self.data_command);
|
||||
let _ = self.data_command.set_low();
|
||||
let _ = self.spi.write(&[RAMWR]);
|
||||
let _ = self.data_command.set_high();
|
||||
for row in frame.partial(0, start_y, frame.width(), end_y) {
|
||||
let _ = self.spi.write(row);
|
||||
}
|
||||
Step {
|
||||
param_cnt: 0,
|
||||
command: 0x13,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: None,
|
||||
}
|
||||
.send_command(&mut self.spi, &mut self.data_command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<BoardSelectId: PinId, DataCommandId: PinId, D: SpiDevice, Pinout: ValidSpiPinout<D>> Drop
|
||||
|
Loading…
Reference in New Issue
Block a user