/** \defgroup adc Analog-to-Digital Conversion \defgroup buffer Circular Buffer \defgroup delay Time Delays \defgroup serial Serial I/O \defgroup spi Serial Peripheral Interface \defgroup timer0 Timer 0 \defgroup timer1 Timer 1 \defgroup timer2 Timer 2 \defgroup timer3 Timer 3 (only available for processors with Timer 3) \defgroup timer4 Timer 4 (only available for processors with Timer 4) \defgroup timer5 Timer 5 (only available for processors with Timer 5) \defgroup twi Two-Wire Interface \defgroup serial_support Serial Support Functions (not for user code) */ #ifndef OULIB_INCLUDE #define OULIB_INCLUDE #include #include #include #include #include #define OULIB_VERSION "2012_02_14" #ifndef F_CPU #error "F_CPU must be defined" #endif // The latter test allows us to deal with the fact that AVRstudio // resets our F_CPU parameter #if (F_CPU == 160000UL) #define MS_SHIFT 4 #define MS_GATE 0x0f #undef F_CPU #define F_CPU 16000000 #elif (F_CPU == 16000000) #define MS_SHIFT 4 #define MS_GATE 0x0f #elif (F_CPU == 8000000) #define MS_SHIFT 5 #define MS_GATE 0x1f #elif (F_CPU == 1000000) #define MS_SHIFT 8 #define MS_GATE 0xff #else #error "Bad F_CPU specification" #endif //Using AtMega168: define standard register names #ifdef atmega168 # define TCCR0 TCCR0B # define TCCR2 TCCR2B # define UCSRA UCSR0A # define UCSRB UCSR0B # define UDR UDR0 # define UDRE UDRE0 # define RXC RXC0 # define RXEN RXEN0 # define TXEN TXEN0 # define UBRRH UBRR0H # define UBRRL UBRR0L # define TICIE1 ICIE1 # define RXCIE RXCIE0 # define UDRIE UDRIE0 //# define TIMSK TIMSK1 #define CPU_DEFINED #endif #ifdef atmega328p # define TCCR0 TCCR0B # define TCCR2 TCCR2B # define UCSRA UCSR0A # define UCSRB UCSR0B # define UDR UDR0 # define UDRE UDRE0 # define RXC RXC0 # define RXEN RXEN0 # define TXEN TXEN0 # define UBRRH UBRR0H # define UBRRL UBRR0L # define TICIE1 ICIE1 # define RXCIE RXCIE0 # define UDRIE UDRIE0 # define TIMSK TIMSK1 #define USART_RXC_vect USART_RX_vect #define TIMER0A #define TIMER0B #define TIMER2A #define TIMER2B #define TIMER1B #define CPU_DEFINED #endif #ifdef at90usb1287 # define TCCR0 TCCR0B # define TCCR2 TCCR2B # define UCSRA UCSR1A # define UCSRB UCSR1B //# define TIMSK2 TIMSK # define UDR UDR1 # define UDRE UDRE1 # define RXC RXC1 # define RXEN RXEN1 # define TXEN TXEN1 # define UBRRH UBRR1H # define UBRRL UBRR1L //# define TICIE1 ICIE1 # define RXCIE RXCIE1 # define UDRIE UDRIE1 //# define TIMSK TIMSK1 #define USART_RXC_vect USART1_RX_vect #define USART_UDRE_vect USART1_UDRE_vect #define CPU_DEFINED #endif #ifdef atmega644p # define TCCR0 TCCR0B # define TCCR2 TCCR2B # define UCSRA UCSR0A # define UCSRB UCSR0B # define UDR UDR0 # define UDRE UDRE0 # define RXC RXC0 # define RXEN RXEN0 # define TXEN TXEN0 # define UBRRH UBRR0H # define UBRRL UBRR0L //# define TICIE1 ICIE1 //# define TIMSK TIMSK1 // Indicate that we have more than 1 serial port #define SERIAL_NPORTS_2 #define CPU_DEFINED #endif #ifdef atmega2560 # define TCCR0 TCCR0B # define TCCR2 TCCR2B # define UCSRA UCSR0A # define UCSRB UCSR0B # define UDR UDR0 # define UDRE UDRE0 # define RXC RXC0 # define RXEN RXEN0 # define TXEN TXEN0 # define UBRRH UBRR0H # define UBRRL UBRR0L # define RXCIE RXCIE0 # define UDRIE UDRIE0 //# define TICIE1 ICIE1 //# define TIMSK TIMSK1 // Indicate that we have 4 serial ports #define SERIAL_NPORTS_4 #define TIMER0A #define TIMER0B #define TIMER1B #define TIMER1C #define TIMER2A #define TIMER2B #define CPU_DEFINED #define TIMER3 #define TIMER4 #define TIMER5 #define ADC_CHANS_16 #define HAS_PORTA #define HAS_PORTE #define HAS_PORTF #define HAS_PORTG #define HAS_PORTH #define HAS_PORTJ #define HAS_PORTK #endif #ifdef atmega8 #define UCSR0B UCSRB #define UDRIE0 UDRIE #define RXCIE0 RXCIE #define CPU_DEFINED #endif #ifdef atmega88 #define CPU_DEFINED #endif #ifndef CPU_DEFINED #error "Missing definitions: CDEFS = -DF_CPU=16000000 -D$(MCU)" #endif /////////////////////////////////////////////////// // Serial /** File pointer structure for unbuffered serial ports. */ struct OU_FILE { /** Reference to physical serial port. 0 .. 3, depending on hardware */ uint8_t port; }; /** struct OU_FILE_BUF File pointer structure for buffered serial ports. */ struct OU_FILE_BUF { /** Reference to physical serial port. 0 .. 3, depending on hardware */ uint8_t port; /** Number of bytes in input buffer. */ uint8_t buf_size_in; /** Number of bytes in output buffer. */ uint8_t buf_size_out; /** Index of the front of the input buffer. */ volatile uint8_t buf_in_front; /** Index of the back of the input buffer (index of the next char spot). */ volatile uint8_t buf_in_back; /** Index of the front of the output buffer. */ volatile uint8_t buf_out_front; /** Index of the back of the output buffer (index of the next char spot). */ volatile uint8_t buf_out_back; /** Reference to the buffer space. */ char *buffer; }; // Having this global variable is ugly: need to clean this up // There must be a way to get to the stdlib stream list... #ifndef SERIAL_NPORTS_2 #ifndef SERIAL_NPORTS_4 extern struct OU_FILE_BUF *ou_file_buf[1]; #else extern struct OU_FILE_BUF *ou_file_buf[4]; #endif #else extern struct OU_FILE_BUF *ou_file_buf[2]; #endif /////////////////////////////////////////////////////////////// // Serial interrupt enable/disable /** Enable the receive interrupt for serial port 0. @author Andrew H. Fagg \ingroup serial */ inline void serial0_receive_enable(void) { UCSRB |= _BV(RXCIE); } /** Disable the receive interrupt for serial port 0. @author Andrew H. Fagg \ingroup serial */ inline void serial0_receive_disable(void) { UCSRB &= ~_BV(RXCIE); } /** Enable the transmit interrupt for serial port 0. @author Andrew H. Fagg \ingroup serial */ inline void serial0_transmit_enable(void) { UCSRB |= _BV(UDRIE); } /** Disable the transmit interrupt for serial port 0. @author Andrew H. Fagg \ingroup serial */ inline void serial0_transmit_disable(void) { UCSRB &= ~_BV(UDRIE); } #if defined(SERIAL_NPORTS_2) || defined(SERIAL_NPORTS_4) /** Enable the receive interrupt for serial port 1. Note: only available for chips with two or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial1_receive_enable(void) { UCSR1B |= _BV(RXCIE1); } /** Disable the receive interrupt for serial port 1. Note: only available for chips with two or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial1_receive_disable(void) { UCSR1B &= ~_BV(RXCIE1); } /** Enable the transmit interrupt for serial port 1. Note: only available for chips with two or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial1_transmit_enable(void) { UCSR1B |= _BV(UDRIE1); } /** Disable the transmit interrupt for serial port 1. Note: only available for chips with two or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial1_transmit_disable(void) { UCSR1B &= ~_BV(UDRIE1); } #endif #if defined(SERIAL_NPORTS_4) /** Enable the transmit interrupt for serial port 2. Note: only available for chips with four or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial2_transmit_enable(void) { UCSR2B |= _BV(UDRIE2); } /** Disable the transmit interrupt for serial port 2. Note: only available for chips with four or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial2_transmit_disable(void) { UCSR2B &= ~_BV(UDRIE2); } /** Enable the transmit interrupt for serial port 3. Note: only available for chips with four or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial3_transmit_enable(void) { UCSR3B |= _BV(UDRIE3); } /** Disable the transmit interrupt for serial port 3. Note: only available for chips with four or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial3_transmit_disable(void) { UCSR3B &= ~_BV(UDRIE3); } /** Enable the receive interrupt for serial port 2. Note: only available for chips with four or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial2_receive_enable(void) { UCSR2B |= _BV(RXCIE2); } /** Disable the receive interrupt for serial port 2. Note: only available for chips with four or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial2_receive_disable(void) { UCSR2B &= ~_BV(RXCIE2); } /** Enable the receive interrupt for serial port 3. Note: only available for chips with four or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial3_receive_enable(void) { UCSR3B |= _BV(RXCIE3); } /** Disable the receive interrupt for serial port 3. Note: only available for chips with four or more serial ports. @author Andrew H. Fagg \ingroup serial */ inline void serial3_receive_disable(void) { UCSR3B &= ~_BV(RXCIE3); } #endif /////////////////////////////////////////////////// // Delay extern void delay_ms(unsigned int); extern void delay_us(unsigned int); /////////////////////////////////////////////////// // Timer0 extern void timer0_config(uint8_t config); // Possible configuration parameters for timer0_config() #define TIMER0_NOCLK 0 #define TIMER0_NOPRE 1 #define TIMER0_PRE_8 2 #define TIMER0_PRE_64 3 #define TIMER0_PRE_256 4 #define TIMER0_PRE_1024 5 #define TIMER0_EXT_FALLING 6 #define TIMER0_EXT_RISING 7 #ifdef TIMER0A /** Set the state of the timer 0 output compare unit A register.

@param val The new value of the timer 0 output compare unit A register. @author Andrew H. Fagg \ingroup timer0 */ inline void timer0_output_compare_A_set(uint8_t val) { OCR0A = val; } /** Read the state of the timer 0 output compare unit A register.

@return The value of the timer 0 output compare unit A register. @author Andrew H. Fagg \ingroup timer0 */ inline uint8_t timer0_output_compare_A_read(void) { return(OCR0A); } #endif #ifdef TIMER0B /** Set the state of the timer 0 output compare unit B register.

@param val The new value of the timer 0 output compare unit B register. @author Andrew H. Fagg \ingroup timer0 */ inline void timer0_output_compare_B_set(uint8_t val) { OCR0B = val; } /** Read the state of the timer 0 output compare unit B register.

@return The value of the timer 0 output compare unit B register. @author Andrew H. Fagg \ingroup timer0 */ inline uint8_t timer0_output_compare_B_read(void) { return(OCR0B); } #endif #if defined(TIMER0A) | defined(TIME0B) extern void timer0_output_compare_config(uint8_t config); #define TIMER0_OUTPUT_COMPARE_CONFIG_NORMAL 0x0 #define TIMER0_OUTPUT_COMPARE_CONFIG_PWM_PC 0x1 #define TIMER0_OUTPUT_COMPARE_CONFIG_CTC_OCRA 0x2 #define TIMER0_OUTPUT_COMPARE_CONFIG_PWM_F 0x3 #define TIMER0_OUTPUT_COMPARE_CONFIG_PWM_PC_OCRA 0x5 #define TIMER0_OUTPUT_COMPARE_CONFIG_PWM_F_OCRA 0x7 #endif #ifdef TIMER0A extern void timer0_compare_output_A_mode_set(uint8_t mode); #endif #ifdef TIMER0B extern void timer0_compare_output_B_mode_set(uint8_t mode); #endif #if defined(TIMER0A) | defined(TIME0B) // Valid modes #define TIMER0_COMPARE_OUTPUT_MODE_NORMAL 0 #define TIMER0_COMPARE_OUTPUT_MODE_TOGGLE 1 #define TIMER0_COMPARE_OUTPUT_MODE_CLEAR 2 #define TIMER0_COMPARE_OUTPUT_MODE_SET 3 #endif ///////////////////////////////////////////////////////////////////// // Timer 1 extern void timer1_config(uint8_t config); #define TIMER1_NOCLK 0 #define TIMER1_NOPRE 1 #define TIMER1_PRE_8 2 #define TIMER1_PRE_64 3 #define TIMER1_PRE_256 4 #define TIMER1_PRE_1024 5 #define TIMER1_EXT_FALLING 6 #define TIMER1_EXT_RISING 7 //extern inline void timer1_enable(void); //extern inline void timer1_disable(void); extern uint16_t timer1_read(void); extern void timer1_set(uint16_t); extern void timer1_output_compare_config(uint8_t config); #define TIMER1_OUTPUT_COMPARE_CONFIG_NORMAL 0x0 #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_PC_08 0x1 #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_PC_09 0x2 #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_PC_10 0x3 #define TIMER1_OUTPUT_COMPARE_CONFIG_CTC_OCR1A 0x4 #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_F_08 0x5 #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_F_09 0x6 #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_F_10 0x7 #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_PFC_ICR1 0x8 #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_PFC_OCR1A 0x9 #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_PC_ICR1 0xa #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_PC_OCR1A 0xb #define TIMER1_OUTPUT_COMPARE_CONFIG_CTC_ICR1 0xc #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_F_ICR1 0xe #define TIMER1_OUTPUT_COMPARE_CONFIG_PWM_F_OCR1A 0xf extern void timer1_output_compare_A_set(uint16_t val); extern uint16_t timer1_output_compare_A_read(void); extern void timer1_compare_output_A_mode_set(uint8_t mode); // Valid modes #define TIMER16B_COMPARE_OUTPUT_MODE_NORMAL 0 #define TIMER16B_COMPARE_OUTPUT_MODE_TOGGLE 1 #define TIMER16B_COMPARE_OUTPUT_MODE_CLEAR 2 #define TIMER16B_COMPARE_OUTPUT_MODE_SET 3 #ifdef TIMER1B extern void timer1_output_compare_B_set(uint16_t val); extern uint16_t timer1_output_compare_B_read(void); extern void timer1_compare_output_B_mode_set(uint8_t mode); #endif #ifdef TIMER1C extern void timer1_output_compare_C_set(uint16_t val); extern uint16_t timer1_output_compare_C_read(void); extern void timer1_compare_output_C_mode_set(uint8_t mode); #endif //////////////////////////////////////////////////////////// // Timer 2 extern void timer2_config(uint8_t config); #define TIMER2_NOCLK 0 #define TIMER2_NOPRE 1 #define TIMER2_PRE_8 2 #define TIMER2_PRE_32 3 #define TIMER2_PRE_64 4 #define TIMER2_PRE_128 5 #define TIMER2_PRE_256 6 #define TIMER2_PRE_1024 7 #ifdef TIMER2A /** Set the state of the timer 2 output compare unit A register.

@param val The new value of the timer 2 output compare unit A register. @author Andrew H. Fagg \ingroup timer2 */ inline void timer2_output_compare_A_set(uint8_t val) { OCR2A = val; } /** Read the state of the timer 2 output compare unit A register.

@return The value of the timer 2 output compare unit A register. @author Andrew H. Fagg \ingroup timer2 */ inline uint8_t timer2_output_compare_A_read(void) { return(OCR2A); } #endif #ifdef TIMER2B /** Set the state of the timer 2 output compare unit B register.

@param val The new value of the timer 2 output compare unit B register. @author Andrew H. Fagg \ingroup timer2 */ inline void timer2_output_compare_B_set(uint8_t val) { OCR2B = val; } /** Read the state of the timer 2 output compare unit B register.

@return The value of the timer 2 output compare unit B register. @author Andrew H. Fagg \ingroup timer2 */ inline uint8_t timer2_output_compare_B_read(void) { return(OCR2B); } #endif #if defined(TIMER2A) | defined(TIME2B) extern void timer2_output_compare_config(uint8_t config); #define TIMER2_OUTPUT_COMPARE_CONFIG_NORMAL 0x0 #define TIMER2_OUTPUT_COMPARE_CONFIG_PWM_PC 0x1 #define TIMER2_OUTPUT_COMPARE_CONFIG_CTC_OCRA 0x2 #define TIMER2_OUTPUT_COMPARE_CONFIG_PWM_F 0x3 #define TIMER2_OUTPUT_COMPARE_CONFIG_PWM_PC_OCRA 0x5 #define TIMER2_OUTPUT_COMPARE_CONFIG_PWM_F_OCRA 0x7 #endif #ifdef TIMER2A extern void timer2_compare_output_A_mode_set(uint8_t mode); #endif #ifdef TIMER2B extern void timer2_compare_output_B_mode_set(uint8_t mode); #endif #if defined(TIMER2A) | defined(TIME2B) // Valid modes #define TIMER2_COMPARE_OUTPUT_MODE_NORMAL 0 #define TIMER2_COMPARE_OUTPUT_MODE_TOGGLE 1 #define TIMER2_COMPARE_OUTPUT_MODE_CLEAR 2 #define TIMER2_COMPARE_OUTPUT_MODE_SET 3 #endif ///////////////////////////////////////////////////////////////////// // Timer 3 #ifdef TIMER3 extern void timer3_config(uint8_t config); #define TIMER3_NOCLK 0 #define TIMER3_NOPRE 1 #define TIMER3_PRE_8 2 #define TIMER3_PRE_64 3 #define TIMER3_PRE_256 4 #define TIMER3_PRE_1024 5 #define TIMER3_EXT_FALLING 6 #define TIMER3_EXT_RISING 7 extern uint16_t timer3_read(void); extern void timer3_set(uint16_t); extern void timer3_output_compare_config(uint8_t config); #define TIMER3_OUTPUT_COMPARE_CONFIG_NORMAL 0x0 #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_PC_08 0x1 #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_PC_09 0x2 #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_PC_10 0x3 #define TIMER3_OUTPUT_COMPARE_CONFIG_CTC_OCR1A 0x4 #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_F_08 0x5 #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_F_09 0x6 #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_F_10 0x7 #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_PFC_ICR1 0x8 #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_PFC_OCR1A 0x9 #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_PC_ICR1 0xa #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_PC_OCR1A 0xb #define TIMER3_OUTPUT_COMPARE_CONFIG_CTC_ICR1 0xc #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_F_ICR1 0xe #define TIMER3_OUTPUT_COMPARE_CONFIG_PWM_F_OCR1A 0xf extern void timer3_output_compare_A_set(uint16_t val); extern uint16_t timer3_output_compare_A_read(void); extern void timer3_compare_output_A_mode_set(uint8_t mode); extern void timer3_output_compare_B_set(uint16_t val); extern uint16_t timer3_output_compare_B_read(void); extern void timer3_compare_output_B_mode_set(uint8_t mode); extern void timer3_output_compare_C_set(uint16_t val); extern uint16_t timer3_output_compare_C_read(void); extern void timer3_compare_output_C_mode_set(uint8_t mode); /** Enable the timer 3 overflow interrupt. @author Andrew H. Fagg \ingroup timer3 */ inline void timer3_enable(void) { TIMSK3 |= _BV(TOIE3); }; /** Disable the timer 3 overflow interrupt. @author Andrew H. Fagg \ingroup timer3 */ inline void timer3_disable(void) { TIMSK3 &= ~_BV(TOIE3); }; #endif ///////////////////////////////////////////////////////////////////// // Timer 4 #ifdef TIMER4 extern void timer4_config(uint8_t config); #define TIMER4_NOCLK 0 #define TIMER4_NOPRE 1 #define TIMER4_PRE_8 2 #define TIMER4_PRE_64 3 #define TIMER4_PRE_256 4 #define TIMER4_PRE_1024 5 #define TIMER4_EXT_FALLING 6 #define TIMER4_EXT_RISING 7 extern uint16_t timer4_read(void); extern void timer4_set(uint16_t); extern void timer4_output_compare_config(uint8_t config); #define TIMER4_OUTPUT_COMPARE_CONFIG_NORMAL 0x0 #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_PC_08 0x1 #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_PC_09 0x2 #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_PC_10 0x3 #define TIMER4_OUTPUT_COMPARE_CONFIG_CTC_OCR1A 0x4 #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_F_08 0x5 #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_F_09 0x6 #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_F_10 0x7 #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_PFC_ICR1 0x8 #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_PFC_OCR1A 0x9 #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_PC_ICR1 0xa #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_PC_OCR1A 0xb #define TIMER4_OUTPUT_COMPARE_CONFIG_CTC_ICR1 0xc #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_F_ICR1 0xe #define TIMER4_OUTPUT_COMPARE_CONFIG_PWM_F_OCR1A 0xf extern void timer4_output_compare_A_set(uint16_t val); extern uint16_t timer4_output_compare_A_read(void); extern void timer4_compare_output_A_mode_set(uint8_t mode); extern void timer4_output_compare_B_set(uint16_t val); extern uint16_t timer4_output_compare_B_read(void); extern void timer4_compare_output_B_mode_set(uint8_t mode); extern void timer4_output_compare_C_set(uint16_t val); extern uint16_t timer4_output_compare_C_read(void); extern void timer4_compare_output_C_mode_set(uint8_t mode); /** Enable the timer 4 overflow interrupt. @author Andrew H. Fagg \ingroup timer4 */ inline void timer4_enable(void) { TIMSK4 |= _BV(TOIE4); }; /** Disable the timer 4 overflow interrupt. @author Andrew H. Fagg \ingroup timer4 */ inline void timer4_disable(void) { TIMSK4 &= ~_BV(TOIE4); }; #endif ///////////////////////////////////////////////////////////////////// // Timer 5 #ifdef TIMER5 extern void timer5_config(uint8_t config); #define TIMER5_NOCLK 0 #define TIMER5_NOPRE 1 #define TIMER5_PRE_8 2 #define TIMER5_PRE_64 3 #define TIMER5_PRE_256 4 #define TIMER5_PRE_1024 5 #define TIMER5_EXT_FALLING 6 #define TIMER5_EXT_RISING 7 extern uint16_t timer5_read(void); extern void timer5_set(uint16_t); extern void timer5_output_compare_config(uint8_t config); #define TIMER5_OUTPUT_COMPARE_CONFIG_NORMAL 0x0 #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_PC_08 0x1 #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_PC_09 0x2 #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_PC_10 0x3 #define TIMER5_OUTPUT_COMPARE_CONFIG_CTC_OCR1A 0x4 #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_F_08 0x5 #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_F_09 0x6 #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_F_10 0x7 #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_PFC_ICR1 0x8 #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_PFC_OCR1A 0x9 #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_PC_ICR1 0xa #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_PC_OCR1A 0xb #define TIMER5_OUTPUT_COMPARE_CONFIG_CTC_ICR1 0xc #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_F_ICR1 0xe #define TIMER5_OUTPUT_COMPARE_CONFIG_PWM_F_OCR1A 0xf extern void timer5_output_compare_A_set(uint16_t val); extern uint16_t timer5_output_compare_A_read(void); extern void timer5_compare_output_A_mode_set(uint8_t mode); extern void timer5_output_compare_B_set(uint16_t val); extern uint16_t timer5_output_compare_B_read(void); extern void timer5_compare_output_B_mode_set(uint8_t mode); extern void timer5_output_compare_C_set(uint16_t val); extern uint16_t timer5_output_compare_C_read(void); extern void timer5_compare_output_C_mode_set(uint8_t mode); /** Enable the timer 5 overflow interrupt. @author Andrew H. Fagg \ingroup timer5 */ inline void timer5_enable(void) { TIMSK5 |= _BV(TOIE5); }; /** Disable the timer 5 overflow interrupt. @author Andrew H. Fagg \ingroup timer5 */ inline void timer5_disable(void) { TIMSK5 &= ~_BV(TOIE5); }; #endif /////////////////////////////////////////////////// // Serial I/O //extern char kbhit(void); //extern void serial0_init(unsigned long); //extern FILE* serial_init(uint8_t port, unsigned long baud_rate); extern FILE* serial_init_buffered(uint8_t port, unsigned long baud_rate, uint8_t buf_size_in, uint8_t buf_size_out); //extern int8_t serial_input_waiting(FILE *fp); extern int8_t serial_buffered_input_waiting(FILE *fp); extern int16_t serial_buffered_output_free(FILE* fp); extern int16_t serial_buffered_input_nbytes(FILE* fp); extern void serial_receive_isr(struct OU_FILE_BUF *fp); extern void serial_transmit_isr(struct OU_FILE_BUF *fp); /////////////////////////////////////////////////// // ADC extern void adc_set_reference(uint8_t ref); #define ADC_REF_AREF 0x0 #define ADC_REF_AREF_CAP 0x1 #define ADC_REF_2p56V 0x3 extern void adc_set_adlar(uint8_t adlar); #define ADC_ADLAR_RIGHT 0 #define ADC_ADLAR_LEFT 1 extern void adc_set_channel(uint8_t chan); // Not clear that we need this ifdef #ifdef atmega8 #define ADC_CHANNEL_0 0x0 #define ADC_CHANNEL_1 0x1 #define ADC_CHANNEL_2 0x2 #define ADC_CHANNEL_3 0x3 #define ADC_CHANNEL_4 0x4 #define ADC_CHANNEL_5 0x5 #define ADC_CHANNEL_6 0x6 #define ADC_CHANNEL_7 0x7 #define ADC_CHANNEL_1p23V 0xE #define ADC_CHANNEL_0V 0xF #else #define ADC_CHANNEL_0 0x0 #define ADC_CHANNEL_1 0x1 #define ADC_CHANNEL_2 0x2 #define ADC_CHANNEL_3 0x3 #define ADC_CHANNEL_4 0x4 #define ADC_CHANNEL_5 0x5 #define ADC_CHANNEL_6 0x6 #define ADC_CHANNEL_7 0x7 #define ADC_CHANNEL_1p1V 0xE #define ADC_CHANNEL_0V 0xF #endif #ifdef ADC_CHANS_16 #define ADC_CHANNEL_8 0x20 #define ADC_CHANNEL_9 0x21 #define ADC_CHANNEL_10 0x22 #define ADC_CHANNEL_11 0x23 #define ADC_CHANNEL_12 0x24 #define ADC_CHANNEL_13 0x25 #define ADC_CHANNEL_14 0x26 #define ADC_CHANNEL_15 0x27 #endif extern void adc_set_enable(uint8_t cmd); #define ADC_ENABLE 1 #define ADC_DISABLE 0 /** Initiate an analog-to-digital conversion.

Assumptions: the ADC has been configured. @author Andrew H. Fagg \ingroup adc */ inline void adc_start_conversion(void) { ADCSRA = ADCSRA | 0x40; } /** Returns the state of the ADC interrupt flag (indicates whether a conversion has been completed). Should only be used when the ISR is not being used. @return 1 if the conversion is complete
0 if not complete @author Andrew H. Fagg \ingroup adc */ inline uint8_t adc_interrupt_flag(void) { return((ADCSRA&0x10) >> 4); }; extern void adc_set_auto_trigger(uint8_t cmd); #define ADC_AUTO_TRIGGER_ENABLE 1 #define ADC_AUTO_TRIGGER_DISABLE 0 extern void adc_interrupt_enable(uint8_t cmd); #define ADC_INTERRUPT_ENABLE 1 #define ADC_INTERRUPT_DISABLE 0 extern void adc_set_prescalar(uint8_t cmd); #define ADC_PRESCALAR_2 0 // Correct? docs say this is factor 2 *** //#define ADC_PRESCALAR_2 1 #define ADC_PRESCALAR_4 2 #define ADC_PRESCALAR_8 3 #define ADC_PRESCALAR_16 4 #define ADC_PRESCALAR_32 5 #define ADC_PRESCALAR_64 6 #define ADC_PRESCALAR_128 7 extern uint16_t adc_read(void); #ifdef atmega88 extern void adc_set_trigger_source(uint8_t cmd); #define ADC_TRIGGER_MODE_FREE 0x0 #define ADC_TRIGGER_MODE_ACOMP 0x1 #define ADC_TRIGGER_MODE_EXTINT 0x2 #define ADC_TRIGGER_MODE_TC0A 0x3 #define ADC_TRIGGER_MODE_TC0O 0x4 #define ADC_TRIGGER_MODE_TC1B 0x5 #define ADC_TRIGGER_MODE_TC1O 0x6 #define ADC_TRIGGER_MODE_TCCE 0x7 #define TIMSK_SINGLE #define CPU_DEFINED extern void adc_set_digital_disable(uint8_t cmd); #endif #ifdef atmega8 #define TIMSK_SINGLE #define CPU_DEFINED #endif ///////////////////////////////////////////////////////////////////////// // TWI interface #define TWI_INTERRUPT_ENABLE (_BV(TWIE)) #define TWI_INTERRUPT_DISABLE 0 extern void twi_send_start(void); extern void twi_wait_twint(void); extern void twi_send_byte(uint8_t val); extern void twi_send_stop(void); extern void twi_interrupt_config(uint8_t cmd); extern void twi_set_prescalar(uint8_t pre); #define TWI_PRESCALAR_1 0 #define TWI_PRESCALAR_4 (_BV(TWPS0)) #define TWI_PRESCALAR_16 (_BV(TWPS1)) #define TWI_PRESCALAR_64 (_BV(TWPS0) | _BV(TWPS1)) extern void twi_set_ack(uint8_t ack); #define TWI_ACKNOWLEDGE_ENABLE (_BV(TWEA)) #define TWI_ACKNOWLEDGE_DISABLE 0 //////////////////////////////////////////////////////////// // Static inline definitions /** Enable the timer 0 overflow interrupt. @author Andrew H. Fagg \ingroup timer0 */ inline void timer0_enable(void) { #ifdef TIMSK_SINGLE TIMSK |= _BV(TOIE0); #else // We will assume that this is the case until we know otherwise TIMSK0 |= _BV(TOIE0); #endif }; /** Disable the timer 0 overflow interrupt. @author Andrew H. Fagg \ingroup timer0 */ inline void timer0_disable(void) { #ifdef TIMSK_SINGLE TIMSK &= ~_BV(TOIE0); #else TIMSK0 &= ~_BV(TOIE0); #endif }; /** Read the state of the timer 0 counter @return The current state of the timer 0 counter @author Andrew H. Fagg \ingroup timer0 */ inline uint8_t timer0_read(void) { return(TCNT0); }; /** Set the state of the timer 0 counter @param val The new value of the timer 0 counter. @author Andrew H. Fagg \ingroup timer0 */ inline void timer0_set(uint8_t val) { TCNT0 = val; }; /** Enable the timer 1 overflow interrupt. @author Andrew H. Fagg \ingroup timer1 */ inline void timer1_enable(void) { #ifdef TIMSK_SINGLE TIMSK |= _BV(TOIE1); #else TIMSK1 |= _BV(TOIE1); //PRR &= ~_BV(PRTIM1); /// What is this? **** AHF: removed 4/1/9 #endif }; /** Disable the timer 1 overflow interrupt. @author Andrew H. Fagg \ingroup timer1 */ inline void timer1_disable(void) { #ifdef TIMSK_SINGLE TIMSK &= ~_BV(TOIE1); #else TIMSK1 &= ~_BV(TOIE1); #endif }; /** Enable the timer 1 output compare unit A interrupt. @author Andrew H. Fagg \ingroup timer1 */ inline void timer1_output_compare_A_enable(void) { #ifdef TIMSK_SINGLE TIMSK |= _BV(OCIE1A); #else TIMSK1 |= _BV(OCIE1A); // Need to check *** //#warning "Unchecked implementation" #endif }; /** Disable the timer 1 output compare unit A interrupt. @author Andrew H. Fagg \ingroup timer1 */ inline void timer1_output_compare_A_disable(void) { #ifdef TIMSK_SINGLE TIMSK &= ~_BV(OCIE1A); #else TIMSK1 &= ~_BV(OCIE1A); // Need to check **** //#warning "Unchecked implementation" #endif }; /** Enable the timer 1 output compare unit B interrupt. @author Andrew H. Fagg \ingroup timer1 */ inline void timer1_output_compare_B_enable(void) { #ifdef TIMSK_SINGLE TIMSK |= _BV(OCIE1B); #else TIMSK1 |= _BV(OCIE1B); // Need to check *** // #warning "Unchecked implementation" #endif }; /** Disable the timer 1 output compare unit B interrupt. @author Andrew H. Fagg \ingroup timer1 */ inline void timer1_output_compare_B_disable(void) { #ifdef TIMSK_SINGLE TIMSK &= ~_BV(OCIE1B); #else TIMSK1 &= ~_BV(OCIE1B); // Need to check *** // #warning "Unchecked implementation" #endif }; /** Enable the timer 2 overflow interrupt. @author Andrew H. Fagg \ingroup timer2 */ inline void timer2_enable(void) { #ifdef TIMSK_SINGLE TIMSK |= _BV(TOIE2); #else TIMSK2 |= _BV(TOIE2); #endif }; /** Disable the timer 2 overflow interrupt. @author Andrew H. Fagg \ingroup timer2 */ inline void timer2_disable(void) { #ifdef TIMSK_SINGLE TIMSK &= ~_BV(TOIE2); #else TIMSK2 &= ~_BV(TOIE2); #endif }; /** Read the state of the timer 2 counter @return The current state of the timer 2 counter @author Andrew H. Fagg \ingroup timer2 */ inline uint8_t timer2_read(void) { return(TCNT2); }; /** Set the state of the timer 2 counter @param val The new value of the timer 2 counter. @author Andrew H. Fagg \ingroup timer2 */ inline void timer2_set(uint8_t val) { TCNT2 = val; }; ////////////////// // TWI /** Return the TWINT status bit. @return 0: not ready
non-zero (_BV(TWINT)): ready. @author Andrew H. Fagg \ingroup twi */ inline uint8_t twi_get_twint(void) { return(TWCR & _BV(TWINT)); }; /** Return the status register @return The value of the TWI status register. @author Andrew H. Fagg \ingroup twi */ inline uint8_t twi_get_status(void) { return(TWSR & 0xf8); }; /** Return the byte received from the twi transaction @return Last byte received. @author Andrew H. Fagg \ingroup twi */ inline uint8_t twi_get_byte(void) { return(TWDR); }; /** Set the state of the TWCR register @param val The value to set TWCR to. @author Andrew H. Fagg \ingroup twi */ inline void twi_set_state(uint8_t val) { TWCR = val; }; /** Get the state of the TWCR register @return The state of the TWCR register. @author Andrew H. Fagg \ingroup twi */ inline uint8_t twi_get_state(void) { return(TWCR); }; /** Get the stop state of the TWI device. @return The stop state: 0 or _BF(TWSTO) @author Andrew H. Fagg \ingroup twi */ inline uint8_t twi_get_stop(void) { return(TWCR & _BV(TWSTO)); }; /** Set the TWI data transmission rate @param rate Transmission rate @author Andrew H. Fagg \ingroup twi */ inline void twi_set_rate(uint8_t rate) { TWBR = rate; } /** Set the slave address @param address Slave address @author Andrew H. Fagg \ingroup twi */ inline void twi_set_address(uint8_t address) { TWAR = address; }; /** Force the twi device to initiate a transaction immediately. We assume that the device has already been configured @author Andrew H. Fagg \ingroup twi */ inline void twi_set_twint(void) { TWCR |= _BV(TWINT); }; ///////////////////////////////////////////////////////////////// // SPI /** Enable the SPI device interrupt @author Andrew H. Fagg \ingroup spi */ #define spi_interrupt_enable() (SPCR |= _BV(SPIE)) /** Disable the SPI device interrupt @author Andrew H. Fagg \ingroup spi */ #define spi_interrupt_disable() (SPCR &= ~_BV(SPIE)) /** Enable the SPI hardware device @author Andrew H. Fagg \ingroup spi */ #define spi_enable() (SPCR |= _BV(SPE)) /** Disable the SPI hardware device @author Andrew H. Fagg \ingroup spi */ #define spi_disable() (SPCR |= _BV(SPE)) /** Configure SPI data order to be MSB first @author Andrew H. Fagg \ingroup spi */ #define spi_data_order_msb_first() (SPCR &= ~_BV(DORD)) /** Configure SPI data order to be LSB first (default). @author Andrew H. Fagg \ingroup spi */ #define spi_data_order_lsb_first() (SPCR |= _BV(DORD)) /** Configure SPI device as a master. @author Andrew H. Fagg \ingroup spi */ #define spi_mode_master() (SPCR |= _BV(MSTR)) /** Configure SPI device as a slave. @author Andrew H. Fagg \ingroup spi */ #define spi_mode_slave() (SPCR &= ~_BV(MSTR)) /** Configure SPI device with clock idle high. @author Andrew H. Fagg \ingroup spi */ #define spi_clock_idle_high() (SPCR |= _BV(CPOL)) /** Configure SPI device with clock idle low (default). @author Andrew H. Fagg \ingroup spi */ #define spi_clock_idle_low() (SPCR &= ~_BV(CPOL)) /** Configure SPI device with sample leading the clock edge (default). @author Andrew H. Fagg \ingroup spi */ #define spi_clock_sample_leading() (SPCR &= ~_BV(CPHA)) /** Configure SPI device with sample trailing the clock edge. @author Andrew H. Fagg \ingroup spi */ #define spi_clock_sample_trailing() (SPCR |= _BV(CPHA)) #define SPI_PRE_2 4 #define SPI_PRE_4 0 #define SPI_PRE_8 5 #define SPI_PRE_16 1 #define SPI_PRE_32 6 #define SPI_PRE_64 2 #define SPI_PRE_64b 7 #define SPI_PRE_128 3 extern void spi_prescale_config(uint8_t prescale); /** Check whether a write collision occurred. @return 0: no collision has occurred
1: a collision has occurred @author Andrew H. Fagg \ingroup spi */ #define spi_write_collision_p() ((SPSR >> WCOL) & 0x1) //////////////////////////////////////////////////////// #endif