Implement keypad support with sx1509
This commit is contained in:
parent
03f560b2c1
commit
4a3a88f0c0
43
src/main.rs
43
src/main.rs
@ -141,25 +141,25 @@ fn main() -> ! {
|
|||||||
);
|
);
|
||||||
|
|
||||||
sx1509.init().unwrap();
|
sx1509.init().unwrap();
|
||||||
sx1509.set_pin_dir(0, sx1509::PinDirection::Output, false);
|
sx1509.keypad(3, 4, 256, 2, 1);
|
||||||
sx1509.set_pin_dir(1, sx1509::PinDirection::InputPullUp, false);
|
|
||||||
sx1509.set_pin_dir(2, sx1509::PinDirection::Output, false);
|
|
||||||
sx1509.set_pin_dir(3, sx1509::PinDirection::InputPullUp, false);
|
|
||||||
sx1509.set_pin_dir(4, sx1509::PinDirection::Output, false);
|
|
||||||
sx1509.set_pin_dir(5, sx1509::PinDirection::InputPullUp, false);
|
|
||||||
sx1509.set_pin_dir(6, sx1509::PinDirection::InputPullUp, false);
|
|
||||||
|
|
||||||
let delay = Delay::new();
|
let delay = Delay::new();
|
||||||
|
|
||||||
|
let keypad = [
|
||||||
|
['2', '1', '3'],
|
||||||
|
['0', '*', '#'],
|
||||||
|
['8', '7', '9'],
|
||||||
|
['5', '4', '6'],
|
||||||
|
];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
delay.delay_millis(500);
|
delay.delay_millis(500);
|
||||||
sx1509.write_pin(0, true);
|
let keypad_data = sx1509.read_keypad();
|
||||||
log::info!("Pin 1: {:?}", sx1509.read_pin(1));
|
let row = bit_representation_to_number(((keypad_data & 0xFF00) >> 8) as u8) as usize;
|
||||||
log::info!("Pin 3: {:?}", sx1509.read_pin(3));
|
let col = bit_representation_to_number((keypad_data & 0xFF) as u8) as usize;
|
||||||
log::info!("Pin 5: {:?}", sx1509.read_pin(5));
|
if row > 0 && col > 0 {
|
||||||
log::info!("Pin 6: {:?}", sx1509.read_pin(6));
|
log::info!("Key data: {}", keypad[row - 1][col - 1]);
|
||||||
|
}
|
||||||
sx1509.write_pin(0, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// let mut at_commands = ATCommands::new(sim_rst, sim_pwr_key, uart);
|
// let mut at_commands = ATCommands::new(sim_rst, sim_pwr_key, uart);
|
||||||
@ -230,3 +230,18 @@ fn thread_2_main(async_io: AsyncIO, mut at_commands: ATCommands<'static, 'static
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bit_representation_to_number(byte: u8) -> u8 {
|
||||||
|
match byte {
|
||||||
|
0b00000000 => 0,
|
||||||
|
0b00000001 => 1,
|
||||||
|
0b00000010 => 2,
|
||||||
|
0b00000100 => 3,
|
||||||
|
0b00001000 => 4,
|
||||||
|
0b00010000 => 5,
|
||||||
|
0b00100000 => 6,
|
||||||
|
0b01000000 => 7,
|
||||||
|
0b10000000 => 8,
|
||||||
|
_ => 255,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
138
src/sx1509.rs
138
src/sx1509.rs
@ -1,14 +1,36 @@
|
|||||||
use esp_hal::{Blocking, delay::Delay, gpio::Output, i2c::master::I2c};
|
use esp_hal::{Blocking, delay::Delay, gpio::Output, i2c::master::I2c};
|
||||||
|
|
||||||
pub enum Register {
|
pub enum Register {
|
||||||
|
/// RegPullUpB Pull_up register _ I/O[15_8] (Bank B) 0000 0000
|
||||||
RegPullUpB = 0x6,
|
RegPullUpB = 0x6,
|
||||||
|
/// RegPullDownB Pull_down register _ I/O[15_8] (Bank B) 0000 0000
|
||||||
RegPullDownB = 0x8,
|
RegPullDownB = 0x8,
|
||||||
|
/// RegOpenDrainA Open drain register _ I/O[7_0] (Bank A) 0000 0000
|
||||||
|
RegOpenDrainA = 0x0B,
|
||||||
|
/// RegDirB Direction register _ I/O[15_8] (Bank B) 1111 1111
|
||||||
RegDirB = 0x0E,
|
RegDirB = 0x0E,
|
||||||
|
/// RegDataB Data register _ I/O[15_8] (Bank B) 1111 1111*
|
||||||
RegDataB = 0x10,
|
RegDataB = 0x10,
|
||||||
|
|
||||||
|
/// RegInterruptMaskA Interrupt mask register _ I/O[7_0] (Bank A) 1111 1111
|
||||||
RegInterruptMaskA = 0x13,
|
RegInterruptMaskA = 0x13,
|
||||||
|
|
||||||
|
/// RegClock Clock management register 0000 0000
|
||||||
|
RegClock = 0x1E,
|
||||||
|
/// RegMisc Miscellaneous device settings register 0000 0000
|
||||||
RegMisc = 0x1F,
|
RegMisc = 0x1F,
|
||||||
|
|
||||||
|
/// RegDebounceEnableB Debounce enable register _ I/O[15_8] (Bank B) 0000 0000
|
||||||
|
RegDebounceEnableB = 0x23,
|
||||||
|
/// RegDebounceConfig Debounce configuration register 0000 0000
|
||||||
|
RegDebounceConfig = 0x22,
|
||||||
|
|
||||||
|
/// RegKeyConfig1 Key scan configuration register 0000 0000
|
||||||
|
RegKeyConfig1 = 0x25,
|
||||||
|
/// RegKeyConfig2 Key scan configuration register 0000 0000
|
||||||
|
RegKeyConfig2 = 0x26,
|
||||||
|
/// RegKeyData1 Key value (column) 1111 1111
|
||||||
|
RegKeyData1 = 0x27,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
@ -168,5 +190,121 @@ impl<'d> Sx1509<'d> {
|
|||||||
scan_time: u16,
|
scan_time: u16,
|
||||||
debounce_time: u8,
|
debounce_time: u8,
|
||||||
) {
|
) {
|
||||||
|
// Set regDir 0:7 outputs, 8:15 inputs:
|
||||||
|
let mut temp_dir = self.read_16(Register::RegDirB);
|
||||||
|
for i in 0..rows {
|
||||||
|
temp_dir &= !(1 << i);
|
||||||
|
}
|
||||||
|
for i in 8..(columns * 2) {
|
||||||
|
temp_dir |= 1 << i;
|
||||||
|
}
|
||||||
|
self.write_16(Register::RegDirB, temp_dir);
|
||||||
|
|
||||||
|
// Set regOpenDrain on 0:7:
|
||||||
|
let mut temp_open_drain = self.read_8(Register::RegOpenDrainA);
|
||||||
|
for i in 0..rows {
|
||||||
|
temp_open_drain |= 1 << i;
|
||||||
|
}
|
||||||
|
self.write_8(Register::RegOpenDrainA, temp_open_drain);
|
||||||
|
|
||||||
|
// Set regPullUp on 8:15:
|
||||||
|
let mut temp_pull_up = self.read_8(Register::RegPullUpB);
|
||||||
|
for i in 0..columns {
|
||||||
|
temp_pull_up |= 1 << i;
|
||||||
|
}
|
||||||
|
self.write_8(Register::RegPullUpB, temp_pull_up);
|
||||||
|
|
||||||
|
let mut debounce_time = debounce_time.clamp(1, 64);
|
||||||
|
let scan_time = scan_time.clamp(1, 128);
|
||||||
|
if debounce_time as u16 >= scan_time {
|
||||||
|
debounce_time = (scan_time >> 1) as u8;
|
||||||
|
}
|
||||||
|
self.debounce_keypad(debounce_time, rows, columns);
|
||||||
|
|
||||||
|
let mut scan_time_bits = 0u8;
|
||||||
|
for i in 7..0 {
|
||||||
|
if (scan_time & (1 << i)) > 0 {
|
||||||
|
scan_time_bits = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sleep_time_bits = 0u8;
|
||||||
|
if sleep_time != 0 {
|
||||||
|
for i in 7..0 {
|
||||||
|
if (sleep_time & (1u16 << i + 6)) > 0 {
|
||||||
|
sleep_time_bits = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If sleepTime was non-zero, but less than 128,
|
||||||
|
// assume we wanted to turn sleep on, set it to minimum:
|
||||||
|
if sleep_time_bits == 0 {
|
||||||
|
sleep_time_bits = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegKeyConfig1 sets the auto sleep time and scan time per row
|
||||||
|
let sleep_time_bits = (sleep_time_bits & 0b111) << 4;
|
||||||
|
scan_time_bits &= 0b111; // Scan time is bits 2:0
|
||||||
|
self.write_8(
|
||||||
|
Register::RegKeyConfig1,
|
||||||
|
// TODO: Was incorrectly sleep_time
|
||||||
|
sleep_time_bits as u8 | scan_time_bits,
|
||||||
|
);
|
||||||
|
|
||||||
|
let rows = (rows - 1) & 0b111;
|
||||||
|
let columns = (columns - 1) & 0b111;
|
||||||
|
self.write_8(Register::RegKeyConfig2, (rows << 3) | columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debounce_keypad(&mut self, debounce_time: u8, rows: u8, columns: u8) {
|
||||||
|
self.debounce_time(debounce_time);
|
||||||
|
|
||||||
|
for i in 0..rows {
|
||||||
|
self.debounce_pin(i);
|
||||||
|
}
|
||||||
|
for i in 0..(8 + columns) {
|
||||||
|
self.debounce_pin(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debounce_time(&mut self, debounce_time: u8) {
|
||||||
|
let mut config_value = 0u8;
|
||||||
|
for i in 7..0 {
|
||||||
|
if (debounce_time & (1 << i)) > 0 {
|
||||||
|
config_value = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config_value = config_value.clamp(0, 7);
|
||||||
|
self.debounce_config(config_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debounce_pin(&mut self, pin: u8) {
|
||||||
|
let mut debounce_enable = self.read_16(Register::RegDebounceEnableB);
|
||||||
|
debounce_enable |= 1 << pin;
|
||||||
|
self.write_16(Register::RegDebounceEnableB, debounce_enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debounce_config(&mut self, config: u8) {
|
||||||
|
let mut temp_reg_misc = self.read_8(Register::RegMisc);
|
||||||
|
if (temp_reg_misc & 0x70) == 0 {
|
||||||
|
temp_reg_misc |= 1 << 4;
|
||||||
|
self.write_8(Register::RegMisc, temp_reg_misc);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut temp_clock = self.read_8(Register::RegClock);
|
||||||
|
if (temp_clock & 0x60) == 0 {
|
||||||
|
temp_clock |= 1 << 6;
|
||||||
|
self.write_8(Register::RegClock, temp_clock);
|
||||||
|
}
|
||||||
|
|
||||||
|
let config_value = config & 0b111;
|
||||||
|
self.write_8(Register::RegDebounceConfig, config_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_keypad(&mut self) -> u16 {
|
||||||
|
0xFFFF ^ self.read_16(Register::RegKeyData1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user