aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/example/display.rs
blob: 58302547f9633538aea4115901d67f8c28eae4d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use defmt::info;
use display_interface_spi::SpiInterface;
use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive};
use embassy_nrf::{interrupt::typelevel::Binding, spim, Peri};
use embassy_time::Timer;
use embedded_graphics::{
    framebuffer::{buffer_size, Framebuffer},
    pixelcolor::{raw::LittleEndian, Gray4},
};
use embedded_hal_bus::spi::ExclusiveDevice;
use ssd1322::{DisplayAsync, PixelCoord};

type SPIDevice<'t> = ExclusiveDevice<spim::Spim<'t>, Output<'t>, embassy_time::Delay>;

type Display<'t> = DisplayAsync<SpiInterface<SPIDevice<'t>, Output<'t>>>;

pub struct Pins<'t> {
    pub ven: Peri<'t, AnyPin>,
    pub rst: Peri<'t, AnyPin>,
    pub sck: Peri<'t, AnyPin>,
    pub sdo: Peri<'t, AnyPin>,
    pub cs: Peri<'t, AnyPin>,
    pub dc: Peri<'t, AnyPin>,
}

pub async fn init<T: spim::Instance>(
    spi_instance: Peri<'static, T>,
    irq_binding: impl Binding<T::Interrupt, spim::InterruptHandler<T>> + 'static,
    pins: Pins<'static>,
) -> Display<'static> {
    Output::new(pins.ven, Level::High, OutputDrive::Standard).persist();

    let mut out_rst = Output::new(pins.rst, Level::Low, OutputDrive::Standard);
    Timer::after_millis(2).await;
    out_rst.set_high();
    Timer::after_millis(2).await;

    let out_cs = Output::new(pins.cs, Level::High, OutputDrive::Standard);
    let out_dc = Output::new(pins.dc, Level::High, OutputDrive::Standard);

    let mut spi_config = spim::Config::default();
    spi_config.frequency = spim::Frequency::M8;
    let spi_bus = spim::Spim::new_txonly(spi_instance, irq_binding, pins.sck, pins.sdo, spi_config);
    let spi_dev = ExclusiveDevice::new(spi_bus, out_cs, embassy_time::Delay).unwrap();
    let spi_iface = SpiInterface::new(spi_dev, out_dc);

    let mut display = DisplayAsync::new(spi_iface, PixelCoord(256, 64), PixelCoord(0x1C * 4, 0));

    info!("initializing display");
    display
        .init(
            ssd1322::ConfigAsync::new(
                ssd1322::ComScanDirection::RowZeroLast,
                ssd1322::ComLayout::Progressive,
            )
            .column_remap(ssd1322::command::ColumnRemap::Reverse)
            .clock_fosc_divset(9, 1)
            .display_enhancements(true, true)
            .contrast_current(0x7f)
            .phase_lengths(5, 15)
            .precharge_voltage(0x1f)
            .com_deselect_voltage(0x04),
        )
        .await
        .unwrap();

    display
}

#[embassy_executor::task]
pub async fn task(mut display: Display<'static>) {
    let mut fb =
        Framebuffer::<Gray4, _, LittleEndian, 128, 64, { buffer_size::<Gray4>(128, 64) }>::new();

    info!("display task starting");
    t114_meshcore_example::display_task(&mut fb, async |fb| {
        display
            .region(PixelCoord(0, 0), PixelCoord(256, 64))
            .unwrap()
            .draw_packed(fb.data().iter().flat_map(|n| {
                let upper = n & 0xf0;
                let lower = n & 0x0f;
                [upper | (upper >> 4), lower | (lower << 4)]
            }))
            .await
            .unwrap();
    })
    .await;
}