Lots of development of new features. Radio input, motor output, PID control
loops, boot-time initialisation, option to run without attached UART. And.. it flies!
This commit is contained in:
172
timer.c
172
timer.c
@@ -3,8 +3,12 @@
|
||||
#include "uart.h"
|
||||
#include "event.h"
|
||||
|
||||
#define FP0XVAL (*((volatile unsigned int *) 0x3FFFC014))
|
||||
|
||||
#define TIMER0BASE 0xE0004000
|
||||
#define TIMER1BASE 0xE0008000
|
||||
#define TIMER2BASE 0xE0070000
|
||||
#define TIMER3BASE 0xE0074000
|
||||
|
||||
#define IR 0x00
|
||||
#define TCR 0x04
|
||||
@@ -28,6 +32,15 @@
|
||||
#define TREG(x) (((volatile unsigned char *)TIMER0BASE)[x])
|
||||
#define TWREG(x) (((volatile unsigned int *)TIMER0BASE)[(x)/sizeof(unsigned int)])
|
||||
|
||||
#define T1REG(x) (((volatile unsigned char *)TIMER1BASE)[x])
|
||||
#define T1WREG(x) (((volatile unsigned int *)TIMER1BASE)[(x)/sizeof(unsigned int)])
|
||||
|
||||
#define T2REG(x) (((volatile unsigned char *)TIMER2BASE)[x])
|
||||
#define T2WREG(x) (((volatile unsigned int *)TIMER2BASE)[(x)/sizeof(unsigned int)])
|
||||
|
||||
#define T3REG(x) (((volatile unsigned char *)TIMER3BASE)[x])
|
||||
#define T3WREG(x) (((volatile unsigned int *)TIMER3BASE)[(x)/sizeof(unsigned int)])
|
||||
|
||||
#define TCR_ENABLE (1<<0)
|
||||
#define TCR_RESET (1<<1)
|
||||
|
||||
@@ -44,7 +57,14 @@
|
||||
#define MR3R (1<<10)
|
||||
#define MR3S (1<<11)
|
||||
|
||||
|
||||
volatile unsigned int timer1_rising[4];
|
||||
volatile unsigned int timer1_width[4];
|
||||
|
||||
unsigned int timer_map[] = {0, 3, 2, 1};
|
||||
|
||||
void __attribute__((interrupt("IRQ"))) timer_interrupt_handler(void);
|
||||
void __attribute__((interrupt("IRQ"))) timer1_interrupt_handler(void);
|
||||
|
||||
void timer_event_handler(void);
|
||||
|
||||
@@ -58,6 +78,52 @@ void init_timer(void)
|
||||
TWREG(PC) = 0;
|
||||
|
||||
TREG(TCR) = TCR_ENABLE;
|
||||
|
||||
interrupt_register(TIMER1, timer1_interrupt_handler);
|
||||
|
||||
T1REG(TCR) = TCR_ENABLE | TCR_RESET;
|
||||
|
||||
T1REG(CTCR) = 0; /* Use PCLK */
|
||||
T1WREG(TC) = 0;
|
||||
T1WREG(PR) = TIMER_PRESCALE ;
|
||||
T1WREG(PC) = 0;
|
||||
|
||||
T1WREG(CCR) = 0x00000fff;
|
||||
|
||||
T1REG(TCR) = TCR_ENABLE;
|
||||
|
||||
T2REG(TCR) = TCR_ENABLE | TCR_RESET;
|
||||
T2REG(CTCR) = 0; /* Use PCLK */
|
||||
T2WREG(PR) = 0; // Prescaling
|
||||
T2WREG(PC) = 0; // Reset the prescale counter
|
||||
T2WREG(TC) = 0; // Reset the counter
|
||||
|
||||
T2WREG(MCR) = 0x0400; // Reset on MR3 match
|
||||
T2WREG(PWM) = 0x0000000d; // Enable PWMs
|
||||
|
||||
T2WREG(MR3) = PWM_PERIOD; // Period duration
|
||||
|
||||
/* This is chosen to be an invalid output. */
|
||||
T2WREG(MR1) = 1; // Pulse width
|
||||
T2WREG(MR0) = 1; // Pulse width
|
||||
|
||||
T3REG(TCR) = TCR_ENABLE | TCR_RESET;
|
||||
T3REG(CTCR) = 0; /* Use PCLK */
|
||||
T3WREG(PR) = 0; // Prescaling
|
||||
T3WREG(PC) = 0; // Reset the prescale counter
|
||||
T3WREG(TC) = 0; // Reset the counter
|
||||
|
||||
T3WREG(MCR) = 0x0010; // Reset on MR1 match
|
||||
T3WREG(PWM) = 0x0000000b; // Enable PWMs
|
||||
|
||||
T3WREG(MR1) = PWM_PERIOD; // Period duration
|
||||
|
||||
/* This is chosen to be an invalid output. */
|
||||
T3WREG(MR3) = 1; // Pulse width
|
||||
T3WREG(MR0) = 1; // Pulse width
|
||||
|
||||
T2REG(TCR) = TCR_ENABLE;
|
||||
T3REG(TCR) = TCR_ENABLE;
|
||||
}
|
||||
|
||||
unsigned int timer_read(void)
|
||||
@@ -92,3 +158,109 @@ void __attribute__((interrupt("IRQ"))) timer_interrupt_handler(void)
|
||||
|
||||
interrupt_clear();
|
||||
}
|
||||
|
||||
void __attribute__((interrupt("IRQ"))) timer1_interrupt_handler(void)
|
||||
{
|
||||
unsigned int ir;
|
||||
unsigned int gpio;
|
||||
ir = T1REG(IR);
|
||||
T1REG(IR) = ir;
|
||||
|
||||
gpio = FP0XVAL;
|
||||
|
||||
if (ir & (1<<4)) {
|
||||
/* Capture channel 0 */
|
||||
if (gpio & (1<<10)) {
|
||||
timer1_rising[0] = T1WREG(CR0);
|
||||
} else {
|
||||
timer1_width[0] = T1WREG(CR0) - timer1_rising[0];
|
||||
}
|
||||
}
|
||||
if (ir & (1<<5)) {
|
||||
/* Capture channel 1 */
|
||||
if (gpio & (1<<11)) {
|
||||
timer1_rising[1] = T1WREG(CR1);
|
||||
} else {
|
||||
timer1_width[1] = T1WREG(CR1) - timer1_rising[1];
|
||||
}
|
||||
}
|
||||
if (ir & (1<<6)) {
|
||||
/* Capture channel 2 */
|
||||
if (gpio & (1<<17)) {
|
||||
timer1_rising[2] = T1WREG(CR2);
|
||||
} else {
|
||||
timer1_width[2] = T1WREG(CR2) - timer1_rising[2];
|
||||
}
|
||||
}
|
||||
if (ir & (1<<7)) {
|
||||
/* Capture channel 3 */
|
||||
if (gpio & (1<<18)) {
|
||||
timer1_rising[3] = T1WREG(CR3);
|
||||
} else {
|
||||
timer1_width[3] = T1WREG(CR3) - timer1_rising[3];
|
||||
}
|
||||
}
|
||||
|
||||
interrupt_clear();
|
||||
}
|
||||
|
||||
bool timer_valid(int channel) {
|
||||
channel = TIMER_CH(channel);
|
||||
/* Be careful here to ensure that this can't be in the past */
|
||||
unsigned int chtime = timer1_rising[channel]; /* Atomic */
|
||||
unsigned int time = T1WREG(TC); /* Atomic */
|
||||
return (time - chtime) < TIMER_INPUT_TIMEOUT;
|
||||
}
|
||||
|
||||
bool timer_allvalid(void) {
|
||||
unsigned int time;
|
||||
unsigned int chtime[4];
|
||||
int i;
|
||||
/* Be careful here to ensure that this can't be in the past */
|
||||
for (i = 0; i < 4; i++)
|
||||
chtime[i] = timer1_rising[i];
|
||||
time = T1WREG(TC);
|
||||
for (i = 0; i < 4; i++)
|
||||
if ((time - chtime[i]) >= TIMER_INPUT_TIMEOUT)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void timer_set_pwm_value(int channel, int value)
|
||||
{
|
||||
value = PWM_PERIOD - (PWM_MAX + value);
|
||||
switch (channel) {
|
||||
case 0:
|
||||
T2WREG(MR2) = value;
|
||||
break;
|
||||
case 1:
|
||||
T2WREG(MR0) = value;
|
||||
break;
|
||||
case 2:
|
||||
T3WREG(MR3) = value;
|
||||
break;
|
||||
case 3:
|
||||
T3WREG(MR0) = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_set_pwm_invalid(int channel)
|
||||
{
|
||||
int value = 1;
|
||||
switch (channel) {
|
||||
case 0:
|
||||
T2WREG(MR2) = value;
|
||||
break;
|
||||
case 1:
|
||||
T2WREG(MR0) = value;
|
||||
break;
|
||||
case 2:
|
||||
T3WREG(MR3) = value;
|
||||
break;
|
||||
case 3:
|
||||
T3WREG(MR0) = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user