diff --git a/src/main.rs b/src/main.rs index 23726e4..0c8125e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,25 +141,25 @@ fn main() -> ! { ); sx1509.init().unwrap(); - sx1509.set_pin_dir(0, sx1509::PinDirection::Output, false); - 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); + sx1509.keypad(3, 4, 256, 2, 1); let delay = Delay::new(); + let keypad = [ + ['2', '1', '3'], + ['0', '*', '#'], + ['8', '7', '9'], + ['5', '4', '6'], + ]; + loop { delay.delay_millis(500); - sx1509.write_pin(0, true); - log::info!("Pin 1: {:?}", sx1509.read_pin(1)); - log::info!("Pin 3: {:?}", sx1509.read_pin(3)); - log::info!("Pin 5: {:?}", sx1509.read_pin(5)); - log::info!("Pin 6: {:?}", sx1509.read_pin(6)); - - sx1509.write_pin(0, false); + let keypad_data = sx1509.read_keypad(); + let row = bit_representation_to_number(((keypad_data & 0xFF00) >> 8) as u8) as usize; + let col = bit_representation_to_number((keypad_data & 0xFF) as u8) as usize; + if row > 0 && col > 0 { + log::info!("Key data: {}", keypad[row - 1][col - 1]); + } } // 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, + } +} diff --git a/src/sx1509.rs b/src/sx1509.rs index e5e1596..efbe001 100644 --- a/src/sx1509.rs +++ b/src/sx1509.rs @@ -1,14 +1,36 @@ use esp_hal::{Blocking, delay::Delay, gpio::Output, i2c::master::I2c}; pub enum Register { + /// RegPullUpB Pull_up register _ I/O[15_8] (Bank B) 0000 0000 RegPullUpB = 0x6, + /// RegPullDownB Pull_down register _ I/O[15_8] (Bank B) 0000 0000 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, + /// RegDataB Data register _ I/O[15_8] (Bank B) 1111 1111* RegDataB = 0x10, + /// RegInterruptMaskA Interrupt mask register _ I/O[7_0] (Bank A) 1111 1111 RegInterruptMaskA = 0x13, + /// RegClock Clock management register 0000 0000 + RegClock = 0x1E, + /// RegMisc Miscellaneous device settings register 0000 0000 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)] @@ -168,5 +190,121 @@ impl<'d> Sx1509<'d> { scan_time: u16, 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) } }