Untitled
unknown
c_cpp
4 years ago
4.7 kB
16
Indexable
/* Defines */
#define LED PORTA.F0
#define BTN PORTB.F0
#define OUTPUT LED /* Output is the LED */
#define enable_interrupts() INTCON.GIE = 1 /* Enable global interrupts */
#define disable_interrupts() INTCON.GIE = 0 /* Disable global interrupts */
#define BTN_TIME (32/TIMESTEP) /* 32ms button debounce */
#define TMR0_PRELOAD 131 /* Timer 0 preload */
#define TIMESTEP 8 /* 8ms step */
#define DELAY_TIME (10000/TIMESTEP) /* 10s delay */
#define UP_TIME (30000/TIMESTEP) /* 30s up time */
#define DOWN_TIME (30000/TIMESTEP) /* 30s down time */
/* Variables */
struct{
volatile unsigned int timer0; // volatile because it's modified inside an interrupt
volatile unsigned int button;
unsigned int output;
unsigned int now;
}count;
union{
unsigned char data;
struct{
unsigned enable:1;
unsigned button:1;
unsigned output:1;
unsigned delay:1;
};
} status;
/* Functions */
void clearTimer0(void){
disable_interrupts();
count.timer0 = 0; // Clear Timer0 counter
enable_interrupts();
}
void initTimer0(void){ // Default internal clock = 4MHz, (1 MIPS, CLKOUT=1MHz)
OPTION_REG = 0x05; // TMR0 source = CLKOUT, 1:64, WDT = 1:32. Timer0 clock = 15625Hz
INTCON = 0b10110000; // GIE=1, T0IE=1, RB0/INT=1
TMR0 = TMR0_PRELOAD; // 15625Hz / ((255-131)+1) = 125Hz = 8ms
clearTimer0();
}
void toggle_state(void){
clearTimer0();
if(status.output){
status.output = 0; // Clear state
OUTPUT = 0; // Disable output
}
else{
status.output = 1; // Set state
OUTPUT = 1; // Enable output
}
}
/* ISR */
void Interrupt(void){
if (TMR0IF_bit)
{
TMR0 = TMR0_PRELOAD;
TMR0IF_bit = 0;
count.timer0++;
count.button++;
}
}
/* Main */
void main() {
TRISA.F0=0;
TRISB.F0=1;
TRISB.F1=0;
TRISA.F1=0;
PORTA.F1=0;
LED=0;
InitTimer0(); // Init and start Timer0
while(1) {
/* Read Timer0 counter at the start of the loop */
disable_interrupts(); // Interrupts must be paused when handling timer0 and button counters
count.now = count.timer0; // Save counter status
enable_interrupts();
/* Handle button update and debouncing */
if(status.button != BTN){ // If button changed from last stored state
if(count.button >= BTN_TIME){ // If button debounce time elapsed
status.button = BTN; // Update stored state and take action
if(!status.button){ // Stop state?
count.out = count.now; // Save counter status into output counter variable
status.enable = 0; // Disabled state
OUTPUT = 0; // Disable output
}
else{ // Run state?
clearTimer0(); // Clear timer
status.enable = 1; // Enabled state
status.delay = 1; // Enable delay
}
}
}
else{ // Button didn't change
disable_interrupts();
count.button = 0; // Clear button counter
enable_interrupts();
}
/* If enabled, handle delay and output signal */
if(status.enable){
if(status.delay){
if(now >= DELAY_TIME { // If counter >= delay time
status.delay = 0; // Delay done, clear flag
disable_interrupts();
count.timer0 = count.out; // Restore counter status from output counter variable
enable_interrupts();
if(status.output){ // Restore output state
OUTPUT = 1;
}
}
}
else{ // Running
if(status.output){ // If output high
if(count.now >= UP_TIME) { // Check for elapsed up time
toggle_state();
}
}
else{ // If output low
if(count.now >= DOWN_TIME) { // Check for elapsed down time
toggle_state();
}
}
}
}
}
}Editor is loading...