rust: enum for I/O pin definitions

This commit is contained in:
Wladimir J. van der Laan 2019-05-14 11:29:47 +00:00
parent 582092810f
commit 08cd58654f
8 changed files with 176 additions and 44 deletions

View File

@ -25,7 +25,7 @@ Maix Go
### On-board ### On-board
- MSA300 - Accelerometer (I2C) - MSA300 - Accelerometer (I2C, address 0x26)
- STM32F103C8 - JTAG & UART, debug M1 without extra Jlink, this bypasses the CH340C on the module (USB to host, serial to K210) - STM32F103C8 - JTAG & UART, debug M1 without extra Jlink, this bypasses the CH340C on the module (USB to host, serial to K210)
- OV2640 - Color CMOS UXGA (2.0 MegaPixel) CAMERA C HI (DVP) - OV2640 - Color CMOS UXGA (2.0 MegaPixel) CAMERA C HI (DVP)
@ -34,6 +34,6 @@ Maix Go
(source: schematic) (source: schematic)
- ST7789V - 240RGB x 320 dot 262K Color with Frame Memory Single-Chip TFT Controller/Driver (SPI) - ST7789V - 240RGB x 320 dot 262K Color with Frame Memory Single-Chip TFT Controller/Driver (SPI)
- NS2009 - 4-Wire Touch Screen Controller (I2C) - NS2009 - 4-Wire Touch Screen Controller (I2C, address 0x48)
- TF card slot (SPI) - TF card slot (SPI)

View File

@ -7,10 +7,10 @@ def rgb565(r, g, b):
image = [[(0, 0, 0)] * BLK_SIZE for _ in range(BLK_SIZE)] image = [[(0, 0, 0)] * BLK_SIZE for _ in range(BLK_SIZE)]
mm = BLK_SIZE//2 mm = BLK_SIZE//2-1
for y in range(BLK_SIZE//2): for y in range(BLK_SIZE//2):
for x in range(BLK_SIZE//2): for x in range(BLK_SIZE//2):
l = min(x,y) l = min(min(x,y),mm)
col = (0xa8*(l+1)//mm,0x48*(l+1)//mm,0xa8*(l+1)//mm) col = (0xa8*(l+1)//mm,0x48*(l+1)//mm,0xa8*(l+1)//mm)
image[y][x] = col image[y][x] = col
image[BLK_SIZE-y-1][x] = col image[BLK_SIZE-y-1][x] = col
@ -24,4 +24,4 @@ for y in range(BLK_SIZE):
print('pub static BLOCK_SPRITE: [[u32; 4];8] = [') print('pub static BLOCK_SPRITE: [[u32; 4];8] = [')
for y in outb: for y in outb:
print(' [%s],' % (', '.join(('0x%08x' % i) for i in y))) print(' [%s],' % (', '.join(('0x%08x' % i) for i in y)))
print(']') print('];')

View File

@ -9,7 +9,7 @@ extern crate panic_halt;
use k210_hal::pac; use k210_hal::pac;
use k210_hal::prelude::*; use k210_hal::prelude::*;
use k210_hal::stdout::Stdout; use k210_hal::stdout::Stdout;
use k210_shared::board::def::{DISP_WIDTH,DISP_HEIGHT,NS2009_SLV_ADDR,NS2009_CAL,NS2009_ADDR_BITS,NS2009_CLK}; use k210_shared::board::def::{io,DISP_WIDTH,DISP_HEIGHT,NS2009_SLV_ADDR,NS2009_CAL,NS2009_ADDR_BITS,NS2009_CLK};
use k210_shared::board::lcd; use k210_shared::board::lcd;
use k210_shared::board::lcd_colors; use k210_shared::board::lcd_colors;
use k210_shared::board::ns2009::TouchScreen; use k210_shared::board::ns2009::TouchScreen;
@ -23,14 +23,20 @@ pub const BLK_SIZE: usize = 8;
pub const GRID_WIDTH: usize = DISP_WIDTH / BLK_SIZE; pub const GRID_WIDTH: usize = DISP_WIDTH / BLK_SIZE;
pub const GRID_HEIGHT: usize = DISP_HEIGHT / BLK_SIZE; pub const GRID_HEIGHT: usize = DISP_HEIGHT / BLK_SIZE;
/** Array for representing an image of the entire screen.
* This is an array of DISP_WIDTH / 2 × DISP_HEIGHT, each two horizontally consecutive
* pixels are encoded in a u32 with `(a << 16)|b`.
*/
pub type ScreenImage = [u32; DISP_WIDTH * DISP_HEIGHT / 2]; pub type ScreenImage = [u32; DISP_WIDTH * DISP_HEIGHT / 2];
/** Universe abstraction */
struct Universe { struct Universe {
state: [[bool; GRID_WIDTH*GRID_HEIGHT]; 2], state: [[bool; GRID_WIDTH*GRID_HEIGHT]; 2],
cur: usize, cur: usize,
} }
impl Universe { impl Universe {
/** Create a new universe */
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
state: [[false; GRID_WIDTH*GRID_HEIGHT]; 2], state: [[false; GRID_WIDTH*GRID_HEIGHT]; 2],
@ -38,14 +44,17 @@ impl Universe {
} }
} }
/** Get status of a cell */
pub fn get(&self, x: usize, y: usize) -> bool { pub fn get(&self, x: usize, y: usize) -> bool {
self.state[self.cur][y * GRID_WIDTH + x] self.state[self.cur][y * GRID_WIDTH + x]
} }
/** Set status of a cell */
pub fn set(&mut self, x: usize, y: usize, state: bool) { pub fn set(&mut self, x: usize, y: usize, state: bool) {
self.state[self.cur][y * GRID_WIDTH + x] = state; self.state[self.cur][y * GRID_WIDTH + x] = state;
} }
/** Toggle a cell dead/alive */
pub fn toggle(&mut self, x: usize, y: usize) { pub fn toggle(&mut self, x: usize, y: usize) {
self.state[self.cur][y * GRID_WIDTH + x] ^= true; self.state[self.cur][y * GRID_WIDTH + x] ^= true;
} }
@ -96,16 +105,16 @@ impl Universe {
/** Connect pins to internal functions */ /** Connect pins to internal functions */
fn io_mux_init() { fn io_mux_init() {
/* Init SPI IO map and function settings */ /* Init SPI IO map and function settings */
fpioa::set_function(37, fpioa::function::gpiohs(lcd::RST_GPIONUM)); fpioa::set_function(io::LCD_RST.into(), fpioa::function::gpiohs(lcd::RST_GPIONUM));
fpioa::set_io_pull(37, fpioa::pull::DOWN); // outputs must be pull-down fpioa::set_io_pull(io::LCD_RST.into(), fpioa::pull::DOWN); // outputs must be pull-down
fpioa::set_function(38, fpioa::function::gpiohs(lcd::DCX_GPIONUM)); fpioa::set_function(io::LCD_DC.into(), fpioa::function::gpiohs(lcd::DCX_GPIONUM));
fpioa::set_io_pull(38, fpioa::pull::DOWN); fpioa::set_io_pull(io::LCD_DC.into(), fpioa::pull::DOWN);
fpioa::set_function(36, fpioa::function::SPI0_SS3); fpioa::set_function(io::LCD_CS.into(), fpioa::function::SPI0_SS3);
fpioa::set_function(39, fpioa::function::SPI0_SCLK); fpioa::set_function(io::LCD_WR.into(), fpioa::function::SPI0_SCLK);
/* I2C0 for touch-screen */ /* I2C0 for touch-screen */
fpioa::set_function(30, fpioa::function::I2C0_SCLK); fpioa::set_function(io::I2C1_SCL.into(), fpioa::function::I2C0_SCLK);
fpioa::set_function(31, fpioa::function::I2C0_SDA); fpioa::set_function(io::I2C1_SDA.into(), fpioa::function::I2C0_SDA);
sysctl::set_spi0_dvp_data(true); sysctl::set_spi0_dvp_data(true);
} }
@ -119,14 +128,14 @@ fn io_set_power() {
/** How to show a block */ /** How to show a block */
pub static BLOCK_SPRITE: [[u32; 4];8] = [ pub static BLOCK_SPRITE: [[u32; 4];8] = [
[0x28852885, 0x28852885, 0x28852885, 0x28852885], [0x38c738c7, 0x38c738c7, 0x38c738c7, 0x38c738c7],
[0x2885512a, 0x512a512a, 0x512a512a, 0x512a2885], [0x38c7718e, 0x718e718e, 0x718e718e, 0x718e38c7],
[0x2885512a, 0x79af79af, 0x79af79af, 0x512a2885], [0x38c7718e, 0xaa55aa55, 0xaa55aa55, 0x718e38c7],
[0x2885512a, 0x79afaa55, 0xaa5579af, 0x512a2885], [0x38c7718e, 0xaa55e31c, 0xe31caa55, 0x718e38c7],
[0x2885512a, 0x79afaa55, 0xaa5579af, 0x512a2885], [0x38c7718e, 0xaa55e31c, 0xe31caa55, 0x718e38c7],
[0x2885512a, 0x79af79af, 0x79af79af, 0x512a2885], [0x38c7718e, 0xaa55aa55, 0xaa55aa55, 0x718e38c7],
[0x2885512a, 0x512a512a, 0x512a512a, 0x512a2885], [0x38c7718e, 0x718e718e, 0x718e718e, 0x718e38c7],
[0x28852885, 0x28852885, 0x28852885, 0x28852885], [0x38c738c7, 0x38c738c7, 0x38c738c7, 0x38c738c7],
]; ];
#[entry] #[entry]
@ -174,11 +183,11 @@ fn main() -> ! {
universe.set(GRID_WIDTH/2+1, GRID_HEIGHT/2+1, true); universe.set(GRID_WIDTH/2+1, GRID_HEIGHT/2+1, true);
loop { loop {
if let Some(ev) = filter.poll() { if let Some(ev) = filter.poll() {
// writeln!(stdout, "{:?}", ev).unwrap(); //writeln!(stdout, "{:?}", ev).unwrap();
let x = ev.x / (BLK_SIZE as i32); let x = ev.x / (BLK_SIZE as i32);
let y = ev.y / (BLK_SIZE as i32); let y = ev.y / (BLK_SIZE as i32);
// Determine radius of changed area from pressure // Determine radius of changed area from pressure
let r = ev.z / 300; let r = (ev.z / 300) + 1;
for yi in y-r..y+r+1 { for yi in y-r..y+r+1 {
for xi in x-r..x+r+1 { for xi in x-r..x+r+1 {
if (xi as usize) < DISP_WIDTH && (yi as usize) < DISP_HEIGHT { if (xi as usize) < DISP_WIDTH && (yi as usize) < DISP_HEIGHT {

View File

@ -15,6 +15,7 @@ mod palette_xterm256;
use k210_hal::pac; use k210_hal::pac;
use k210_hal::prelude::*; use k210_hal::prelude::*;
use k210_hal::stdout::Stdout; use k210_hal::stdout::Stdout;
use k210_shared::board::def::io;
use k210_shared::board::lcd; use k210_shared::board::lcd;
use k210_shared::board::lcd_colors; use k210_shared::board::lcd_colors;
use k210_shared::soc::fpioa; use k210_shared::soc::fpioa;
@ -28,12 +29,12 @@ use crate::palette_xterm256::PALETTE;
/** Connect pins to internal functions */ /** Connect pins to internal functions */
fn io_mux_init() { fn io_mux_init() {
/* Init SPI IO map and function settings */ /* Init SPI IO map and function settings */
fpioa::set_function(37, fpioa::function::gpiohs(lcd::RST_GPIONUM)); fpioa::set_function(io::LCD_RST.into(), fpioa::function::gpiohs(lcd::RST_GPIONUM));
fpioa::set_io_pull(37, fpioa::pull::DOWN); // outputs must be pull-down fpioa::set_io_pull(io::LCD_RST.into(), fpioa::pull::DOWN); // outputs must be pull-down
fpioa::set_function(38, fpioa::function::gpiohs(lcd::DCX_GPIONUM)); fpioa::set_function(io::LCD_DC.into(), fpioa::function::gpiohs(lcd::DCX_GPIONUM));
fpioa::set_io_pull(38, fpioa::pull::DOWN); fpioa::set_io_pull(io::LCD_DC.into(), fpioa::pull::DOWN);
fpioa::set_function(36, fpioa::function::SPI0_SS3); fpioa::set_function(io::LCD_CS.into(), fpioa::function::SPI0_SS3);
fpioa::set_function(39, fpioa::function::SPI0_SCLK); fpioa::set_function(io::LCD_WR.into(), fpioa::function::SPI0_SCLK);
sysctl::set_spi0_dvp_data(true); sysctl::set_spi0_dvp_data(true);
} }

View File

@ -1,11 +1,11 @@
/** Global board definitions */ /** Global board definitions for Sipeed Maix Go */
/** Display width in pixels */ /** Display width in pixels */
pub const DISP_WIDTH: usize = 320; pub const DISP_WIDTH: usize = 320;
/** Display height in pixels */ /** Display height in pixels */
pub const DISP_HEIGHT: usize = 240; pub const DISP_HEIGHT: usize = 240;
/** I2C address of NS2009 */ /** I2C address of NS2009 (touch screen sensor) */
pub const NS2009_SLV_ADDR: u16 = 0x48; pub const NS2009_SLV_ADDR: u16 = 0x48;
/** I2C address bits for NS2009 */ /** I2C address bits for NS2009 */
@ -16,3 +16,114 @@ pub const NS2009_CLK: u32 = 100000;
/** Calibration matrix for touch screen */ /** Calibration matrix for touch screen */
pub const NS2009_CAL: [i32; 7] = [65, 5853, -1083592, -4292, -15, 16450115, 65536]; pub const NS2009_CAL: [i32; 7] = [65, 5853, -1083592, -4292, -15, 16450115, 65536];
/** I2C address of MSA300 (accelerometer) */
pub const MSA300_SLV_ADDR: u16 = 0x26;
/** I/O pins for FPIOA */
#[derive(Copy, Clone)]
#[repr(u32)]
pub enum io {
/** JTAG TCK */
JTAG_TCK = 0,
/** JTAG TDI */
JTAG_TDI = 1,
/** JTAG TMS */
JTAG_TMS = 2,
/** JTAG TDO */
JTAG_TDO = 3,
/** Host RX (from STM32F103C8) */
ISP_RX = 4,
/** Host TX (to STM32F103C8) */
ISP_TX = 5,
/** WIFI serial TX (to ESP8285) */
WIFI_TX = 6,
/** WIFI serial RX (from ESP8285) */
WIFI_RX = 7,
/** WIFI enable (to ESP8285) */
WIFI_EN = 8,
/** Unused */
BPSK_P = 9,
/** Unused */
BPSK_N = 10,
/** General purpose I/O pin */
IO11 = 11,
/** Blue led (output) */
LED_B = 12,
/** Green led (output) */
LED_G = 13,
/** Red led (output) */
LED_R = 14,
/** Key direction 1 press (input) */
KEY1 = 15,
/** Key center press (input) */
BOOT_KEY0 = 16,
/** Key direction 2 press (input) */
KEY2 = 17,
/** Microphone I2S BCK */
MIC_BCK = 18,
/** Microphone I2S WS */
MIC_WS = 19,
/** Microphone I2S DAT3 */
MIC_DAT3 = 20,
/** Microphone I2S DAT2 */
MIC_DAT2 = 21,
/** Microphone I2S DAT1 */
MIC_DAT1 = 22,
/** Microphone I2S DAT0 */
MIC_DAT0 = 23,
/** Microphone LED DAT */
MIC_LED_DAT = 24,
/** Microphone LED CLK */
MIC_LED_CLK = 25,
/** SDCARD SPI MISO */
SPI0_MISO = 26,
/** SDCARD SPI SCLK */
SPI0_SCLK = 27,
/** SDCARD SPI MOSI */
SPI0_MOSI = 28,
/** SDCARD SPI CS */
SPI0_CS0 = 29,
/** I2C bus 1 SCLK (NS2009, MSA300) */
I2C1_SCL = 30,
/** I2C bus 2 SDA (NS2009, MSA300) */
I2C1_SDA = 31,
/** General purpose I/O pin */
IO32 = 32,
/** DAC I2S WS */
I2S_WS = 33,
/** DAC I2S DA */
I2S_DA = 34,
/** DAC I2S BCK */
I2S_BCK = 35,
/** LCD chip select (output) */
LCD_CS = 36,
/** LCD reset (output) */
LCD_RST = 37,
/** LCD Data/Command */
LCD_DC = 38,
/** LCD SPI SCLK */
LCD_WR = 39,
/** Camera DVP SDA */
DVP_SDA = 40,
/** Camera DVP SCL */
DVP_SCL = 41,
/** Camera DVP RST */
DVP_RST = 42,
/** Camera DVP VSYNC */
DVP_VSYNC = 43,
/** Camera DVP PWDN */
DVP_PWDN = 44,
/** Camera DVP HSYNC */
DVP_HSYNC = 45,
/** Camera DVP XCLK */
DVP_XCLK = 46,
/** Camera DVP PCLK */
DVP_PCLK = 47,
}
impl From<io> for u8 {
fn from(io: io) -> Self {
io as u8
}
}

View File

@ -3,7 +3,17 @@ use core::result::Result;
use crate::soc::i2c; use crate::soc::i2c;
use crate::util::filters; use crate::util::filters;
/** Touch event will trigger at a z1 value higher than this (lower values regarded as noise)
*/
const TOUCH_THR_MIN: u16 = 80;
/** Touch event will no longer trigger at a z1 value higher than this (higher values regarded as
* noise)
*/
const TOUCH_THR_MAX: u16 = 2000;
/* low level functions */ /* low level functions */
/** NS2009 commands. */
#[repr(u8)] #[repr(u8)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum command { pub enum command {
@ -13,6 +23,7 @@ pub enum command {
LOW_POWER_READ_Z2 = 0xf0, LOW_POWER_READ_Z2 = 0xf0,
} }
/** Read a 12-bit value. */
pub fn read(cmd: command) -> Result<u16, ()> pub fn read(cmd: command) -> Result<u16, ()>
{ {
let mut buf = [0u8; 2]; let mut buf = [0u8; 2];
@ -23,6 +34,8 @@ pub fn read(cmd: command) -> Result<u16, ()>
} }
} }
/* high level functions */
/** Position filter */ /** Position filter */
pub struct TSFilter { pub struct TSFilter {
mx: filters::Median<i32>, mx: filters::Median<i32>,
@ -106,7 +119,7 @@ impl TouchScreen {
pub fn poll(&mut self) -> Option<Event> { pub fn poll(&mut self) -> Option<Event> {
let mut ev: Option<Event> = None; let mut ev: Option<Event> = None;
if let Ok(z1) = read(command::LOW_POWER_READ_Z1) { if let Ok(z1) = read(command::LOW_POWER_READ_Z1) {
if z1 > 80 && z1 < 2000 { if z1 > TOUCH_THR_MIN && z1 < TOUCH_THR_MAX {
if let (Ok(x), Ok(y)) = (read(command::LOW_POWER_READ_X), read(command::LOW_POWER_READ_Y)) { if let (Ok(x), Ok(y)) = (read(command::LOW_POWER_READ_X), read(command::LOW_POWER_READ_Y)) {
let (x, y) = self.filter.update(x, y); let (x, y) = self.filter.update(x, y);
if !self.press if !self.press

View File

@ -349,7 +349,7 @@ static FUNCTION_DEFAULTS: &[u32] = &[
0x00001ff8, 0x00001ff9, 0x00001ffa, 0x00001ffb, 0x00001ffc, 0x00001ffd, 0x00001ffe, 0x00001fff, 0x00001ff8, 0x00001ff9, 0x00001ffa, 0x00001ffb, 0x00001ffc, 0x00001ffd, 0x00001ffe, 0x00001fff,
]; ];
pub fn set_function(number: u32, function: function) { pub fn set_function(number: u8, function: function) {
// TODO: check for overlapping assignments and assign to RESV0 as the Kendryte SDK does? // TODO: check for overlapping assignments and assign to RESV0 as the Kendryte SDK does?
unsafe { unsafe {
let ptr = pac::FPIOA::ptr(); let ptr = pac::FPIOA::ptr();
@ -357,7 +357,7 @@ pub fn set_function(number: u32, function: function) {
} }
} }
pub fn set_io_pull(number: u32, pull: pull) { pub fn set_io_pull(number: u8, pull: pull) {
unsafe { unsafe {
(*pac::FPIOA::ptr()).io[number as usize].modify(|_, w| match pull { (*pac::FPIOA::ptr()).io[number as usize].modify(|_, w| match pull {
pull::NONE => w.pu().bit(false).pd().bit(false), pull::NONE => w.pu().bit(false).pd().bit(false),

View File

@ -11,6 +11,7 @@ mod palette;
use k210_hal::pac; use k210_hal::pac;
use k210_hal::prelude::*; use k210_hal::prelude::*;
use k210_hal::stdout::Stdout; use k210_hal::stdout::Stdout;
use k210_shared::board::def::{io,DISP_WIDTH,DISP_HEIGHT};
use k210_shared::board::lcd; use k210_shared::board::lcd;
use k210_shared::board::lcd_colors; use k210_shared::board::lcd_colors;
use k210_shared::soc::fpioa; use k210_shared::soc::fpioa;
@ -20,20 +21,17 @@ use riscv_rt::entry;
use crate::palette::PALETTE; use crate::palette::PALETTE;
pub const DISP_WIDTH: usize = 320;
pub const DISP_HEIGHT: usize = 240;
pub type ScreenImage = [u32; DISP_WIDTH * DISP_HEIGHT / 2]; pub type ScreenImage = [u32; DISP_WIDTH * DISP_HEIGHT / 2];
/** Connect pins to internal functions */ /** Connect pins to internal functions */
fn io_mux_init() { fn io_mux_init() {
/* Init SPI IO map and function settings */ /* Init SPI IO map and function settings */
fpioa::set_function(37, fpioa::function::gpiohs(lcd::RST_GPIONUM)); fpioa::set_function(io::LCD_RST.into(), fpioa::function::gpiohs(lcd::RST_GPIONUM));
fpioa::set_io_pull(37, fpioa::pull::DOWN); // outputs must be pull-down fpioa::set_io_pull(io::LCD_RST.into(), fpioa::pull::DOWN); // outputs must be pull-down
fpioa::set_function(38, fpioa::function::gpiohs(lcd::DCX_GPIONUM)); fpioa::set_function(io::LCD_DC.into(), fpioa::function::gpiohs(lcd::DCX_GPIONUM));
fpioa::set_io_pull(38, fpioa::pull::DOWN); fpioa::set_io_pull(io::LCD_DC.into(), fpioa::pull::DOWN);
fpioa::set_function(36, fpioa::function::SPI0_SS3); fpioa::set_function(io::LCD_CS.into(), fpioa::function::SPI0_SS3);
fpioa::set_function(39, fpioa::function::SPI0_SCLK); fpioa::set_function(io::LCD_WR.into(), fpioa::function::SPI0_SCLK);
sysctl::set_spi0_dvp_data(true); sysctl::set_spi0_dvp_data(true);
} }