//---------------------------------------------------------------------- //---------------------------------------------------------------------- // user interface test program // // This program uses 2 switches for user inputs and an LCD for user // output // // one switch is designated as the increment key and the other switch is // designated as the decrement key. // // A control value is displayed on the LCD. When the increment key is // pressed the control value is incremented. When the decrement key is // pressed the control value is decremented. when the control value // changes, the new value is displayed on the LCD // // // This program uses 3 tasks. Task 1 debounces the switches in the // background, task 2 handles the user output and task 3 handles // the user input. // // this program differs in functionality from lcd-tst-003.bas in that // there is a delay between a key press and the start of auto repeat. // Also whereas lcd-tst-003.bas incremented and decremented the control // value as quickly as possible, this program inserts a specific delay // between steps, giving the user much better control over the process. // // This program demonstrates how a program can be simplified and // responsiveness improved by spliting a program into seperate tasks. // It also gives examples of // interaction between tasks // using FIFOs to pass messages // using FIFO events in the task_wait statement //---------------------------------------------------------------------- //---------------------------------------------------------------------- include "hwreg-p16f628.h" // 16f628 config // enable internal oscillator FOSC2,FOSC1,FOSC0 = 100 // disable watchdog WDT = 0 // enable power up timer PWRTE = 0 // use MCLR as RA5 MCLRE = 0 // disable brown-out detect BODEN = 0 // low voltage prog disabled LVP = 0 // data memory not protected CPD = 1 // code memory not protected CP1,CP0,CP1,CP0 = 1111 // // see section 14.1 of PIC16F26X ref manual // microchip document name 40300b.pdf pragma cpu_config 0x3F10 include "strlib.bas" include "lcdlib.bas" include "fifo_lib.bas" FIFO switch_event_fifo[6] include "debounce.bas" // NOTE: the use of the user defined character 7 // this is because the LCD uses the yen symbol in // place of where the ASCII backslash would normally // be const char spin = "|/-", 7 // *.... // .*... // .*... // ..*.. // ...*. // ...*. // ....* // ..... const ubyte backslash_glyph = 0x10, 0x08, 0x08, 0x04, 0x02, 0x02, 0x01, 0x00 //---------------------------------------------------------------------- //---------------------------------------------------------------------- int ctl_val //---------------------------------------------------------------------- //---------------------------------------------------------------------- proc task_1() debounce_init(0xC0, 0x00, &switch_event_fifo) while 1 do debounce_queue_service() task_wait 1 done endproc //---------------------------------------------------------------------- //---------------------------------------------------------------------- proc task_2() char buff[10] int last_ctl_val uint loop_cnt ubyte acc LCD_init() LCD_define_glyph_code(7, &backslash_glyph) LCD_cursor_off() loop_cnt = 0 while 1 do last_ctl_val = ctl_val task_wait 1 if last_ctl_val != ctl_val then int_to_str(&buff, ctl_val) strcat_code(&buff, " ") LCD_set_pos(0, 0) LCD_write_str(&buff) endif LCD_set_pos(0, 1) acc = (loop_cnt >> 2) & 0x03 LCD_write_char(spin[acc]) loop_cnt += 1 done endproc //---------------------------------------------------------------------- //---------------------------------------------------------------------- proc main() ubyte acc ubyte switch_state // set PORTA to digital I/O instead of analog CMCON = 7 ctl_val = 0 task_start task_1 task_start task_2 switch_state = 0 while 1 do if switch_state == 0 then // wait for a switch event task_wait while_empty switch_event_fifo else // one or more switches is currently pressed // wait for 0.1 seconds between autoreapeat // or a switch event task_wait 2 while_empty switch_event_fifo endif while 1 do int switch_change switch_change = fifo_read(&switch_event_fifo) if switch_change < 0 then break endif // a switch change has occured // NOTE: process all switch change events if (switch_change & 0x7f) == 6 then // porta bit 6 changed state if (switch_change & 0x80) == 0 then // NOTE: this switch reads 1 for open and 0 for closed // so look to 1 to 0 transition which means from // open to closed (not pressed to pressed) // decrease ctl_val -= 1 switch_state = switch_state | 0x81 else switch_state = switch_state & ~1 endif else if (switch_change & 0x7f) == 7 then // porta bit 7 changed state if (switch_change & 0x80) == 0 then // NOTE: this switch reads 1 for open and 0 for closed // so look for 1 to 0 transition which means from // open to closed (not pressed to pressed) // increase number of flashes ctl_val += 1 switch_state = switch_state | 0x82 else switch_state = switch_state & ~2 endif endif done if (switch_state & 0x80) != 0 then // a switch press has just occured so insert // a pause beteen the switch press and // autorepeat // clear the just pressed flag switch_state = switch_state & ~0x80 // wait for 0.75 seconds or a switch event task_wait 15 while_empty switch_event_fifo else if (switch_state & 1) != 0 then ctl_val -= 1 endif if (switch_state & 2) != 0 then ctl_val += 1 endif endif done endproc //---------------------------------------------------------------------- //---------------------------------------------------------------------- proc intserv() endproc