rp2040_akizuki_lcd_aqm0802/
main.rs

1#![no_std]
2#![no_main]
3
4use rp2040_hal as hal;
5
6use hal::{fugit::RateExtU32, i2c::I2C};
7
8use embedded_hal::{delay::DelayNs, digital::OutputPin, i2c::I2c};
9
10#[cfg(not(feature = "defmt"))]
11#[panic_handler]
12fn panic(_: &core::panic::PanicInfo) -> ! {
13    loop {}
14}
15
16#[cfg(feature = "defmt")]
17use {defmt_rtt as _, panic_probe as _};
18
19#[link_section = ".boot2"]
20#[no_mangle]
21#[used]
22static BOOT2_FIRMWARE: [u8; 256] = rp2040_boot2::BOOT_LOADER_GD25Q64CS;
23
24const XOSC_CRYSTAL_FREQ: u32 = 12_000_000;
25
26#[hal::entry]
27fn main() -> ! {
28    let mut pac = hal::pac::Peripherals::take().unwrap();
29    let _core = hal::pac::CorePeripherals::take().unwrap();
30
31    let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
32
33    let clocks = hal::clocks::init_clocks_and_plls(
34        XOSC_CRYSTAL_FREQ,
35        pac.XOSC,
36        pac.CLOCKS,
37        pac.PLL_SYS,
38        pac.PLL_USB,
39        &mut pac.RESETS,
40        &mut watchdog,
41    )
42    .unwrap();
43
44    let mut timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks);
45
46    let sio = hal::Sio::new(pac.SIO);
47    let pins = hal::gpio::Pins::new(
48        pac.IO_BANK0,
49        pac.PADS_BANK0,
50        sio.gpio_bank0,
51        &mut pac.RESETS,
52    );
53
54    let mut led = pins.gpio13.into_push_pull_output();
55    let mut lcd_resetn = pins.gpio7.into_push_pull_output();
56
57    let mut i2c = I2C::i2c1(
58        pac.I2C1,
59        pins.gpio2.reconfigure(),
60        pins.gpio3.reconfigure(),
61        400.kHz(),
62        &mut pac.RESETS,
63        &clocks.system_clock,
64    );
65
66    const LCD_ADDRESS: u8 = 0x3e;
67
68    // めも: control byte, data byte の順で交互に書き込む
69    // i2c.write(LCD_ADDRESS, &[
70    //       ┌───── C0: 最終データのとき0、それ以外のとき1
71    //       │┌──── Rs: Data register の読み書きのとき1
72    //     0b11_000000, 0b0011_0000
73    //     0b11_000000, 0b0011_0001
74    //     0b01_000000, 0b0011_0010
75    // ]).unwrap();
76
77    // power on and external reset
78    lcd_resetn.set_high().unwrap();
79    timer.delay_us(50_000);
80
81    // Function Set:
82    //  0 0 0 0 1 DL N DH *0 IS
83    //  where:   DL: interface data is 8/4 bits
84    //            N: number of line is 2/1
85    //           DH: double height font
86    //           IS: instruction table select
87
88    i2c.write(LCD_ADDRESS, &[0b00_000000, 0b0011_1000]).unwrap();
89    timer.delay_us(30);
90
91    i2c.write(LCD_ADDRESS, &[0b00_000000, 0b0011_1001]).unwrap();
92    timer.delay_us(30);
93
94    // Internal OSC frequency:
95    //  0 0 0 0 0 1 BS F2 F1 F0
96    // where:   BS: 1:1/4 bias
97    //          BS: 0:1/5 bias
98    //        F2~0: adjust internal OSC frequency for FR frequency.
99
100    i2c.write(LCD_ADDRESS, &[0b00_000000, 0b0001_0100]).unwrap();
101    timer.delay_us(30);
102
103    // Contrast set:
104    //  0 0 0 1 1 1 C3 C2 C1 C0
105
106    i2c.write(LCD_ADDRESS, &[0b00_000000, 0b0111_0000]).unwrap();
107    timer.delay_us(30);
108
109    // Power/ICON control/Contrast set:
110    //  0 0 0 1 0 1 Ion Bon C5 C4
111    // where:  Ion: ICON display on/off
112    //         Bon: set booster circuit on/off
113    //       C5,C4: Contrast set for internal follower mode.
114
115    i2c.write(LCD_ADDRESS, &[0b00_000000, 0b0101_0110]).unwrap();
116    timer.delay_us(30);
117
118    // Follower control:
119    //  0 0 0 1 1 0 Fon Rab2 Rab1 Rab0
120    // where:  Fon: set follower circuit on/off
121    //      Rab2~0: select follower amplified ratio.
122
123    i2c.write(LCD_ADDRESS, &[0b00_000000, 0b0110_1100]).unwrap();
124    timer.delay_us(200_000);
125
126    i2c.write(LCD_ADDRESS, &[0b00_000000, 0b0011_1000]).unwrap();
127    timer.delay_us(30);
128
129    // Display ON/OFF:
130    //  0 0 0 0 0 0 1 D C B
131    // where:  D=1: entire display on
132    //         C=1: cursor on
133    //         B=1: cursor position on
134
135    i2c.write(LCD_ADDRESS, &[0b00_000000, 0b0000_1110]).unwrap();
136    timer.delay_us(30);
137
138    // Clear Display:
139    //  0 0 0 0 0 0 0 0 0 1
140
141    i2c.write(LCD_ADDRESS, &[0b00_000000, 0b0000_0001]).unwrap();
142    timer.delay_us(2_000);
143
144    #[rustfmt::skip]
145    const PATTERNS: &[&[u8]] = &[
146        &[
147            0b11_000000, 0b0011_0000,
148            0b11_000000, 0b0011_0001,
149            0b11_000000, 0b0011_0010,
150            0b11_000000, 0b0011_0011,
151            0b11_000000, 0b0011_0100,
152            0b11_000000, 0b0011_0101,
153            0b11_000000, 0b0011_0110,
154            0b01_000000, 0b0011_0111,
155        ],
156        &[
157            0b11_000000, 0b0100_0001,
158            0b11_000000, 0b0100_0010,
159            0b11_000000, 0b0100_0011,
160            0b11_000000, 0b0100_0100,
161            0b11_000000, 0b0100_0101,
162            0b11_000000, 0b0100_0110,
163            0b11_000000, 0b0100_0111,
164            0b01_000000, 0b0100_1000,
165        ],
166        &[
167            0b11_000000, 0b0110_0001,
168            0b11_000000, 0b0110_0010,
169            0b11_000000, 0b0110_0011,
170            0b11_000000, 0b0110_0100,
171            0b11_000000, 0b0110_0101,
172            0b11_000000, 0b0110_0110,
173            0b11_000000, 0b0110_0111,
174            0b01_000000, 0b0110_1000,
175        ],
176        &[
177            0b11_000000, 0b1011_0001,
178            0b11_000000, 0b1011_0010,
179            0b11_000000, 0b1011_0011,
180            0b11_000000, 0b1011_0100,
181            0b11_000000, 0b1011_0101,
182            0b11_000000, 0b1011_0110,
183            0b11_000000, 0b1011_0111,
184            0b01_000000, 0b1011_1000,
185        ],
186    ];
187
188    loop {
189        for (i, p) in PATTERNS.iter().enumerate() {
190            // Set DDRAM address:
191            //  0 0 1 AC6 AC5 AC4 AC3 AC2 AC1 AC0
192            if i & 1 == 0 {
193                led.set_high().unwrap();
194                i2c.write(LCD_ADDRESS, &[0b00_000000, 0b1000_0000]).unwrap();
195            } else {
196                led.set_low().unwrap();
197                i2c.write(LCD_ADDRESS, &[0b00_000000, 0b1100_0000]).unwrap();
198            }
199            timer.delay_us(30);
200
201            i2c.write(LCD_ADDRESS, p).unwrap();
202
203            timer.delay_us(500_000);
204        }
205    }
206}