spi: Simplify all reg reads/writes as rw_n()

This commit is contained in:
Harry Ho 2021-06-02 17:03:35 +08:00
parent 27ba42c4fb
commit d05d7f91e2
1 changed files with 45 additions and 69 deletions

View File

@ -91,30 +91,35 @@ impl <SPI: Transfer<u8>,
pub fn read_reg_8b(&mut self, addr: u8) -> Result<u8, Error> { pub fn read_reg_8b(&mut self, addr: u8) -> Result<u8, Error> {
// Using RCRU instruction to read using unbanked (full) address // Using RCRU instruction to read using unbanked (full) address
let r_data = self.rw_addr_u8(opcodes::RCRU, addr, 0)?; let mut buf: [u8; 4] = [0; 4];
Ok(r_data) buf[1] = addr;
self.rw_n(&mut buf, opcodes::RCRU, 2)?;
Ok(buf[2])
} }
pub fn read_reg_16b(&mut self, lo_addr: u8) -> Result<u16, Error> { pub fn read_reg_16b(&mut self, lo_addr: u8) -> Result<u16, Error> {
// Unless the register can be written with specific opcode,
// use WCRU instruction to write using unbanked (full) address
let mut buf: [u8; 4] = [0; 4];
let mut data_offset = 0; // number of bytes separating
// actual data from opcode
match lo_addr { match lo_addr {
addrs::ERXRDPT | addrs::EGPWRPT => { addrs::ERXRDPT | addrs::EGPWRPT => { }
let mut buf: [u8; 3] = [0; 3]; _ => {
buf[1] = lo_addr;
data_offset = 1;
}
}
self.rw_n( self.rw_n(
&mut buf, match lo_addr { &mut buf,
match lo_addr {
addrs::ERXRDPT => opcodes::RRXRDPT, addrs::ERXRDPT => opcodes::RRXRDPT,
addrs::EGPWRPT => opcodes::RGPWRPT, addrs::EGPWRPT => opcodes::RGPWRPT,
_ => unreachable!() _ => opcodes::RCRU
}, 2 },
2 + data_offset // extra 8-bit lo_addr before data
)?; )?;
Ok((buf[2] as u16) << 8 | buf[1] as u16) Ok(buf[data_offset+1] as u16 | (buf[data_offset+2] as u16) << 8)
}
_ => {
let r_data_lo = self.read_reg_8b(lo_addr)?;
let r_data_hi = self.read_reg_8b(lo_addr + 1)?;
// Combine top and bottom 8-bit to return 16-bit
Ok(((r_data_hi as u16) << 8) | r_data_lo as u16)
}
}
} }
// Currently requires manual slicing (buf[1..]) for the data read back // Currently requires manual slicing (buf[1..]) for the data read back
@ -131,33 +136,38 @@ impl <SPI: Transfer<u8>,
} }
pub fn write_reg_8b(&mut self, addr: u8, data: u8) -> Result<(), Error> { pub fn write_reg_8b(&mut self, addr: u8, data: u8) -> Result<(), Error> {
// TODO: addr should be separated from w_data
// Using WCRU instruction to write using unbanked (full) address // Using WCRU instruction to write using unbanked (full) address
self.rw_addr_u8(opcodes::WCRU, addr, data)?; let mut buf: [u8; 3] = [0; 3];
Ok(()) buf[1] = addr;
buf[2] = data;
self.rw_n(&mut buf, opcodes::WCRU, 2)
} }
pub fn write_reg_16b(&mut self, lo_addr: u8, data: u16) -> Result<(), Error> { pub fn write_reg_16b(&mut self, lo_addr: u8, data: u16) -> Result<(), Error> {
// Unless the register can be written with specific opcode,
// use WCRU instruction to write using unbanked (full) address
let mut buf: [u8; 4] = [0; 4];
let mut data_offset = 0; // number of bytes separating
// actual data from opcode
match lo_addr { match lo_addr {
addrs::ERXRDPT | addrs::EGPWRPT => { addrs::ERXRDPT | addrs::EGPWRPT => { }
let mut buf: [u8; 3] = [0; 3]; _ => {
buf[1] = data as u8 & 8; buf[1] = lo_addr;
buf[2] = (data >> 8) as u8 & 8; data_offset = 1;
}
}
buf[1+data_offset] = data as u8;
buf[2+data_offset] = (data >> 8) as u8;
self.rw_n( self.rw_n(
&mut buf, match lo_addr { &mut buf,
match lo_addr {
addrs::ERXRDPT => opcodes::WRXRDPT, addrs::ERXRDPT => opcodes::WRXRDPT,
addrs::EGPWRPT => opcodes::WGPWRPT, addrs::EGPWRPT => opcodes::WGPWRPT,
_ => unreachable!() _ => opcodes::WCRU
}, 2 },
2 + data_offset // extra 8-bit lo_addr before data
) )
} }
_ => {
self.write_reg_8b(lo_addr, (data & 0xff) as u8)?;
self.write_reg_8b(lo_addr + 1, ((data & 0xff00) >> 8) as u8)?;
Ok(())
}
}
}
pub fn send_opcode(&mut self, opcode: u8) -> Result<(), Error> { pub fn send_opcode(&mut self, opcode: u8) -> Result<(), Error> {
match opcode { match opcode {
@ -174,40 +184,6 @@ impl <SPI: Transfer<u8>,
(self.delay_ns)(duration * 1000) (self.delay_ns)(duration * 1000)
} }
// TODO: Generalise transfer functions
// Completes an SPI transfer for reading or writing 8-bit data,
// and returns the data read/written.
// It starts with an 8-bit instruction, followed by an 8-bit address.
fn rw_addr_u8(&mut self, opcode: u8, addr: u8, data: u8)
-> Result<u8, Error> {
// Enable chip select
self.nss.set_low();
// Start writing to SLAVE
// TODO: don't just use 3 bytes
let mut buf: [u8; 3] = [0; 3];
buf[0] = opcode;
buf[1] = addr;
buf[2] = data;
match self.spi.transfer(&mut buf) {
Ok(_) => {
// Disable chip select
(self.delay_ns)(60);
self.nss.set_high();
(self.delay_ns)(30);
Ok(buf[2])
},
// TODO: Maybe too naive?
Err(_) => {
// Disable chip select
(self.delay_ns)(60);
self.nss.set_high();
(self.delay_ns)(30);
Err(Error::TransferError)
}
}
}
// TODO: Generalise transfer functions
// TODO: Actual data should start from buf[0], not buf[1] // TODO: Actual data should start from buf[0], not buf[1]
// Completes an SPI transfer for reading data to the given buffer, // Completes an SPI transfer for reading data to the given buffer,
// or writing data from the buffer. // or writing data from the buffer.