~ruther/map-led-strip

ref: b7e43afe1dd99a6454be3c355d038bd228571ba2 map-led-strip/src/main.rs -rw-r--r-- 5.7 KiB
b7e43afe — František Boháček feat: add map clear 1 year, 9 months ago
                                                                                
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#![no_std]
#![no_main]

extern crate alloc;

mod strip;
mod map;
mod commands;
mod animations;
mod constants;

use alloc::boxed::Box;
use embedded_hal::serial::{Read, Write};
use embedded_hal::timer::CountDown;
use esp_backtrace as _;
use esp_println::println;
use hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, timer::{TimerGroup}, Rtc, IO, Delay, PulseControl, Uart};
use hal::uart::config::{Config, DataBits, Parity, StopBits};
use hal::uart::TxRxPins;
use nb::block;
use nb::Error::{Other};
use smart_leds::{RGB8, SmartLedsWrite};
use esp_alloc::EspHeap;
use crate::animations::animation_manager::AnimationManager;
use crate::commands::all_command::AllCommand;
use crate::commands::command_handler::{CommandHandler};
use crate::commands::command_handler;
use crate::commands::hello_world_command::HelloWorldCommand;
use crate::commands::reset_command::ResetCommand;
use crate::commands::set_command::SetCommand;
use crate::commands::snake_command::SnakeCommand;
use crate::map::Map;
use crate::strip::StripTiming;

#[global_allocator]
static ALLOCATOR: EspHeap = EspHeap::empty();

fn init_heap() {
    extern "C" {
        static mut _heap_start: u32;
        static mut _heap_end: u32;
    }

    unsafe {
        let heap_start = &_heap_start as *const _ as usize;
        let heap_end = &_heap_end as *const _ as usize;
        ALLOCATOR.init(heap_start as *mut u8, heap_end - heap_start);
    }
}

#[entry]
fn main() -> ! {
    let peripherals = Peripherals::take();
    let mut system = peripherals.DPORT.split();
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

    init_heap();

    // Disable the RTC and TIMG watchdog timers
    let mut rtc = Rtc::new(peripherals.RTC_CNTL);
    let timer_group0 = TimerGroup::new(
        peripherals.TIMG0,
        &clocks,
        &mut system.peripheral_clock_control,
    );
    let mut wdt0 = timer_group0.wdt;
    let timer_group1 = TimerGroup::new(
        peripherals.TIMG1,
        &clocks,
        &mut system.peripheral_clock_control,
    );
    let mut wdt1 = timer_group1.wdt;
    rtc.rwdt.disable();
    wdt0.disable();
    wdt1.disable();

    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

    // Init UART
    let pins = TxRxPins::new_tx_rx(
        io.pins.gpio1.into_push_pull_output(),
        io.pins.gpio3.into_floating_input(),
    );

    let config = Config {
        baudrate: 115200,
        data_bits: DataBits::DataBits8,
        parity: Parity::ParityNone,
        stop_bits: StopBits::STOP1,
    };

    let mut serial = Uart::new_with_config(
        peripherals.UART0,
        Some(config),
        Some(pins),
        &clocks,
        &mut system.peripheral_clock_control,
    );

    // Init strip
    let pulse = PulseControl::new(
        peripherals.RMT,
        &mut system.peripheral_clock_control,
    ).unwrap();

    let mut strip = strip::Strip::<_, { constants::LEDS_COUNT * 24 + 1 }>::new(
        pulse.channel0,
        io.pins.gpio25,
        StripTiming::new(
            800u32.nanos(),
            450u32.nanos(),
            400u32.nanos(),
            850u32.nanos(),
        ),
    );

    // Init map
    let mut rgb_data: [RGB8; 72] = [RGB8 { r: 0, g: 0, b: 0 }; 72];
    let mut map = map::Map::new(&map::INDEX_MAP, &mut rgb_data);
    let mut animations = AnimationManager::new(timer_group0.timer0);
    let mut delay = Delay::new(&clocks);

    // Init commands
    let mut handler = CommandHandler::new(
        [
            ("HELLO_WORLD", Box::new(HelloWorldCommand::default())),
            ("SET", Box::new(SetCommand::default())),
            ("RESET", Box::new(ResetCommand::default())),
            ("ALL", Box::new(AllCommand::default())),
            ("SNAKE", Box::new(SnakeCommand::default()))
        ],
        ['\0'; constants::COMMAND_BUFFER],
    );

    print_new_command(&mut serial);

    loop {
        // result is either ok, then do nothing,
        // would block, then do nothing
        // or last step, then do nothing as well...
        let _ = animations.update(&mut map);

        let new_command = match handler.read_command(&mut serial) {
            Ok(()) => {
                println!("\r");
                let result = handler.handle_command(&mut map, animations.storage());

                match result {
                    Ok(()) => true,
                    Err(err) => {
                        match err {
                            command_handler::CommandHandleError::NotFound => println!("Command not found.\r"),
                            command_handler::CommandHandleError::WrongArguments => println!("Wrong arguments.\r"),
                            command_handler::CommandHandleError::CommandNotRead => println!("FATAL: Command is not prepared.\r")
                        }
                        true
                    }
                }
            },
            Err(err) => {
                match err {
                    Other(error) => {
                        match error {
                            command_handler::CommandReadError::BufferOverflowed => println!("Command is too long.\r"),
                            command_handler::CommandReadError::UnexpectedEndOfLine => (),
                            command_handler::CommandReadError::CommandLoadedAlready => println!("FATAL: Previous command not processed correctly.\r")
                        };
                        true
                    }
                    _ => false
                }
            }
        };

        if new_command {
            print_new_command(&mut serial);
        }

        strip.write(map.get_map().cloned()).unwrap();
        delay.delay_us(500u32);
    }

    fn print_new_command<T: Write<u8>>(serial: &mut T) {
        println!("\r");
        block!(serial.write(b'>')).ok().unwrap();
        block!(serial.write(b' ')).ok().unwrap();
    }
}
Do not follow this link