Facebook
From d4rk, 2 Weeks ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 115
  1. #![no_std]
  2. #![no_main]
  3. #![allow(unused_imports, dead_code, unused_variables, unused_mut)]
  4.  
  5. use core::panic::PanicInfo;
  6. use embassy_executor::Spawner;
  7.  
  8. use embassy_rp::gpio::{Input, Level, Output, Pin, Pull};
  9.  
  10. // USB driver
  11. use embassy_rp::usb::{Driver, InterruptHandler as USBInterruptHandler};
  12. use embassy_rp::{bind_interrupts, peripherals::USB};
  13. use log::info;
  14.  
  15. use embassy_time::Timer;
  16.  
  17. // I2C
  18. use embassy_rp::i2c::{Config as I2cConfig, I2c, InterruptHandler as I2CInterruptHandler};
  19. use embassy_rp::peripherals::I2C0;
  20. use embedded_hal_async::i2c::{Error, I2c as _};
  21.  
  22. use core::cell::RefCell;
  23. use embassy_embedded_hal::shared_bus::blocking::spi::SpiDeviceWithConfig;
  24. use embassy_rp::spi;
  25. use embassy_rp::spi::{Async, Blocking, Spi};
  26. use embassy_sync::blocking_mutex::raw::NoopRawMutex;
  27. use embassy_sync::blocking_mutex::Mutex;
  28.  
  29. use core::fmt::Write;
  30. use embassy_time::Delay;
  31. use embedded_graphics::mono_font::iso_8859_16::FONT_10X20;
  32. use embedded_graphics::mono_font::MonoTextStyle;
  33. use embedded_graphics::pixelcolor::Rgb565;
  34. use embedded_graphics::prelude::*;
  35. use embedded_graphics::text::renderer::CharacterStyle;
  36. use embedded_graphics::text::Text;
  37. use heapless::String;
  38. use lab07_all::SPIDeviceInterface;
  39. use st7789::{Orientation, ST7789};
  40.  
  41. bind_interrupts!(struct Irqs {
  42.     // Use for the serial over USB driver
  43.     USBCTRL_IRQ => USBInterruptHandler<USB>;
  44.     I2C0_IRQ => I2CInterruptHandler<I2C0>;
  45. });
  46.  
  47. const DISPLAY_FREQ: u32 = 64_000_000;
  48.  
  49. #[embassy_executor::task]
  50. async fn logger_task(driver: Driver<'static, USB>) {
  51.     embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver);
  52. }
  53.  
  54. // The formula for calculating the actual temperature value (in Celsius) from the raw value
  55. fn calculate_temperature(temperature_raw: u32) -> i32 {
  56.     let var1: i32 = ((temperature_raw as i32 >> 3) - (27504 << 1)) * (26435 >> 11);
  57.     let var2: i32 = ((temperature_raw as i32 >> 4) - 27504)
  58.         * (((temperature_raw as i32 >> 4) - 27504) >> 12)
  59.         * (-1000 >> 14);
  60.     ((var1 + var2) * 5 + 128) >> 8
  61. }
  62.  
  63. #[embassy_executor::main]
  64. async fn main(spawner: Spawner) {
  65.     let peripherals = embassy_rp::init(Default::default());
  66.  
  67.     // Start the serial port over USB driver
  68.     let driver = Driver::new(peripherals.USB, Irqs);
  69.     spawner.spawn(logger_task(driver)).unwrap();
  70.  
  71.     let mut display_config = spi::Config::default();
  72.     display_config.frequency = DISPLAY_FREQ;
  73.     display_config.phase = spi::Phase::CaptureOnSecondTransition;
  74.     display_config.polarity = spi::Polarity::IdleHigh;
  75.  
  76.     // Display SPI pins
  77.     let miso = peripherals.PIN_4;
  78.     let mosi = peripherals.PIN_19;
  79.     let clk = peripherals.PIN_18;
  80.  
  81.     // Display SPI
  82.     let mut spi_display: Spi<'_, _, Blocking> =
  83.         Spi::new_blocking(peripherals.SPI0, clk, mosi, miso, display_config.clone());
  84.     // SPI bus for display
  85.     let spi_bus: Mutex<NoopRawMutex, _> = Mutex::new(RefCell::new(spi_display));
  86.  
  87.     let mut display_cs = Output::new(peripherals.PIN_17, Level::High);
  88.  
  89.     // Display SPI device initialization
  90.     let display_spi = SpiDeviceWithConfig::new(&spi;_bus, display_cs, display_config);
  91.  
  92.     // Other display pins
  93.     let rst = peripherals.PIN_0;
  94.     let dc = peripherals.PIN_16;
  95.     let dc = Output::new(dc, Level::Low);
  96.     let rst = Output::new(rst, Level::Low);
  97.     let di = SPIDeviceInterface::new(display_spi, dc);
  98.  
  99.     // Init ST7789 LCD
  100.     let mut display = ST7789::new(di, rst, 240, 240);
  101.     display.init(&mut; Delay).unwrap();
  102.     display.set_orientation(Orientation::Portrait).unwrap();
  103.     display.clear(Rgb565::BLACK).unwrap();
  104.  
  105.     // Define style
  106.     let mut style = MonoTextStyle::new(&FONT;_10X20, Rgb565::GREEN);
  107.     style.set_background_color(Some(Rgb565::BLACK));
  108.  
  109.     // EXERCISE 2 --------------------
  110.     // TODO 1: Declare SDA and SCL pins
  111.     let sda = peripherals.PIN_26;
  112.     let scl = peripherals.PIN_27;
  113.  
  114.     // TODO 2: Define async I2C
  115.     let mut i2c = I2c::new_async(peripherals.I2C0, scl, sda, Irqs, I2cConfig::default());
  116.  
  117.     // TODO 3: Define I2C address of the BMP280 (from lab or from datasheet)
  118.     const BMP280_ADDR: u16 = 0x76;
  119.  
  120.     // TODO 4: Define ID register address (from last lab or from datasheet)
  121.     const REG_ADDR_ID: u8 = 0xD0;
  122.     // EXERCISE 3 --------------------
  123.     // TODO 9: Define CTRL_MEAS register address
  124.     const REG_ADDR_CTRL_MEAS: u8 = 0x00;
  125.  
  126.     // TODO 12: Define PRESS register address
  127.     const REG_ADDR_PRESS_MSB: u8 = 0x00;
  128.  
  129.     // TODO 17: Define TEMP register address
  130.     const REG_ADDR_TEMP_MSB: u8 = 0x00;
  131.  
  132.     // TODO 5: Define TX buffer that will be sent to the sensor
  133.     //         This should be initialized with one element: the address of the register we want to read
  134.     let tx_buf = [0xFA];
  135.     // TODO 6: Define RX buffer that will store the value received from the sensor
  136.     //         This can be initially set to a buffer with one empty value (0)
  137.     //         This will store the value of the register we read from the sensor
  138.     let mut rx_buf = [0x00u8];
  139.  
  140.     let mut id: u8 = 0;
  141.     match i2c.write_read_async(BMP280_ADDR, tx_buffer.iter().copied(), &mut; rx_buffer).await {
  142.         Ok(_) => {
  143.             id = rx_buffer[0];
  144.             info!("ID of BMP280: {}", id);
  145.         }
  146.         Err(e) => {
  147.             info!("Error reading ID: {:?}", e);
  148.         }
  149.     }
  150.  
  151.     loop {
  152.         Timer::after_millis(1000).await;
  153.         info!("ID of BMP280: {id}");
  154.         // TODO 10: Define TX buffer for configuring the sensor (for writing to the `ctrl_meas` register)
  155.         //          The contents of the buffer are similar to what we used in the last lab with SPI
  156.  
  157.         // TODO 11: Write this buffer to the sensor (`write`)
  158.  
  159.         // TODO 13: Define TX and RX buffers for reading pressure registers
  160.         //          Hint: The RX buffer should have 3 elements, since we want to
  161.         //                read press_msb, press_lsb and press_xlsb
  162.  
  163.         // TODO 14: Read the three pressure register values from the sensor (just like you did with the `id`)
  164.  
  165.         // TODO 15: Compute the raw pressure value from the three register values
  166.         let pressure_raw: u32 = 0; // modify
  167.  
  168.         // TODO 16: Print the raw pressure value
  169.  
  170.         info!("Raw pressure reading: {pressure_raw}");
  171.  
  172.         // TODO 18: Define TX and RX buffers for reading temperature registers
  173.  
  174.         // TODO 19: Read the three temperature register values from the sensor
  175.  
  176.         // TODO 20: Compute the raw temperature value from the three register values
  177.  
  178.         let temperature_raw: u32 = 0; // modify
  179.  
  180.         // TODO 21: Get the actual temperature value (in Celsius), using the provided `calculate_temperature`
  181.         //          function
  182.         let temperature: i32 = 0; // modify
  183.  
  184.         // TODO 22: Print the actual temperature value
  185.  
  186.         info!("Temperature reading (Celsius): {temperature}");
  187.  
  188.         // END EXERCISE 3 -------------------------
  189.  
  190.         // EXERCISE 4
  191.         // TODO 23: Print the raw pressure and the actual temperature to the screen
  192.         //          Hint: The temperature value returned by the `calculate_temperature` function is 100 * temperature
  193.         //                Print the correct value to the screen, as a rational number (example: 24.50 degrees)
  194.     }
  195. }
  196.  
  197. #[panic_handler]
  198. fn panic(_info: &PanicInfo;) -> ! {
  199.     loop {}
  200. }
  201.