use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use error::{Error, ErrorKind};
use peripherals::consts::*;
use system::System;
use util::mem::RegisterMap;
static RESERVED: AtomicBool = ATOMIC_BOOL_INIT;
pub use peripherals::consts::PWM_CHANNELS;
pub struct Pwm {
registers: RegisterMap,
}
impl Pwm {
pub fn new() -> Result<Pwm, Error> {
if RESERVED.fetch_or(true, Ordering::SeqCst) {
return Err(Error::new(ErrorKind::Reserved));
}
Ok(Pwm {
registers: unsafe { RegisterMap::map(
System::detect()?.peripheral_offset() + PWM_PAGE_OFFSET,
PAGE_SIZE,
)}?,
})
}
pub fn is_valid_channel(channel: usize) -> bool {
channel < PWM_CHANNELS
}
pub fn check_channel(channel: usize) -> Result<(), Error> {
if Pwm::is_valid_channel(channel) {
Ok(())
} else {
Err(Error::new(ErrorKind::OutOfRange))
}
}
pub fn enable(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg |= PWM_CTL_PWEN[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn disable(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg &= !PWM_CTL_PWEN[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn enable_serial(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg |= PWM_CTL_MODE[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn disable_serial(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg &= !PWM_CTL_MODE[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn set_sbit_high(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg |= PWM_CTL_SBIT[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn set_sbit_low(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg &= !PWM_CTL_SBIT[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn set_polarity_inverse(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg |= PWM_CTL_POLA[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn set_polarity_normal(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg &= !PWM_CTL_POLA[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn enable_fifo(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg |= PWM_CTL_USEF[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn disable_fifo(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg &= !PWM_CTL_USEF[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn clear_fifo(&mut self) {
let mut reg = self.registers.load(PWM_CTL);
reg |= PWM_CTL_CLRF1;
self.registers.store(PWM_CTL, reg);
}
pub fn enable_mark_space(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg |= PWM_CTL_MSEN[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn disable_mark_space(&mut self, channel: usize) {
let mut reg = self.registers.load(PWM_CTL);
reg &= !PWM_CTL_MSEN[channel];
self.registers.store(PWM_CTL, reg);
}
pub fn set_range(&mut self, channel: usize, range: u32) {
self.registers.store(PWM_RNG[channel], range);
}
pub fn set_data(&mut self, channel: usize, data: u32) {
self.registers.store(PWM_DAT[channel], data);
}
pub fn write_fifo(&mut self, data: u32) {
self.registers.store(PWM_FIF1, data);
}
}