Files
bacnet_stack/ports/atmega328/timer.c
T
Steve Karg 4781582204 Changed ATmega168 port to ATmega328 on Uno R3 with DFR0259 RS485 shield (#784)
* Changed ATmega168 example for ATmega328 on Arduino Uno R3 with DFR0259 RS485 shield. Added ADC interface from BDK port and mapped to some AV objects. Removed MS/TP MAC address DIP switch GPIO and moved MS/TP configuration to AV objects. Added AV units property. Added some Uno R3 Digital Inputs and outputs mapped to some BV. Added AVR EEPROM from BDK port and mapped some non-volatile data including MAC address and max manager and baud rate, device ID and names and description and location.
2024-09-27 14:42:47 -05:00

102 lines
2.8 KiB
C

/**
* @brief This module handles the 1 millisecond timer for the mstimer library
* @author Steve Karg <skarg@users.sourceforge.net>
* @date 2007
* @copyright SPDX-License-Identifier: MIT
*/
#include <stdint.h>
#include "hardware.h"
#include "bacnet/basic/sys/mstimer.h"
/* Prescaling: 1, 8, 64, 256, 1024 */
#define TIMER_MICROSECONDS 1000UL
#define TIMER_TICKS(p) \
(((((F_CPU) / (p)) / 1000UL) * (TIMER_MICROSECONDS)) / 1000UL)
#define TIMER_TICKS_MAX 255UL
/* adjust the prescaler for the processor clock */
#if (TIMER_TICKS(1) <= TIMER_TICKS_MAX)
#define TIMER0_PRESCALER 1
#elif (TIMER_TICKS(8) <= TIMER_TICKS_MAX)
#define TIMER0_PRESCALER 8
#elif (TIMER_TICKS(64) <= TIMER_TICKS_MAX)
#define TIMER0_PRESCALER 64
#elif (TIMER_TICKS(256) <= TIMER_TICKS_MAX)
#define TIMER0_PRESCALER 256
#elif (TIMER_TICKS(1024) <= TIMER_TICKS_MAX)
#define TIMER0_PRESCALER 1024
#else
#error "TIMER0: F_CPU too large for timer prescaler."
#endif
#define TIMER0_TICKS TIMER_TICKS(TIMER0_PRESCALER)
/* Timer counts up from count to TIMER_TICKS_MAX and then signals overflow */
#define TIMER0_COUNT (TIMER_TICKS_MAX - TIMER0_TICKS)
/* millisecond time counter */
static volatile unsigned long Millisecond_Counter;
/* Configure the Timer */
void mstimer_init(void)
{
/* Normal Operation */
TCCR1A = 0;
/* CSn2 CSn1 CSn0 Description
---- ---- ---- -----------
0 0 0 No Clock Source
0 0 1 No prescaling
0 1 0 CLKio/8
0 1 1 CLKio/64
1 0 0 CLKio/256
1 0 1 CLKio/1024
1 1 0 Falling Edge of T0 (external)
1 1 1 Rising Edge of T0 (external)
*/
#if (TIMER0_PRESCALER == 1)
TCCR0B = _BV(CS00);
#elif (TIMER0_PRESCALER == 8)
TCCR0B = _BV(CS01);
#elif (TIMER0_PRESCALER == 64)
TCCR0B = _BV(CS01) | _BV(CS00);
#elif (TIMER0_PRESCALER == 256)
TCCR0B = _BV(CS02);
#elif (TIMER0_PRESCALER == 1024)
TCCR0B = _BV(CS02) | _BV(CS00);
#else
#error Timer0 Prescale: Invalid Value
#endif
/* Clear any TOV1 Flag set when the timer overflowed */
BIT_CLEAR(TIFR0, TOV0);
/* Initial value */
TCNT0 = TIMER0_COUNT;
/* Enable the overflow interrupt */
BIT_SET(TIMSK0, TOIE0);
/* Clear the Power Reduction Timer/Counter0 */
BIT_CLEAR(PRR, PRTIM0);
}
/* Timer interupt */
/* note: Global interupts must be enabled - sei() */
/* Timer Overflowed! Increment the time. */
ISR(TIMER0_OVF_vect)
{
/* Set the counter for the next interrupt */
TCNT0 = TIMER0_COUNT;
/* Overflow Flag is automatically cleared */
/* Update the global timer */
Millisecond_Counter++;
}
/**
* Get the current time in milliseconds
* @return milliseconds
*/
unsigned long mstimer_now(void)
{
unsigned long milliseconds;
BIT_CLEAR(TIMSK0, TOIE0);
milliseconds = Millisecond_Counter;
BIT_SET(TIMSK0, TOIE0);
return milliseconds;
}