commit 478744e2316a2d88abbce46ad19e3935e1630874 Author: Jake Goulding Date: Wed Jul 6 19:59:51 2016 -0400 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1e7caa9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target/ diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..cb069fe --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "arduino" +version = "0.1.0" +authors = [ + "The AVR-Rust Project Developers", + "Jake Goulding ", +] +license = "MIT/Apache-2.0" +readme = "README.md" +repository = "https://github.com/avr-rust/arduino" +homepage = "https://github.com/avr-rust/arduino" +description = """ +Reusable components for the Arduino Uno. +""" +keywords = ["avr", "arduino", "uno"] + +[dependencies.core] +path = "../libcore" diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..8933eb2 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2016 The AVR-Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..98cc01b --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,139 @@ +//! Definitions of register addresses and bits within those registers + +#![feature(asm)] +#![feature(no_core)] +#![no_core] + +extern crate core; + +pub mod prelude; +pub mod timer0; +pub mod timer1; +pub mod serial; + +macro_rules! bit { + (-, $pos:expr) => {}; + ($name:ident, $pos:expr) => { + pub const $name: u8 = 1 << $pos; + }; +} + +macro_rules! register { + ($address:expr, $name:ident, [$b7:tt, $b6:tt, $b5:tt, $b4:tt, $b3:tt, $b2:tt, $b1:tt, $b0:tt]) => { + register!($address, $name); + bit!($b7, 7); + bit!($b6, 6); + bit!($b5, 5); + bit!($b4, 4); + bit!($b3, 3); + bit!($b2, 2); + bit!($b1, 1); + bit!($b0, 0); + }; + ($address:expr, $name:ident) => { + pub const $name: *mut u8 = $address as *mut u8; + }; +} + +register!(0xC6, UDR0 ); +register!(0xC5, UBRR0H ); +register!(0xC4, UBRR0L ); +register!(0xC2, UCSR0C, [UMSEL01, UMSEL00, UPM01, UPM00, USBS0, UCSZ01, UCSZ00, UCPOL0 ]); +register!(0xC1, UCSR0B, [RXCIE0, TXCIE0, UDRIE0, RXEN0, TXEN0, UCSZ02, RXB80, TXB80 ]); +register!(0xC0, UCSR0A, [RXC0, TXC0, UDRE0, FE0, DOR0, UPE0, U2X0, MPCM0 ]); +register!(0xBD, TWAMR, [TWAM6, TWAM5, TWAM4, TWAM3, TWAM2, TWAM1, TWAM0, - ]); +register!(0xBC, TWCR, [TWINT, TWEA, TWSTA, TWSTO, TWWC, TWEN, -, TWIE ]); +register!(0xBB, TWDR ); +register!(0xBA, TWAR, [TWA6, TWA5, TWA4, TWA3, TWA2, TWA1, TWA0, TWGCE ]); +register!(0xB9, TWSR, [TWS7, TWS6, TWS5, TWS4, TWS3, -, TWPS1, TWPS0 ]); +register!(0xB8, TWBR ); +register!(0xB6, ASSR, [-, EXCLK, AS2, TCN2UB, OCR2AUB, OCR2BUB, TCR2AUB, TCR2BUB]); +register!(0xB4, OCR2B ); +register!(0xB3, OCR2A ); +register!(0xB2, TCNT2 ); +register!(0xB1, TCCR2B, [FOC2A, FOC2B, -, -, WGM22, CS22, CS21, CS20 ]); +register!(0xB0, TCCR2A, [COM2A1, COM2A0, COM2B1, COM2B0, -, -, WGM21, WGM20 ]); +register!(0x8B, OCR1BH ); +register!(0x8A, OCR1BL ); +register!(0x89, OCR1AH ); +register!(0x88, OCR1AL ); +register!(0x87, ICR1H ); +register!(0x86, ICR1L ); +register!(0x85, TCNT1H ); +register!(0x84, TCNT1L ); +register!(0x82, TCCR1C, [FOC1A, FOC1B, -, -, -, -, -, - ]); +register!(0x81, TCCR1B, [ICNC1, ICES1, -, WGM13, WGM12, CS12, CS11, CS10 ]); +register!(0x80, TCCR1A, [COM1A1, COM1A0, COM1B1, COM1B0, -, -, WGM11, WGM10 ]); +register!(0x7F, DIDR1, [-, -, -, -, -, -, AIN1D, AIN0D ]); +register!(0x7E, DIDR0, [-, -, ADC5D, ADC4D, ADC3D, ADC2D, ADC1D, ADC0D ]); +register!(0x7C, ADMUX, [REFS1, REFS0, ADLAR, -, MUX3, MUX2, MUX1, MUX0 ]); +register!(0x7B, ADCSRB, [-, ACME, -, -, -, ADTS2, ADTS1, ADTS0 ]); +register!(0x7A, ADCSRA, [ADEN, ADSC, ADATE, ADIF, ADIE, ADPS2, ADPS1, ADPS0 ]); +register!(0x79, ADCH ); +register!(0x78, ADCL ); +register!(0x70, TIMSK2, [-, -, -, -, -, OCIE2B, OCIE2A, TOIE2 ]); +register!(0x6F, TIMSK1, [-, -, ICIE1, -, -, OCIE1B, OCIE1A, TOIE1 ]); +register!(0x6E, TIMSK0, [-, -, -, -, -, OCIE0B, OCIE0A, TOIE0 ]); +register!(0x6D, PCMSK2, [PCINT23, PCINT22, PCINT21, PCINT20, PCINT19, PCINT18, PCINT17, PCINT16]); +register!(0x6C, PCMSK1, [-, PCINT14, PCINT13, PCINT12, PCINT11, PCINT10, PCINT9, PCINT8 ]); +register!(0x6B, PCMSK0, [PCINT7, PCINT6, PCINT5, PCINT4, PCINT3, PCINT2, PCINT1, PCINT0 ]); +register!(0x69, EICRA, [-, -, -, -, ISC11, ISC10, ISC01, ISC00 ]); +register!(0x68, PCICR, [-, -, -, -, -, PCIE2, PCIE1, PCIE0 ]); +register!(0x66, OSCCAL ); +register!(0x64, PRR, [PRTWI, PRTIM2, PRTIM0, -, PRTIM1, PRSPI, PRUSART0,PRADC ]); +register!(0x61, CLKPR, [CLKPCE, -, -, -, CLKPS3, CLKPS2, CLKPS1, CLKPS0 ]); +register!(0x60, WDTCSR, [WDIF, WDIE, WDP3, WDCE, WDE, WDP2, WDP1, WDP0 ]); +register!(0x5F, SREG, [I, T, H, S, V, N, Z, C ]); +register!(0x5E, SPH, [-, -, -, -, -, SP10, SP9, SP8 ]); +register!(0x5D, SPL, [SP7, SP6, SP5, SP4, SP3, SP2, SP1, SP0 ]); +register!(0x57, SPMCSR, [SPMIE, RWWSB, SIGRD, RWWSRE, BLBSET, PGWRT, PGERS, SPMEN ]); +register!(0x55, MCUCR, [-, BODS, BODSE, PUD, -, -, IVSEL, IVCE ]); +register!(0x54, MCUSR, [-, -, -, -, WDRF, BORF, EXTRF, PORF ]); +register!(0x53, SMCR, [-, -, -, -, SM2, SM1, SM0, SE ]); +register!(0x50, ACSR, [ACD, ACBG, ACO, ACI, ACIE, ACIC, ACIS1, ACIS0 ]); +register!(0x4E, SPDR ); +register!(0x4D, SPSR, [SPIF, WCOL, -, -, -, -, -, SPI2X ]); +register!(0x4C, SPCR, [SPIE, SPE, DORD, MSTR, CPOL, CPHA, SPR1, SPR0 ]); +register!(0x4B, GPIOR2 ); +register!(0x4A, GPIOR1 ); +register!(0x48, OCR0B ); +register!(0x47, OCR0A ); +register!(0x46, TCNT0 ); +register!(0x45, TCCR0B, [FOC0A, FOC0B, -, -, WGM02, CS02, CS01, CS00 ]); +register!(0x44, TCCR0A, [COM0A1, COM0A0, COM0B1, COM0B0, -, -, WGM01, WGM00 ]); +register!(0x43, GTCCR, [TSM, -, -, -, -, -, PSRASY, PSRSYNC]); +register!(0x42, EEARH ); +register!(0x41, EEARL ); +register!(0x40, EEDR ); +register!(0x3F, EECR, [-, -, EEPM1, EEPM0, EERIE, EEMPE, EEPE, EERE ]); +register!(0x3E, GPIOR0 ); +register!(0x3D, EIMSK, [-, -, -, -, -, -, INT1, INT0 ]); +register!(0x3C, EIFR, [-, -, -, -, -, -, INTF1, INTF0 ]); +register!(0x3B, PCIFR, [-, -, -, -, -, PCIF2, PCIF1, PCIF0 ]); +register!(0x37, TIFR2, [-, -, -, -, -, OCF2B, OCF2A, TOV2 ]); +register!(0x36, TIFR1, [-, -, ICF1, -, -, OCF1B, OCF1A, TOV1 ]); +register!(0x35, TIFR0, [-, -, -, -, -, OCF0B, OCF0A, TOV0 ]); +register!(0x2B, PORTD, [PORTD7, PORTD6, PORTD5, PORTD4, PORTD3, PORTD2, PORTD1, PORTD0 ]); +register!(0x2A, DDRD, [DDD7, DDD6, DDD5, DDD4, DDD3, DDD2, DDD1, DDD0 ]); +register!(0x29, PIND, [PIND7, PIND6, PIND5, PIND4, PIND3, PIND2, PIND1, PIND0 ]); +register!(0x28, PORTC, [-, PORTC6, PORTC5, PORTC4, PORTC3, PORTC2, PORTC1, PORTC0 ]); +register!(0x27, DDRC, [-, DDC6, DDC5, DDC4, DDC3, DDC2, DDC1, DDC0 ]); +register!(0x26, PINC, [-, PINC6, PINC5, PINC4, PINC3, PINC2, PINC1, PINC0 ]); +register!(0x25, PORTB, [PORTB7, PORTB6, PORTB5, PORTB4, PORTB3, PORTB2, PORTB1, PORTB0 ]); +register!(0x24, DDRB, [DDB7, DDB6, DDB5, DDB4, DDB3, DDB2, DDB1, DDB0 ]); +register!(0x23, PINB, [PINB7, PINB6, PINB5, PINB4, PINB3, PINB2, PINB1, PINB0 ]); + +// 16-bit register pairs +pub const ADC: *mut u16 = ADCL as *mut u16; +pub const EEAR: *mut u16 = EEARL as *mut u16; +pub const ICR1: *mut u16 = ICR1L as *mut u16; +pub const OCR1A: *mut u16 = OCR1AL as *mut u16; +pub const OCR1B: *mut u16 = OCR1BL as *mut u16; +pub const OSCCA: *mut u16 = OSCCAL as *mut u16; +pub const SP: *mut u16 = SPL as *mut u16; +pub const TCNT1: *mut u16 = TCNT1L as *mut u16; +pub const UBRR0: *mut u16 = UBRR0L as *mut u16; + +// Aliases +pub const UDORD0: u8 = UCSZ01; +pub const UCPHA0: u8 = UCSZ00; diff --git a/src/prelude.rs b/src/prelude.rs new file mode 100644 index 0000000..8895d93 --- /dev/null +++ b/src/prelude.rs @@ -0,0 +1,26 @@ +use core::prelude::v1::*; +use core::marker::PhantomData; + +pub struct DisableInterrupts(PhantomData<()>); + +impl DisableInterrupts { + #[inline] + pub fn new() -> DisableInterrupts { + unsafe { asm!("CLI") } + DisableInterrupts(PhantomData) + } +} + +impl Drop for DisableInterrupts { + #[inline] + fn drop(&mut self) { + unsafe { asm!("SEI") } + } +} + +pub fn without_interrupts(f: F) -> T + where F: FnOnce() -> T +{ + let _disabled = DisableInterrupts::new(); + f() +} diff --git a/src/serial.rs b/src/serial.rs new file mode 100644 index 0000000..76e9643 --- /dev/null +++ b/src/serial.rs @@ -0,0 +1,226 @@ +use core::prelude::v1::*; +use core::ptr::{read_volatile, write_volatile}; + +use super::*; + +pub enum CharacterSize { + FiveBits, + SixBits, + SevenBits, + EightBits, + NineBits, +} + +impl CharacterSize { + /// Returns bits for UCSR0B, UCSR0C + #[inline] + fn bits(&self) -> (u8, u8) { + use self::CharacterSize::*; + + match *self { + FiveBits => (0 , 0 | 0 ), + SixBits => (0 , 0 | UCSZ00), + SevenBits => (0 , UCSZ01 | 0 ), + EightBits => (0 , UCSZ01 | UCSZ00), + // Reserved => (UCSZ02, 0 | 0 ), + // Reserved => (UCSZ02, 0 | UCSZ00), + // Reserved => (UCSZ02, UCSZ01 | 0 ), + NineBits => (UCSZ02, UCSZ01 | UCSZ00), + } + } + + #[inline] + fn mask() -> (u8, u8) { + (!(UCSZ01 | UCSZ00), !(UCSZ02)) + } +} + +pub enum Mode { + Asynchronous, + Synchronous, + MasterSpi, +} + +impl Mode { + #[inline] + fn bits(&self) -> u8 { + use self::Mode::*; + + match *self { + Asynchronous => 0 | 0, + Synchronous => 0 | UMSEL00, + // Reserved => UMSEL01 | 0, + MasterSpi => UMSEL01 | UMSEL00, + } + } + + #[inline] + fn mask() -> u8 { + !(UMSEL01 | UMSEL00) + } +} + +pub enum Parity { + Disabled, + Even, + Odd, +} + +impl Parity { + #[inline] + fn bits(&self) -> u8 { + use self::Parity::*; + + match *self { + Disabled => 0 | 0, + // Reserved => 0 | UPM00, + Even => UPM01 | 0, + Odd => UPM01 | UPM00, + } + } + + #[inline] + fn mask() -> u8 { + !(UPM01 | UPM00) + } +} + +pub enum StopBits { + OneBit, + TwoBits, +} + +impl StopBits { + #[inline] + fn bits(&self) -> u8 { + use self::StopBits::*; + + match *self { + OneBit => 0, + TwoBits => USBS0, + } + } + + #[inline] + fn mask() -> u8 { + !USBS0 + } +} + +pub struct Serial { + ubrr: u16, + a: u8, + b: u8, + c: u8, +} + +impl Serial { + #[inline] + pub fn new(ubrr: u16) -> Self { + Serial { + ubrr: ubrr, + a: 0, + b: 0, + c: 0, + } + } + + #[inline] + pub fn character_size(mut self, character_size: CharacterSize) -> Self { + let (b, c) = CharacterSize::mask(); + self.b &= b; + self.c &= c; + + let (b, c) = character_size.bits(); + self.b |= b; + self.c |= c; + + self + } + + #[inline] + pub fn mode(mut self, mode: Mode) -> Self { + self.c &= Mode::mask(); + self.c |= mode.bits(); + self + } + + #[inline] + pub fn parity(mut self, parity: Parity) -> Self { + self.c &= Parity::mask(); + self.c |= parity.bits(); + self + } + + #[inline] + pub fn stop_bits(mut self, stop_bits: StopBits) -> Self { + self.c &= StopBits::mask(); + self.c |= stop_bits.bits(); + self + } + + #[inline] + pub fn configure(self) { + unsafe { + // Set Baud rate + write_volatile(UBRR0, self.ubrr); + + write_volatile(UCSR0A, self.a); + write_volatile(UCSR0B, self.b | RXEN0 | TXEN0); + write_volatile(UCSR0C, self.c); + } + } +} + +#[inline] +pub fn ready_to_transmit() -> bool { + unsafe { (read_volatile(UCSR0A) & UDRE0) != 0 } +} + +#[inline] +fn do_write(byte: u8) { + unsafe { write_volatile(UDR0, byte); } +} + +/// Does a blocking transfer of one byte +#[inline] +pub fn transmit(byte: u8) { + while !ready_to_transmit() {} + do_write(byte); +} + +#[inline] +pub fn try_transmit(byte: u8) -> Result<(), ()> { + if ready_to_transmit() { + do_write(byte); + Ok(()) + } else { + Err(()) + } +} + +#[inline] +pub fn ready_to_receive() -> bool { + unsafe { (read_volatile(UCSR0A) & RXC0) != 0 } +} + +#[inline] +fn do_read() -> u8 { + unsafe { read_volatile(UDR0) } +} + +/// Does a blocking read of one byte +#[inline] +pub fn receive() -> u8 { + while !ready_to_receive() {} + do_read() +} + +#[inline] +pub fn try_receive() -> Option { + if ready_to_receive() { + Some(do_read()) + } else { + None + } +} diff --git a/src/timer0.rs b/src/timer0.rs new file mode 100644 index 0000000..5869b7c --- /dev/null +++ b/src/timer0.rs @@ -0,0 +1,139 @@ +use core::prelude::v1::*; +use core::ptr::write_volatile; + +use super::*; + +pub enum ClockSource { + None, + Prescale1, + Prescale8, + Prescale64, + Prescale256, + Prescale1024, + ExternalFalling, + ExternalRising, +} + +impl ClockSource { + #[inline] + fn bits(&self) -> u8 { + use self::ClockSource::*; + + match *self { + None => 0 | 0 | 0, + Prescale1 => 0 | 0 | CS00, + Prescale8 => 0 | CS01 | 0, + Prescale64 => 0 | CS01 | CS00, + Prescale256 => CS02 | 0 | 0, + Prescale1024 => CS02 | 0 | CS00, + ExternalFalling => CS02 | CS01 | 0, + ExternalRising => CS02 | CS01 | CS00, + } + } + + #[inline] + fn mask() -> u8 { + !(CS02 | CS01 | CS00) + } +} + +pub enum WaveformGenerationMode { + Normal, + PwmPhaseCorrect, + ClearOnTimerMatchOutputCompare, + FastPwm , + PwmPhaseCorrectOutputCompare, + FastPwmOutputCompare, +} + +impl WaveformGenerationMode { + /// Returns bits for TCCR0A, TCCR0B + #[inline] + fn bits(&self) -> (u8, u8) { + use self::WaveformGenerationMode::*; + + // It makes more sense to return bytes (A,B), but the manual + // lists the table as (B,A). We match the manual here for + // inspection purposes and flip the values for sanity + // purposes. + let (b, a) = match *self { + Normal => ( 0, 0 | 0), + PwmPhaseCorrect => ( 0, 0 | WGM00), + ClearOnTimerMatchOutputCompare => ( 0, WGM01 | 0), + FastPwm => ( 0, WGM01 | WGM00), + // Reserved => (WGM02, 0 | 0), + PwmPhaseCorrectOutputCompare => (WGM02, 0 | WGM00), + // Reserved => (WGM02, WGM01 | 0), + FastPwmOutputCompare => (WGM02, WGM01 | WGM00), + }; + + (a, b) + } + + #[inline] + fn mask() -> (u8, u8) { + (!(WGM00 | WGM01), !(WGM02)) + } +} + +pub struct Timer { + a: u8, + b: u8, + output_compare_1: Option, +} + +impl Timer { + #[inline] + pub fn new() -> Self { + Timer { + a: 0, + b: 0, + output_compare_1: None, + } + } + + #[inline] + pub fn clock_source(mut self, source: ClockSource) -> Self { + self.b &= ClockSource::mask(); + self.b |= source.bits(); + self + } + + #[inline] + pub fn waveform_generation_mode(mut self, mode: WaveformGenerationMode) -> Self { + let (a, b) = WaveformGenerationMode::mask(); + self.a &= a; + self.b &= b; + + let (a, b) = mode.bits(); + self.a |= a; + self.b |= b; + + self + } + + #[inline] + pub fn output_compare_1(mut self, value: Option) -> Self { + self.output_compare_1 = value; + self + } + + #[inline] + pub fn configure(self) { + unsafe { + write_volatile(TCCR0A, self.a); + write_volatile(TCCR0B, self.b); + + // Reset counter to zero + write_volatile(TCNT0, 0); + + if let Some(v) = self.output_compare_1 { + // Set the match + write_volatile(OCR0A, v); + + // Enable compare interrupt + write_volatile(TIMSK0, OCIE0A); + } + } + } +} diff --git a/src/timer1.rs b/src/timer1.rs new file mode 100644 index 0000000..5c0cfad --- /dev/null +++ b/src/timer1.rs @@ -0,0 +1,159 @@ +use core::prelude::v1::*; +use core::ptr::write_volatile; + +use super::*; + +pub enum ClockSource { + None, + Prescale1, + Prescale8, + Prescale64, + Prescale256, + Prescale1024, + ExternalFalling, + ExternalRising, +} + +impl ClockSource { + #[inline] + fn bits(&self) -> u8 { + use self::ClockSource::*; + + match *self { + None => 0 | 0 | 0, + Prescale1 => 0 | 0 | CS10, + Prescale8 => 0 | CS11 | 0, + Prescale64 => 0 | CS11 | CS10, + Prescale256 => CS12 | 0 | 0, + Prescale1024 => CS12 | 0 | CS10, + ExternalFalling => CS12 | CS11 | 0, + ExternalRising => CS12 | CS11 | CS10, + } + } + + #[inline] + fn mask() -> u8 { + !(CS12 | CS11 | CS10) + } +} + +pub enum WaveformGenerationMode { + Normal, + PwmPhaseCorrect8Bit, + PwmPhaseCorrect9Bit, + PwmPhaseCorrect10Bit, + ClearOnTimerMatchOutputCompare, + FastPwm8Bit, + FastPwm9Bit, + FastPwm10Bit, + PwmPhaseAndFrequencyCorrectInputCapture, + PwmPhaseAndFrequencyCorrectOutputCompare, + PwmPhaseCorrectInputCapture, + PwmPhaseCorrectOutputCompare, + ClearOnTimerMatchInputCapture, + FastPwmInputCapture, + FastPwmOutputCompare, +} + +impl WaveformGenerationMode { + /// Returns bits for TCCR1A, TCCR1B + #[inline] + fn bits(&self) -> (u8, u8) { + use self::WaveformGenerationMode::*; + + // It makes more sense to return bytes (A,B), but the manual + // lists the table as (B,A). We match the manual here for + // inspection purposes and flip the values for sanity + // purposes. + let (b, a) = match *self { + Normal => ( 0 | 0, 0 | 0), + PwmPhaseCorrect8Bit => ( 0 | 0, 0 | WGM10), + PwmPhaseCorrect9Bit => ( 0 | 0, WGM11 | 0), + PwmPhaseCorrect10Bit => ( 0 | 0, WGM11 | WGM10), + ClearOnTimerMatchOutputCompare => ( 0 | WGM12, 0 | 0), + FastPwm8Bit => ( 0 | WGM12, 0 | WGM10), + FastPwm9Bit => ( 0 | WGM12, WGM11 | 0), + FastPwm10Bit => ( 0 | WGM12, WGM11 | WGM10), + PwmPhaseAndFrequencyCorrectInputCapture => (WGM13 | 0, 0 | 0), + PwmPhaseAndFrequencyCorrectOutputCompare => (WGM13 | 0, 0 | WGM10), + PwmPhaseCorrectInputCapture => (WGM13 | 0, WGM11 | 0), + PwmPhaseCorrectOutputCompare => (WGM13 | 0, WGM11 | WGM10), + ClearOnTimerMatchInputCapture => (WGM13 | WGM12, 0 | 0), + // Reserved => (WGM13 | WGM12, 0 | WGM10), + FastPwmInputCapture => (WGM13 | WGM12, WGM11 | 0), + FastPwmOutputCompare => (WGM13 | WGM12, WGM11 | WGM10), + }; + + (a, b) + } + + #[inline] + fn mask() -> (u8, u8) { + (!(WGM10 | WGM11), !(WGM12 | WGM13)) + } +} + +pub struct Timer { + a: u8, + b: u8, + c: u8, + output_compare_1: Option, +} + +impl Timer { + #[inline] + pub fn new() -> Self { + Timer { + a: 0, + b: 0, + c: 0, + output_compare_1: None, + } + } + + #[inline] + pub fn clock_source(mut self, source: ClockSource) -> Self { + self.b &= ClockSource::mask(); + self.b |= source.bits(); + self + } + + #[inline] + pub fn waveform_generation_mode(mut self, mode: WaveformGenerationMode) -> Self { + let (a, b) = WaveformGenerationMode::mask(); + self.a &= a; + self.b &= b; + + let (a, b) = mode.bits(); + self.a |= a; + self.b |= b; + + self + } + + #[inline] + pub fn output_compare_1(mut self, value: Option) -> Self { + self.output_compare_1 = value; + self + } + + #[inline] + pub fn configure(self) { + unsafe { + write_volatile(TCCR1A, self.a); + write_volatile(TCCR1B, self.b); + write_volatile(TCCR1C, self.c); + + // Reset counter to zero + write_volatile(TCNT1, 0); + + if let Some(v) = self.output_compare_1 { + // Set the match + write_volatile(OCR1A, v); + + // Enable compare interrupt + write_volatile(TIMSK1, OCIE1A); + } + } + } +}