| 163 |
Kevin |
1 |
#include <xc.h>
|
|
|
2 |
#include "defines.h"
|
|
|
3 |
#include "base_CPS.h"
|
|
|
4 |
|
|
|
5 |
static CPS_DATA *cps_data_p;
|
|
|
6 |
|
|
|
7 |
void CPS_Init(CPS_DATA* data) {
|
|
|
8 |
cps_data_p = data;
|
|
|
9 |
for (char i = 0; i < 4; i++) {
|
|
|
10 |
cps_data_p->btn_pressed[i] = 0;
|
|
|
11 |
cps_data_p->btn_last_value[i] = 0;
|
|
|
12 |
cps_data_p->btn_avg_value[i] = 0;
|
|
|
13 |
cps_data_p->btn_pct_value[i] = 0;
|
|
|
14 |
}
|
|
|
15 |
|
|
|
16 |
/* Initialize port direction */
|
|
|
17 |
CPS_0_TRIS = 1;
|
|
|
18 |
CPS_1_TRIS = 1;
|
|
|
19 |
|
|
|
20 |
/* Initialize FVR for the upper threshold (Ref+) */
|
|
|
21 |
FVRCONbits.CDAFVR = 0b01; // Gain of 1x (1.024V)
|
|
|
22 |
FVRCONbits.FVREN = 1; // Enable FVR module
|
|
|
23 |
|
| 271 |
Kevin |
24 |
/* Initialize DAC for the lower threshold (Ref-) to Vss */
|
| 163 |
Kevin |
25 |
DACCON0bits.DACEN = 0; // Disable DAC
|
|
|
26 |
DACCON0bits.DACLPS = 0; // Negative reference source selected
|
|
|
27 |
DACCON0bits.DACOE = 0; // Output not routed to DACOUT pin
|
| 271 |
Kevin |
28 |
DACCON0bits.DACPSS = 0b00; // Vss used as positive source
|
| 163 |
Kevin |
29 |
// DACCON0bits.DACNSS = 0; // Vss used as negative source
|
| 271 |
Kevin |
30 |
// Output voltage formula:
|
|
|
31 |
// V_out = ((V_source+ - V_source-) * (DACR / 32)) + V_source-
|
|
|
32 |
DACCON1bits.DACR = 0b00000; // Voltage output set to 0v
|
| 163 |
Kevin |
33 |
|
| 271 |
Kevin |
34 |
// /* Initialize DAC for the lower threshold (Ref-) to variable setting */
|
|
|
35 |
// DACCON0bits.DACEN = 1; // Enable DAC
|
|
|
36 |
// DACCON0bits.DACLPS = 1; // Positive reference source selected
|
|
|
37 |
// DACCON0bits.DACOE = 0; // Output not routed to DACOUT pin
|
|
|
38 |
// DACCON0bits.DACPSS = 0b10; // FVR buffer2 used as positive source
|
|
|
39 |
//// DACCON0bits.DACNSS = 0; // Vss used as negative source
|
|
|
40 |
// // Output voltage formula:
|
|
|
41 |
// // V_out = ((V_source+ - V_source-) * (DACR / 32)) + V_source-
|
|
|
42 |
// DACCON1bits.DACR = 0b10000; // Voltage output set to 0.512v
|
|
|
43 |
|
| 163 |
Kevin |
44 |
/* Initialize Timer 0 */
|
|
|
45 |
OPTION_REGbits.TMR0CS = 0; // Clock source is FOSC/4
|
|
|
46 |
OPTION_REGbits.PSA = 0; // Prescaler enabled
|
|
|
47 |
OPTION_REGbits.PS = 0b111; // Prescaler of 1:256
|
|
|
48 |
|
|
|
49 |
/* Initialize Timer 1 */
|
|
|
50 |
T1CONbits.TMR1CS = 0b11; // Clock source is Capacitive Sensing Oscillator
|
|
|
51 |
T1CONbits.T1CKPS = 0b00; // 1:1 Prescale value
|
|
|
52 |
T1GCONbits.TMR1GE = 1; // Counting is controlled by the gate function
|
|
|
53 |
T1GCONbits.T1GPOL = 1; // Gate is active high
|
|
|
54 |
T1GCONbits.T1GTM = 1; // Gate toggle mode is enabled
|
|
|
55 |
T1GCONbits.T1GSPM = 0; // Gate single-pulse mode is disabled
|
|
|
56 |
T1GCONbits.T1GSS = 0b01; // Gate source is Timer 0 overflow
|
|
|
57 |
T1CONbits.TMR1ON = 1; // Enables timer 1
|
|
|
58 |
|
|
|
59 |
/* Initialize CPS Module */
|
|
|
60 |
CPSCON0bits.CPSRM = 1; // DAC and FVR used for Vref- and Vref+
|
|
|
61 |
CPSCON0bits.CPSRNG = 0b11; // Osc in high range (100uA)
|
|
|
62 |
CPSCON0bits.T0XCS = 0; // Timer 0 clock runs at FOSC/4
|
|
|
63 |
CPSCON1bits.CPSCH = 0b00; // Channel 0 (CPS0)
|
|
|
64 |
cps_data_p->channel = 0;
|
|
|
65 |
CPSCON0bits.CPSON = 1; // CPS module is enabled
|
|
|
66 |
|
|
|
67 |
/* Initialize timer interrupts and clear timers */
|
|
|
68 |
INTCONbits.TMR0IE = 1; // Timer 0 interrupt enabled
|
|
|
69 |
PIE1bits.TMR1IE = 0; // Timer 1 interrupt disabled
|
|
|
70 |
CPS_Reset();
|
|
|
71 |
}
|
|
|
72 |
|
|
|
73 |
void CPS_Timer_0_Interrupt_Handler() {
|
|
|
74 |
unsigned int value = TMR1;
|
|
|
75 |
long percent;
|
|
|
76 |
|
|
|
77 |
if (value < 10) {
|
|
|
78 |
return;
|
|
|
79 |
}
|
|
|
80 |
|
|
|
81 |
// Calculate percentage change
|
|
|
82 |
percent = (long)cps_data_p->btn_avg_value[cps_data_p->channel]-(long)value;
|
|
|
83 |
if (percent < 0)
|
|
|
84 |
percent = 0;
|
|
|
85 |
else {
|
|
|
86 |
percent *= 100;
|
|
|
87 |
percent /= cps_data_p->btn_avg_value[cps_data_p->channel];
|
|
|
88 |
}
|
|
|
89 |
|
|
|
90 |
cps_data_p->btn_last_value[cps_data_p->channel] = value;
|
|
|
91 |
cps_data_p->btn_pct_value[cps_data_p->channel] = percent;
|
|
|
92 |
|
|
|
93 |
if (percent < CPS_PCT_OFF) {
|
|
|
94 |
// Calculate average
|
|
|
95 |
cps_data_p->btn_avg_value[cps_data_p->channel] =
|
|
|
96 |
cps_data_p->btn_avg_value[cps_data_p->channel] +
|
|
|
97 |
((long)value - (long)cps_data_p->btn_avg_value[cps_data_p->channel])
|
|
|
98 |
/CPS_AVG_COUNT;
|
|
|
99 |
// Set flag to indicate that button is not pressed
|
|
|
100 |
cps_data_p->btn_pressed[cps_data_p->channel] = 0;
|
| 271 |
Kevin |
101 |
} else if (percent > CPS_PCT_ON) {
|
| 163 |
Kevin |
102 |
// Set flag to indicate that button was pressed
|
|
|
103 |
cps_data_p->btn_pressed[cps_data_p->channel] = 1;
|
| 271 |
Kevin |
104 |
}
|
| 163 |
Kevin |
105 |
|
|
|
106 |
cps_data_p->channel = cps_data_p->channel + 1;
|
|
|
107 |
if (cps_data_p->channel == CPS_NUM_CHANNELS)
|
|
|
108 |
cps_data_p->channel = 0;
|
|
|
109 |
|
|
|
110 |
CPSCON1bits.CPSCH = cps_data_p->channel;
|
|
|
111 |
|
|
|
112 |
CPS_Reset();
|
|
|
113 |
}
|
|
|
114 |
|
|
|
115 |
void CPS_Reset() {
|
|
|
116 |
TMR1 = 0;
|
|
|
117 |
TMR0 = 0;
|
|
|
118 |
}
|
|
|
119 |
|
|
|
120 |
void CPS_Enable() {
|
|
|
121 |
INTCONbits.TMR0IE = 1; // Timer 0 interrupt enabled
|
|
|
122 |
T1CONbits.TMR1ON = 1;
|
|
|
123 |
CPSCON0bits.CPSON = 1;
|
|
|
124 |
CPS_Reset();
|
|
|
125 |
}
|
|
|
126 |
|
|
|
127 |
void CPS_Disable() {
|
|
|
128 |
INTCONbits.TMR0IE = 0;
|
|
|
129 |
CPSCON0bits.CPSON = 0;
|
|
|
130 |
T1CONbits.TMR1ON = 0;
|
|
|
131 |
}
|