/* * File: main.c * Author: Nangi * * Created on March 8, 2021, 12:32 PM * Rev. 1.0 Mar. 15 2021 */ #include // variable types typedef unsigned char u_char; typedef unsigned int u_int; typedef unsigned char byte; // Boolean #define TRUE 1 #define FALSE 0 #define __ON 1 #define __OFF 0 // CONFIG #pragma config FOSC = XT // Oscillator Selection bits (XT oscillator: Crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR) #pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) // CLOCK external 4.19MHz #define _XTAL_FREQ 4194304 // I/O pin assigned symbols #define DIGIT_SEL RA0 #define SSR_ON RA1 #define SOUNDER RA2 #define HB_SW RA3 #define TM_SW RA4 // Timer setting #define DEFAULT_MIN 15 #define INC_MIN 5 #define MIN_LEAST 5 #define MIN_MOST 60 #define BZ_CYCLE 85 // globals byte t_min, t_sec; // time-count min/secÏ byte t_sub; // sub seconds / 0.5sec display (0-7:ON, 8-15:OFF) byte timer; // timer start time (min) byte runMode; // operation mode byte isBeep; // Buzzer in beep flag byte disp; // display digit select (0:1, 1:10) // 7segment display data buffer byte digit01, digit10; // constants // 7 segment LED pattern const byte segData[] = { //Pgfedcba - segment ON 0b00111111, // 0 0b00000110, // 1 0b01011011, // 2 0b01001111, // 3 0b01100110, // 4 0b01101101, // 5 0b01111101, // 6 0b00000111, // 7 0b01111111, // 8 0b01101111, // 9 0b00000000, // BLANK 0b01000000 // AC line off }; // 7 segment assign bit enum segBit { SEG_A = 0x01, SEG_B = 0x02, SEG_C = 0x04, SEG_D = 0x08, SEG_E = 0x10, SEG_F = 0x20, SEG_G = 0x40, SEG_DP = 0x80 }; // segData pick up symbols enum segSymbols { NUM_0, NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9, BLANK, AC_OFF }; // Run Mode enum { MODE_STOP = 0, MODE_RUN, MODE_SET, MODE_TIMEUP }; // Prototype declaration void initVals(void); void initDevice(void); void doStart(void); void doTimeUp(void); void doSetup(void); _Bool isHB_on(void); _Bool isTM_on(void); void waitHB_off(void); void waitTM_off(void); void doBeep(int); void __interrupt() isr(void); // Main Loop void main(void) { byte _min; // Initialize initVals(); initDevice(); // Main loop while (TRUE) { switch (runMode) { case MODE_TIMEUP: if (isHB_on()) { waitHB_off(); doBeep(500); isBeep = FALSE; doStart(); } else { digit01 = segData[AC_OFF]; digit10 = segData[AC_OFF]; } if (isTM_on()) { doSetup(); } break; case MODE_RUN: if (t_min == 0 && t_sec == 0) { doTimeUp(); doBeep(2000); isBeep = FALSE; } else { if (t_sec > 0 && t_min != timer) _min = t_min + 1; // Zero suppress if (_min >= 10) digit10 = segData[_min / 10]; else digit10 = segData[BLANK]; digit01 = segData[_min % 10]; // running blink DP if (t_sub < 8) digit01 |= SEG_DP; // Live sound if (t_sec == 59 && isBeep == FALSE) doBeep(50); } // Heart Beat corrected if (isHB_on()) { waitHB_off(); doStart(); } break; case MODE_STOP: // operation NOTHING break; case MODE_SET: isBeep = FALSE; _min = timer; digit01 = segData[_min % 10]; // Zero suppress if (_min >= 10) digit10 = segData[_min / 10]; else digit10 = segData[BLANK]; doSetup(); break; default: break; } } } // Variables initialize void initVals(void) { t_min = timer = DEFAULT_MIN; t_sec = 0; t_sub = 0; runMode = MODE_TIMEUP; disp = 0; digit01 = segData[AC_OFF]; digit10 = segData[AC_OFF]; } // Device initialize void initDevice(void) { // Peripherals //!PBPUE 1:off // INTEDG 1:rise up // T0CS 0:CLKOUT(internal instruction cycle) // T0SE 1:rise up // PSA 0:prescaler use TMR0 // PS2:PS0 TMR0 prescaler 010:1/16 OPTION_REG = 0b11010010; /* PORTA * I/O property * RA0 O digit select * RA1 O SSR control * RA2 O sounder * RA3 I Heart Beat (pull upped) * RA4 I Time change(pull upped) * RA5 I MCLR * RA6 I X'TAL 4.194304MHz * RA7 I X'TAL */ TRISA = 0b11111000; PORTA = 0x00; /* PORTB * I/O property * PB0 O SEG a * PB1 O SEG b * PB2 O SEG c * PB3 O SEG d * PB4 O SEG e * PB5 O SEG f * PB6 O SEG g * PB7 O SEG DP */ TRISB = 0b00000000; PORTB = 0x00; // ANALOG functions /* CMCON comparator module control * C2OUT 0 C2VIN- < C2VIN+ * C1OUT 0 C1VIN- < C1VIN- * C2INV 0 C2OUT inverted * C1INV 0 C1OUT inverted * CIS 0 no effect (CM:111 * CM 111:comparetor off */ CMCON = 0b00000111; /* VRCON Vref module control * VREN 0 Vref DISABLE * VROE 0 Vref output * VRR 0 Voltage range : High Range * - 9 NO USE * VR3:VR1 0000 Vref value */ VRCON = 0b00000000; // TMR0 // see OPTION_REG // TMR1 /* T1CON Timer1 control * 7-6 -- unused * T1CKPS1:T1CKPS0 00 : prescaler 1/1 * T1OSCEN 0 TMR1 OSC shutout *!T1SYNC 0 TMR1 clock SYNC ex. clock * TMR1CS 0 TMR1 clock source : 0 (internal Fosc/4) * TMR1ON 0 TRM1 stop */ T1CON = 0b00000000; // Interrupts /* INTERRUPT control * GIE 0 Global INT disable * PEIE 1 Peripheral INT enable * T0IE 0 TMR0 overflow INT disable * INTE 0 RB0 INT disable * RBIE 0 RB port change INT disable * T0IF 0 TMR0 overflow INT flag * INTF 0 RB0/INT no occur * RBIF 0 RB port change INT */ // TMR0 enable T0IE = TRUE; // TMR1 enable TMR1IF = FALSE; TMR1IE = TRUE; // Peripheral interrupt enable PEIE = TRUE; // Global interrupt enable GIE = TRUE; } // Heart Beat timer start void doStart(void) { TMR1L = 0; TMR1H = 0; t_sub = 0; t_sec = 59; t_min = timer - 1; runMode = MODE_RUN; if (t_min >= 10) digit10 = segData[t_min / 10]; else digit10 = segData[BLANK]; digit01 = segData[t_min % 10]; TMR1ON = TRUE; SSR_ON = TRUE; } // Time count upped void doTimeUp(void) { SSR_ON = FALSE; TMR1ON = FALSE; t_sub = 0; t_sec = 0; t_min = timer; runMode = MODE_TIMEUP; } // Timer setup mode void doSetup(void) { // Wait release button if (runMode != MODE_SET) { waitTM_off(); runMode = MODE_SET; doBeep(50); } // Exit set mode ? if (isHB_on()) { waitHB_off(); doTimeUp(); doBeep(50); return; } // timer time to up count if (isTM_on()) { waitTM_off(); if (timer + INC_MIN > MIN_MOST) timer = MIN_LEAST; else timer += INC_MIN; doBeep(50); } } // Check HeartBeat button is ON ? _Bool isHB_on(void) { _Bool result; result = FALSE; if (!HB_SW) { __delay_ms(10); if (!HB_SW) result = TRUE; } return result; } // Check Time set button is ON ? _Bool isTM_on(void) { _Bool result; result = FALSE; if (!TM_SW) { __delay_ms(10); if (!TM_SW) result = TRUE; } return result; } // HeartBeat button wait release void waitHB_off(void) { while (!HB_SW) ; } // TimeSet button wait release void waitTM_off(void) { while (!TM_SW) ; } // Buzzer ringing void doBeep(int n) { // ringing flag ON isBeep = TRUE; // BZ beep while (n--) { SOUNDER = TRUE; __delay_us(BZ_CYCLE); SOUNDER = FALSE; __delay_us(BZ_CYCLE); } } // Interrupt Service Routine void __interrupt() isr(void) { if (TMR1IF) { // TMR1 interrupt // clear interrupt flag TMR1IF = FALSE; // sub second count up t_sub++; // 1 second count down if (t_sub >= 16) { t_sub = 0; if (t_sec == 0 && t_min > 0) { t_sec = 59; t_min--; } else { t_sec--; } isBeep = FALSE; } } else if (T0IF) { // TMR0 interrupt // clear interrupt flag T0IF = FALSE; // blank all segments PORTB = 0x00; if (disp == 1) { // 10's digit disp = 0; // next digit DIGIT_SEL = __ON; PORTB = digit10; } else { // 1's digit disp = 1; // next digit DIGIT_SEL = __OFF; PORTB = digit01; } } }