extern crate i2cdev;
use std;
use std::time::Duration;
use super::devices::I2CMasterDevice;
pub const DEFAULT_TRELLIS_ADDR: u16 = 0x70;
const NUM_LEDS: usize = 16;
type LedVec = [bool; NUM_LEDS];
static LED_ADDRESSES : [u8; NUM_LEDS] = [
0x3A, 0x37, 0x35, 0x34,
0x28, 0x29, 0x23, 0x24,
0x16, 0x1B, 0x11, 0x10,
0x0E, 0x0D, 0x0C, 0x02
];
static BUTTON_ADDRESSES : [u8; NUM_LEDS] = [
0x07, 0x04, 0x02, 0x22,
0x05, 0x06, 0x00, 0x01,
0x03, 0x10, 0x30, 0x21,
0x13, 0x12, 0x11, 0x31
];
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum Col {
A, B, C, D
}
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum Row {
R0, R1, R2, R3
}
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct LedButton {
pub col: Col,
pub row: Row
}
#[derive(Debug)]
pub struct ButtonEvent {
pub buttons_pressed: Vec<LedButton>
}
impl ButtonEvent {
pub fn empty() -> ButtonEvent {
return ButtonEvent{buttons_pressed: vec![]}
}
}
pub type EventLoopHandler = Box<FnMut(&mut Trellis, ButtonEvent) -> bool>;
fn row_to_num(row: Row) -> u8 {
match row {
Row::R0 => 0,
Row::R1 => 1,
Row::R2 => 2,
Row::R3 => 3
}
}
fn num_to_row(num: usize) -> Row {
match num {
0 => Row::R0,
1 => Row::R1,
2 => Row::R2,
3 => Row::R3,
_ => panic!("illegal row")
}
}
fn col_to_num(col: Col) -> u8 {
match col {
Col::A => 0,
Col::B => 1,
Col::C => 2,
Col::D => 3,
}
}
fn num_to_col(num: usize) -> Col {
match num {
0 => Col::A,
1 => Col::B,
2 => Col::C,
3 => Col::D,
_ => panic!("illegal column")
}
}
fn num_to_led_button(num: usize) -> LedButton {
let col_num = num % 4;
let row_num = num / 4;
return LedButton{col: num_to_col(col_num), row: num_to_row(row_num)};
}
fn led_index(col:Col, row:Row) -> usize {
return (row_to_num(row)*4 + col_to_num(col)) as usize;
}
fn to_button_state(dev_data: Vec<u8>) -> LedVec {
let mut result = [false; NUM_LEDS];
for i in 0..NUM_LEDS {
let addr = BUTTON_ADDRESSES[i];
result[i] = (dev_data[(addr >> 4) as usize] & (1 << (addr & 0x0F))) > 0;
}
return result;
}
fn button_event(old: LedVec, new: LedVec) -> ButtonEvent {
let mut pressed = Vec::new();
for i in 0..NUM_LEDS {
if new[i] && !old[i] {
pressed.push(num_to_led_button(i));
}
}
return ButtonEvent{buttons_pressed:pressed};
}
pub struct Trellis {
display_buffer: LedVec,
button_state: LedVec,
device : Box<I2CMasterDevice>
}
impl Trellis {
pub fn new(dev: Box<I2CMasterDevice>) -> Trellis {
return Trellis { display_buffer: [false; NUM_LEDS],
button_state: [false; NUM_LEDS],
device: dev};
}
pub fn init(&mut self) {
let empty_array:[u8;0] = [];
self.device.write_block(0x21, &empty_array).unwrap();
self.device.write_block(0x80 | 0x01 | 0 << 1, &empty_array).unwrap();
self.device.write_block(0xE0 | 15, &empty_array).unwrap();
self.device.write_block(0xA1, &empty_array).unwrap();
}
pub fn set_led(&mut self, col:Col, row: Row) {
self.display_buffer[led_index(col, row)] = true;
}
pub fn clear_led(&mut self, col:Col, row:Row) {
self.display_buffer[led_index(col, row)] = false;
}
pub fn is_led_set(&mut self, col:Col, row: Row) -> bool {
return self.display_buffer[led_index(col, row)];
}
pub fn write_display(&mut self) {
let mut data:[u16; 8] = [0; 8];
for l in 0..NUM_LEDS {
let led_addr = LED_ADDRESSES[l];
if self.display_buffer[l] {
data[(led_addr >> 4) as usize] |= 1 << (led_addr & 0x0F);
} else {
data[(led_addr >> 4) as usize] &= !(1 << (led_addr & 0x0F));
}
}
let mut w:[u8; 16] = [0; 16];
for i in 0..8 {
w[i*2] = (data[i] & 0xFF) as u8;
w[i*2+1] = (data[i] >> 8) as u8;
}
self.device.write_block(0x0, &w).unwrap();
}
pub fn button_evt_loop(&mut self, mut hnd: EventLoopHandler) {
loop {
let new_button_state = to_button_state(self.device.read_block(0x40, 6).unwrap());
let event = button_event(self.button_state, new_button_state);
self.button_state = new_button_state;
let handler_result = hnd(self, event);
if handler_result {
break;
}
std::thread::sleep(Duration::from_millis(30));
}
}
}