avremu/src/devices/oscillator.rs

127 lines
2.8 KiB
Rust

// Oscillator
use devices::DeviceImpl;
use slog::Logger;
const OSC_CTRL: u32 = 0;
const OSC_STATUS: u32 = 1;
const OSC_XOSCCTRL: u32 = 2;
const OSC_XOSCFAIL: u32 = 3;
/*
const OSC_RC32KCAL: u32 = 4;
const OSC_PLLCTRL: u32 = 5;
const OSC_DFLLCTRL: u32 = 6;
*/
/*
enum PllSrc {
RC2M,
RC32M,
XOSC,
}
*/
pub struct Oscillator {
log: Logger,
reg_values: [u8; 7],
// Real attributes:
ctrl: u8,
status: u8,
xoscctrl: u8,
/*
xoscfail: u8,
rs32kcal: u8,
pllsrc: PllSrc,
pllfac: u8,
dfllctrl: u8,
*/
}
impl Oscillator {
pub fn new(log: Logger) -> Self {
Self {
log,
reg_values: [0u8; 7],
ctrl: 0,
status: 0,
xoscctrl: 0,
/*
xoscfail: 0,
rs32kcal: 0,
pllsrc: PllSrc::RC2M,
pllfac: 0,
dfllctrl: 0,
*/
}
}
}
impl DeviceImpl for Oscillator {
fn read(&mut self, addr: u32) -> u8 {
match addr {
OSC_CTRL => {
// PLL and clock ready.
return self.ctrl | 0x30;
}
OSC_STATUS => {
return self.status | 0x30;
}
_ => {}
}
self.reg_values[addr as usize]
}
fn write(&mut self, addr: u32, value: u8) {
match addr {
OSC_CTRL => {
info!(self.log, "OSC_CTRL <= {:02X}", value);
self.ctrl = value & 0x1F;
self.status = value & 0x1F;
}
OSC_XOSCCTRL => {
self.xoscctrl = value & 0xEF;
}
OSC_XOSCFAIL => {}
_ => {}
}
self.reg_values[addr as usize] = value;
}
/*
} else if(addr == 0x03) { // XOSCFAIL
XOSCFAIL vreg;
vreg.data = v & 0x03;
// XOSCFDEN
if(!xoscfail_.xoscfden && vreg.xoscfden) {
if(device_->ccpState() & Device::CCP_IOREG) {
xoscfail_.xoscfden = 1;
} else {
LOGF(ERROR, "cannot set XOSCFAIL.XOSCFDEN: protected by CCP");
}
} else if(xoscfail_.xoscfden && !vreg.xoscfden) {
LOGF(ERROR, "XOSCFAIL.XOSCFDEN cannot be cleared");
}
// XOSCFDIF
if(vreg.xoscfdif) {
xoscfail_.xoscfdif = 0;
}
} else if(addr == 0x04) { // RC32KCAL
rc32kcal_ = v;
} else if(addr == 0x05) { // PLLCTRL
if((v >> 6) == 1) {
LOGF(ERROR, "invalid PLLSRC value");
} else {
pllsrc_ = static_cast<PLLSRC>(v >> 6);
}
pllfac_ = v & 0x1F;
} else if(addr == 0x06) { // DFLLCTRL
//TODO no check nor handling is made here
dfllctrl_.data = v & 0x03;
} else {
LOGF(ERROR, "I/O write %s + 0x%02X: not writable") % name() % addr;
}
*/
}