commit bcc466f985eed8a61bcf6f18d63cc3516bb1e67f Author: Bruno Rybársky Date: Sun Apr 14 13:28:29 2024 +0200 init diff --git a/main.c b/main.c new file mode 100644 index 0000000..2246f5c --- /dev/null +++ b/main.c @@ -0,0 +1,468 @@ +/* +* File: main.c +* Author: Bruno Rybársky +* +* Created on November 17, 2022, 12:49 PM +*/ + +//PINS +//GP0 - Button 1 +//GP1 - Button 2 +//GP2 - Unused +//GP3 - Unused +//GP4 - Serial TX +//GP5 - Serial RX + +//END PINS + + +//FLAGS + +//Flag: + +// Flag, 0: Debounced power outage restore GPIOdeb,3 +// Flag, 1: +// Flag, 2: +// Flag, 3: +// Flag, 4: +// Flag, 5: Millis2 overflow, monitored and cleared in signal strength request +// Flag, 6: +// Flag, 7: GPIO0 status + +//Flag3: + +// Flag3, 0: +// Flag3, 1: +// Flag3, 2: +// Flag3, 3: Millis3 overflow +// Flag3, 4: SMS data beginning +// Flag3, 5: Sending SMS data +// Flag3, 6: +// Flag3, 7: + +//Flag4: + +// Flag4, 0: SMS is 1 ON +// Flag4, 1: SMS is 1 OFF +// Flag4, 2: SMS is 2 ON +// Flag4, 3: SMS is 2 OFF +// Flag4, 4: +// Flag4, 5: +// Flag4, 6: +// Flag4, 7: + + +//START STRING RECIEVING +//Flag2: + +// Flag2, 0: in process of recieving "OK" +// Flag2, 1: in process of recieving "NO CARRIER" +// Flag2, 2: in process of recieving "ERROR" +// Flag2, 3: in process of recieving "SMS Ready" +// Flag2, 4: +// Flag2, 5: +// Flag2, 6: +// Flag2, 7: + +//FlagC: + +// FlagC, 0: "OK" recieved +// FlagC, 1: "NO CARRIER" recieved +// FlagC, 2: "ERROR" recieved +// FlagC, 3: "SMS Ready" recieved +// FlagC, 4: +// FlagC, 5: +// FlagC, 6: +// FlagC, 7: + +//END STRING RECIEVING + +//END Flags + + +// PIC12F683 Configuration Bit Settings + +// 'C' source line config statements + +// CONFIG +#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN) +#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) +#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) +#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD) +#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled) +#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled) +#pragma config BOREN = ON // Brown Out Detect (BOR enabled) +#pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode is enabled) +#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled) + +#define _XTAL_FREQ 8000000 //freq for delay +// #pragma config statements should precede project file includes. +// Use project enums instead of #define for ON and OFF. + +#include + +/* These are the definitions */ + +const char String1[3] = "OK"; //ok response +const char String2[11] = "NO CARRIER"; //call state change +const char String3[6] = "ERROR"; //ok response +const char String4[10] = "SMS Ready"; //modem startup + +const char StringDial[14] = "+421905708125"; + +//#define TMR0_BAUD (256-133) /* trial and error value, comes to 3603 Baud */ +#define TMR0_BAUD (256-133) /* trial and error value, comes to 3603 Baud */ + +#define TxBUF_SIZE 32 +#define RxBufSize 8 +volatile char TxBuf[TxBUF_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; +#define TxBUF_MASK (TxBUF_SIZE-1) +volatile char RxBuf[RxBufSize]; +volatile char RxIPtr; +volatile char RxIPtr_old; +volatile char TxFlags; +volatile char RxOPtr; +volatile char TxIPtr; +volatile char TxOPtr; +volatile char TxCount; +volatile char RxChar; +volatile char TxChar; +volatile char RecSkips; +volatile char InByte; +volatile char TxSkips = 3; +volatile char TxCount; +volatile char RxFlags; +volatile char RxBufDiff; +volatile char InChar; + +//start parsing serial data: + +volatile char messagePointer = 0; + +//flags: +volatile char Flag = 0x05; +char Flag2 = 0xFF; +volatile char Flag3 = 0; +volatile char Flag4 = 0; +char FlagC = 0; +volatile char GPIOtemp = 0; +volatile char GPIOdeb = 0; +volatile char GPIOold = 0; + +//end parsing serial data: + +//measuring time +volatile char Millis = 0; + + + +/* Here's the enqueuing routine for sending data */ + +/* Enqueue data in the transmit buffer to send down the serial line */ +/* This routine adds one character at a time to the 32 byte buffer */ +/* (the size is constrained b the compiler and RAM limitations of the */ +/* processor). When a character has been added, the "new data" flag is */ +/* set to tell the interrupt routine to restart sending data. */ +/* Note: data can be added to the buffer faster than the interrupt */ +/* routine can transmit it */ + +void SendChar(char c) { + GIE = 0; /* disable interrupts to avoid a race condition */ + TxBuf[TxOPtr++] = c; + TxOPtr = TxOPtr & TxBUF_MASK; + TxFlags |= 0x80; + GIE = 1; /* safe to restart them now */ +} + +void SendString(const char *c) { + while (*c != 0x00) { + SendChar(*c); + ++c; + } +} + +/* here's the interrupt handler that performs the serial I-O */ +/* With an 8MHz (internal R-C) clock and the timer0 count value */ +/* defined above, this gives 2400 Baud duplex communication */ +/* As you will see from the original, it samples the incoming */ +/* data 3 times per bit */ + +/* general purpose interrupt handler */ + + +void __interrupt()isr(void) { + if (T0IF) { + T0IF = 0; + TMR0 = TMR0_BAUD; + + // Increment Millis + //Millis++; + //if (STATUS & (1 << 2)) { // if millis overflows + if (!++Millis) { + // if millis overflows + // Debouncing code sampling GPIO2 only runs when Millis overflows + //if ((GPIOtemp & 0x0D) != (GPIO & 0x0D)) { // compare current input with last round + + if ((GPIO & 0x03) != GPIOold){ + GPIOtemp = (GPIO & 0x03) ^ GPIOold; + GPIOold = GPIO & 0x03; + // GPIO2 changed, perform debouncing + if (GPIOtemp & 0x01) { + if (!(GPIO & 0x01)) { + GPIOdeb |= (1 << 4); // arm + } + else { + GPIOdeb |= (1 << 5); // disarm + } + } + + if (GPIOtemp & 0x02) { + if (!(GPIO & 0x02)) { + GPIOdeb |= (1 << 6); // arm + } + else { + GPIOdeb |= (1 << 7); // disarm + } + } + } + } + + + // Routine to receive asynchronous data from GPIO5 + // credit: http://www.electro-tech-online.com/micro-controllers/18828-finding-serial-start-bit-bit-banging.html#post117227 + asm("decfsz _RecSkips,F"); + asm("goto DoneRS232_Rx"); + asm("btfss _RxFlags,0"); // b_receiving + asm("goto get_start_bit"); + asm("bsf STATUS, 0"); + asm("btfss GPIO, 5"); + asm("bcf STATUS,0"); + asm("rrf _InByte,F"); + asm("movlw 3"); + asm("movwf _RecSkips"); + asm("btfss STATUS, 0"); + asm("goto DoneRS232_Rx"); + asm("movf _InByte,W"); + asm("movwf _RxChar"); + asm("bsf _RxFlags,1"); // b_byte_available + asm("bcf _RxFlags,0"); // b_receiving + RxBuf[RxIPtr++] = RxChar; /* write received byte to circular buffer */ + RxIPtr = RxIPtr & 0x7; + asm("goto DoneRS232_Rx"); + + asm("get_start_bit:"); + + asm("incf _RecSkips,F"); // set to 1 + asm("btfsc GPIO, 5"); + asm("goto DoneRS232_Rx"); + asm("movlw 4"); + asm("movwf _RecSkips"); + asm("bsf _RxFlags,0"); // b_receiving + asm("movlw 80h"); + asm("movwf _InByte"); + asm("DoneRS232_Rx:"); + + // Code to transmit data from GPIO.4 + // Note: this can be done while reception is in progress, + // it's full duplex + // Here check if there is data being sent, or ready to send + asm("btfsc _TxFlags, 6"); /* already sending ?*/ + asm("goto Tx_Sending"); + asm("btfsc _TxFlags, 7"); // data to send + asm("goto Tx_Start_Bit"); + asm("incf _TxSkips, F"); // set back to 1, so we retest next time round + asm("goto DoneRS232_Tx"); // nothing to do + + // come here to start sending a new byte + asm("Tx_Start_Bit:"); + asm("decfsz _TxSkips, f"); + asm("goto DoneRS232_Tx"); + asm("bcf GPIO, 4"); // hardware start bit + + TxChar = TxBuf[TxIPtr++]; + TxIPtr = TxIPtr & TxBUF_MASK; + + TxFlags = 8; // initialise bit count, clear FULL flag + asm("bsf _TxFlags, 6"); // indicate we are sending data + TxSkips = 3; + asm("goto DoneRS232_Tx"); + + //here if we are already in the process of sending data + asm("Tx_Sending:"); + asm("decfsz _TxSkips, F"); // only waggle o/p every third intr. + asm("goto DoneRS232_Tx"); + + asm("btfsc _TxFlags, 5"); // time to send stop bit? + asm("goto Tx_Stop_Bit"); + + asm("bcf STATUS, 0"); // carry bit + asm("rrf _TxChar, f"); + asm("btfss STATUS, 0"); + asm("goto Tx_Set_Bit"); + asm("bsf GPIO, 4"); + asm("goto Tx_Sent_Bit"); + asm("Tx_Set_Bit:"); + asm("bcf GPIO, 4"); + // here we have sent the data bit, decrement the bit counter + asm("Tx_Sent_Bit:"); + asm("movlw 3"); + asm("movwf _TxSkips"); // reset Tx skip counter for 3 more intrs + asm("decf _TxFlags, F"); // bit count in lower 3 bits + asm("movf _TxFlags, W"); + asm("andlw 7"); + asm("btfss STATUS, 2"); // if result is zero + asm("goto DoneRS232_Tx"); + asm("bsf _TxFlags, 5"); // all data sent, sent stop bit next time + asm("goto DoneRS232_Tx"); + + // here to send the stop bit and check if there''s more data + // to send, once this byte has completed + asm("Tx_Stop_Bit:"); + asm("bsf GPIO, 4"); + asm("movlw 3"); + asm("movwf _TxSkips"); + asm("bcf _TxFlags, 6"); // sending_data flag + asm("bcf _TxFlags, 5"); // send_stop_bit flag + TxCount = 1 + TxOPtr - TxIPtr; + asm("decfsz _TxCount, F"); // counter of number of chars still to send + asm("goto Tx_More"); + asm("goto DoneRS232_Tx"); // all sent + + asm("Tx_More:"); + asm("bsf _TxFlags, 7"); // signify more data to send + + asm("DoneRS232_Tx:"); + + + } +} + +void init(void) { + OPTION_REGbits.T0CS = 0; + OPTION_REGbits.PSA = 0; + OPTION_REGbits.PS0 = 0; + OPTION_REGbits.PS1 = 0; + OPTION_REGbits.PS2 = 0; + OPTION_REGbits.nGPPU = 0; + INTCONbits.T0IE = 1; + INTCONbits.GIE = 1; + CMCON0bits.CM0 = 1; + CMCON0bits.CM1 = 1; + CMCON0bits.CM2 = 1; + OSCCONbits.IRCF0 = 1; + OSCCONbits.IRCF1 = 1; + OSCCONbits.IRCF2 = 1; + TRISIObits.TRISIO5 = 1; + TRISIObits.TRISIO4 = 0; + TRISIObits.TRISIO1 = 1; + TRISIObits.TRISIO0 = 1; + WPUbits.WPU1 = 1; + WPUbits.WPU0 = 1; + ADCON0bits.ADON = 0; + ANSELbits.ANS0 = 0; + ANSELbits.ANS1 = 0; + ANSELbits.ANS2 = 0; + ANSELbits.ANS3 = 0; + + +} + +int startSMS() { + if (FlagC & (1 << 3)) { + SendString("AT+CMGS=\""); + SendString(StringDial); + SendString("\"\n"); + Flag3 |= (1 << 5); + return 1; + } + return 0; +} + +void processString(const char *string, volatile char *inputCharacter, const int flagBit) { + if (Flag2 & (1 << flagBit)) { + if (!string[messagePointer]) { + FlagC |= (1 << flagBit); + Flag2 &= ~(1 << flagBit); + if (flagBit == 3) { + SendString("AT+CMGF=1\r\n"); + } + } + if (*inputCharacter != string[messagePointer]) { + Flag2 &= ~(1 << flagBit); + } + } +} + +void handleGPIO(const int pin, const int flagBit) { + if (GPIOdeb & (1 << pin)) { + GPIOdeb &= ~(1 << pin); + if(startSMS()){ + Flag4 |= (1 << flagBit); + } + } +} + +void main(void) { + init(); + SendChar('\n'); + while (1) { + + handleGPIO(6, 0); + handleGPIO(7, 1); + handleGPIO(4, 2); + handleGPIO(5, 3); + + if (RxIPtr != RxIPtr_old) { + if (RxIPtr < RxIPtr_old) { + RxBufDiff = RxBufSize - (RxIPtr_old - RxIPtr); + } else { + RxBufDiff = RxIPtr - RxIPtr_old; + } + for (char iy = 0; iy < RxBufDiff; iy++) { + InChar = RxBuf[iy + RxIPtr_old]; + if (InChar == 0x0A) { + Flag2 = 0xFF; + messagePointer = 0; + } else { + if (InChar == '>') { + if (Flag3 & (1 << 5)) { + + if (Flag4 & (1 << 0)) { + SendString("1 ON"); + Flag4 &= ~(1 << 0); + } + + if (Flag4 & (1 << 1)) { + SendString("1 OFF"); + Flag4 &= ~(1 << 1); + } + + if (Flag4 & (1 << 2)) { + SendString("2 ON"); + Flag4 &= ~(1 << 2); + } + + if (Flag4 & (1 << 3)) { + SendString("2 OFF"); + Flag4 &= ~(1 << 3); + } + + SendChar(26); + Flag3 &= ~(1 << 5); + } + } + + processString(String1, &InChar, 0); + processString(String2, &InChar, 1); + processString(String3, &InChar, 2); + processString(String4, &InChar, 3); + + messagePointer++; + } + } + RxIPtr_old = RxIPtr; + } + } +}