From d69740f148892a28c543afed7eda4ba9b5a5e4e2 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Mon, 10 Nov 2025 18:04:50 -0500 Subject: generate speedometer signal --- fw/main.c | 39 ++++++++++++++++++++++++++++++--- fw/system.c | 4 +++- fw/system.h | 4 +++- fw/tests/system/speed_systest.c | 48 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 fw/tests/system/speed_systest.c (limited to 'fw') diff --git a/fw/main.c b/fw/main.c index ff2d754..c0e750e 100644 --- a/fw/main.c +++ b/fw/main.c @@ -23,14 +23,23 @@ #define SIG_CTRL_CAN_ID 0x1272100 // Signal Control Frame ID #define ERR_CAN_ID 0x1272F00 +// Tachometer -- TMR1 // (pulse/min) = 60 * (Fosc/4) / ((pre)*(post)*(2^16 - TMR1)) // = 60 * (48e6/4) / (8*6*(2^16 - TMR1)) // = 15000000 / (2^16 - TMR1) #define TACH_FACTOR 15000000ul #define TMR1_POST 6u // TMR1 postscaler -- must be multiple of 2 -#define EDGE_PER_PULSE 2u // rising and falling edge #define MIN_TACH_PULSE_PER_MIN 229u // (pulse/min) >= TACH_FACTOR / (2^16) +// Speedometer -- TMR2 +// (pulse/min) = 60 * (Fosc/4) / ((pre)*(post)*(PR2+1)*(period)) +// = 60 * (48e6/4) / (64*16*10*(period)) +// = 70313 / (period) +#define SPEED_FACTOR 70313ul +#define MIN_SPEED_PULSE_PER_MIN 2u // (pulse/min) >= SPEED_FACTOR / period_max) + +#define EDGE_PER_PULSE 2u // rising and falling edge + // Signals typedef enum { SIG_TACH = 0, @@ -96,6 +105,7 @@ static const EepromAddr sigFmtAddrs[NSIG] = { static volatile SigFmt sigFmts[NSIG]; static volatile U16 tmr1Start = 0u; +static volatile U16 tmr2Period = 0u; // Load signals' encoding formats and CAN IDs from EEPROM static Status @@ -170,6 +180,10 @@ main(void) { // Setup TMR1 for tachometer T1CON = 0x31; // source=Fosc/4, prescaler=1:8, enable=1 + // Setup TMR2 for speedometer + T2CON = 0x7F; // postscaler=1:16, enable=1, prescaler=1:64 + PR2 = 10u-1u; // period = PR2+1 + // Enable interrupts INTCON = 0x00; // clear flags OPTION_REGbits.INTEDG = 0; // interrupt on falling edge of INT pin @@ -333,6 +347,17 @@ driveTach(U16 pulsePerMin) { } } +// Set frequency of speedometer output signal. +static void +driveSpeed(U16 pulsePerMin) { + if (pulsePerMin < MIN_SPEED_PULSE_PER_MIN) { + TMR2IE = 0; + } else { + TMR2IE = 1; + tmr2Period = ((U32)SPEED_FACTOR / pulsePerMin) & 0xFFFF; + } +} + // Generate the output signal being sent to one of the gauges. // Raw is the raw signal value extracted from a CAN frame. static Status @@ -366,7 +391,7 @@ driveGauge(Signal sig, I32 raw) { driveTach(val); break; case SIG_SPEED: - // TODO + driveSpeed(val); break; case SIG_AN1: dacSet1a(val); @@ -416,6 +441,7 @@ handleSigFrame(const CanFrame *frame) { void __interrupt() isr(void) { static U8 tmr1Ctr = 0u; + static U16 tmr2Ctr = 0u; U8 rxStatus; CanFrame frame; @@ -445,7 +471,7 @@ __interrupt() isr(void) { INTF = 0; // clear flag } if (TMR1IF) { // tachometer - if (++tmr1Ctr == (TMR1_POST/EDGE_PER_PULSE)) { + if (++tmr1Ctr >= (TMR1_POST/EDGE_PER_PULSE)) { tmr1Ctr = 0u; TACH_PIN ^= 1; // toggle tach output } @@ -453,4 +479,11 @@ __interrupt() isr(void) { TMR1L = (tmr1Start>>0u)&0xFF; TMR1IF = 0; } + if (TMR2IF) { // speedometer + if (++tmr2Ctr >= (tmr2Period/EDGE_PER_PULSE)) { + tmr2Ctr = 0u; + SPEED_PIN ^= 1; // toggle speedometer output + } + TMR2IF = 0; + } } diff --git a/fw/system.c b/fw/system.c index 7921d5a..4f97507 100644 --- a/fw/system.c +++ b/fw/system.c @@ -35,6 +35,8 @@ sysInit(void) { ANSELC = 0; // Init pins - TACH_TRIS = OUT; + TACH_TRIS = OUT; // tachometer TACH_PIN = 0; + SPEED_TRIS = OUT; // speedometer + SPEED_PIN = 0; } diff --git a/fw/system.h b/fw/system.h index 897a4b4..7e93c01 100644 --- a/fw/system.h +++ b/fw/system.h @@ -4,8 +4,10 @@ #include "fixed_address_memory.h" // Pins -#define TACH_PIN RC3 +#define TACH_PIN RC3 // tachometer #define TACH_TRIS TRISC3 +#define SPEED_PIN RC4 // speedometer +#define SPEED_TRIS TRISC4 // TRIS enum { diff --git a/fw/tests/system/speed_systest.c b/fw/tests/system/speed_systest.c new file mode 100644 index 0000000..72fb271 --- /dev/null +++ b/fw/tests/system/speed_systest.c @@ -0,0 +1,48 @@ +#include + +#include + +#include "system.h" +#include "types.h" + +// (pulse/min) = 60 * (Fosc/4) / ((pre)*(post)*(PR2+1)*(period)) +// = 60 * (48e6/4) / (64*16*10*(period)) +// = 70313 / (period) +#define SPEED_FACTOR 70313ul +#define MIN_SPEED_PULSE_PER_MIN 2u // (pulse/min) >= SPEED_FACTOR / period_max) +#define EDGE_PER_PULSE 2u // rising and falling edge + +static volatile U16 tmr2Period = 0u; + +void +main(void) { + sysInit(); + + U16 pulsePerMin = 550u; + tmr2Period = ((U32)SPEED_FACTOR / pulsePerMin) & 0xFFFF; + + T2CON = 0x7F; // postscaler=1:16, enable=1, prescaler=1:64 + PR2 = 10u-1u; // period = PR2+1 + + INTCON = 0x00; + PIE1bits.TMR2IE = 1; + INTCONbits.PEIE = 1; + INTCONbits.GIE = 1; + + for (;;) { + + } +} + +void __interrupt() +isr(void) { + static U16 tmr2Ctr = 0u; + + if (TMR2IF) { // speedometer + if (++tmr2Ctr >= (tmr2Period/EDGE_PER_PULSE)) { + tmr2Ctr = 0u; + SPEED_PIN ^= 1; // toggle speedometer output + } + TMR2IF = 0; + } +} -- cgit v1.2.3