aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2025-11-10 18:04:50 -0500
committerSam Anthony <sam@samanthony.xyz>2025-11-10 18:04:50 -0500
commitd69740f148892a28c543afed7eda4ba9b5a5e4e2 (patch)
tree474aa77bdb440f257b6b4f2ba3d4ee3d9d2356ce
parent595c1e7eba19ab8a780e3387cc389583837a42f0 (diff)
downloadcan-gauge-interface-d69740f148892a28c543afed7eda4ba9b5a5e4e2.zip
generate speedometer signal
-rw-r--r--fw/main.c39
-rw-r--r--fw/system.c4
-rw-r--r--fw/system.h4
-rw-r--r--fw/tests/system/speed_systest.c48
4 files changed, 90 insertions, 5 deletions
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 <xc.h>
+
+#include <stdint.h>
+
+#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;
+ }
+}