/*
* OpenI2CRADIO
* Config & Main routine.
- * (C) 2013-06-10 K.Ohta <whatisthis.sowhat ai gmail.com>
- * License: GPL2
+ * Copyright (C) 2013-06-10 K.Ohta <whatisthis.sowhat ai gmail.com>
+ * License: GPL2+LE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ * This library / program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; see the file COPYING. If not, write to the
+ * Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * As a special exception, if you link this(includeed from sdcc) library
+ * with other files, some of which are compiled with SDCC,
+ * to produce an executable, this library does not by itself cause
+ * the resulting executable to be covered by the GNU General Public License.
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#if defined(__SDCC)
#include <sdcc-lib.h>
#include <pic18fregs.h> /* ONLY FOR PIC18x */
-#include <signal.h>
#include <delay.h>
+#else
+#include <xc.h>
+#endif
+
+#include <signal.h>
#include "iodef.h"
#include "idle.h"
#include "akc6955.h"
#include "lcd_acm1602.h"
#include "ui.h"
+#include "eeprom.h"
+#include "ioports.h"
+#include "menu.h"
+#include "power.h"
+#include "adc_int.h"
+#include "i2c_eeprom.h"
+#include "backlight.h"
/*
* Config words.
*/
-__at(__CONFIG1H) _config1h = _FOSC_INTIO67_1H;
-__at(__CONFIG2L) _config2l = _BORV_190_2L & _BOREN_ON_2L & _PWRTEN_ON_2L;
-__at(__CONFIG2H) _config2h = _WDTEN_ON_2H & _WDTPS_32768_2H;
-__at(__CONFIG3H) _config3h = _PBADEN_OFF_3H & _MCLRE_EXTMCLR_3H;
-__at(__CONFIG4L) _config4l = _STVREN_ON_4L & _LVP_OFF_4L & _XINST_ON_4L & _DEBUG_ON_4L;
-__at(__CONFIG5L) _config5l = _CP0_OFF_5L & _CP1_OFF_5L;
-__at(__CONFIG5H) _config5h = _CPB_OFF_5H & _CPD_OFF_5H;
-__at(__CONFIG6L) _config6l = _WRT0_OFF_6L & _WRT1_OFF_6L;
-__at(__CONFIG6H) _config6h = _WRTD_OFF_6H & _WRTB_OFF_6H & _WRTC_OFF_6H;
-__at(__CONFIG7L) _config7l = _EBTR0_OFF_7L & _EBTR1_OFF_7L;
-__at(__CONFIG7H) _config7h = _EBTRB_OFF_7H;
+#if defined(pic18f23k22) || defined(pic18f24k22) || defined(pic18f25k22) || defined(pic18f26k22)
+//#pragma stack 0x200 256 // Set stack size to 256bytes.
+#pragma config FOSC=INTIO67,BORV=190,BOREN=ON,PWRTEN=ON
+#pragma config WDTEN=ON,WDTPS=32768
+#pragma config PBADEN=OFF,MCLRE=EXTMCLR,STVREN=ON,LVP=OFF,DEBUG=ON,XINST=ON
+//#pragma config PBADEN=OFF,MCLRE=EXTMCLR,STVREN=ON,LVP=OFF//,XINST=ON
+#pragma config CP0=OFF,CP1=OFF,CPB=OFF,CPD=OFF
+#pragma config WRT0=OFF,WRT1=OFF,WRTB=OFF,WRTC=OFF,WRTD=OFF
+#pragma config EBTR0=OFF,EBTR1=OFF,EBTRB=OFF
+#endif
+// For 4xK20 or 2xK20 Series
+#if defined(pic18f43k20) || defined(pic18f44k20) || defined(pic18f45k20) || defined(pic18f46k20) || \
+ defined(pic18f23k20) || defined(pic18f24k20) || defined(pic18f25k20) || defined(pic18f26k20) || \
+ defined(_18F43K20) || defined(_18F44K20) || defined(_18F45K20) || defined(_18F46K20) || \
+ defined(_18F23K20) || defined(_18F24K20) || defined(_18F25K20) || defined(_18F26K20)
+
+#ifdef __SDCC
+#pragma stack 0x200 256
+#endif
+#pragma config FOSC=HS,FCMEN=ON,PWRT=ON,BOREN=NOSLP,BORV=27, \
+ WDTEN=ON,WDTPS=32768,PBADEN=OFF,HFOFST=OFF,LPT1OSC=OFF, \
+ MCLRE=ON,STVREN=ON,DEBUG=ON, \
+ XINST=OFF
+#endif
+/*
+ * Statuses
+ */
+unsigned char stereoflag;
+unsigned char tuneflag;
+unsigned char cnrlevel;
+int diffstat;
+unsigned int batlevel_6955;
+unsigned int battlevel;
+int recv_signal;
+unsigned char pollkeybuf[33];
+//#define _LCD_DEBUG 1
+#ifdef __XC
+void TMR0_handler(void)
+#else
SIGHANDLER(TMR0_handler)
+#endif
{
- unsigned char tmr0f;
- unsigned char t0con;
// Stop timer0
- t0con = T0CON;
- t0con &= ~_IDLEN;
- T0CON = t0con;
-
- // Read IOKEYS
- readkey_io();
+ T0CONbits.TMR0ON = 0;
// Clear interrupt flag
- tmr0f = INTCON;
- tmr0f &= ~(_TMR0IF);
- INTCON = tmr0f;
+// INTCONbits.TMR0IF = 0;
+ INTCONbits.TMR0IE = 0;;
return;
}
+/*
+ * Interrupt wake up every 1ms.
+ */
+#ifdef __XC
+void TMR3_Handler(void)
+#else
+SIGHANDLER(TMR3_Handler)
+#endif
+{
+ PIR2bits.TMR3IF = 0;
+ PIE2bits.TMR3IE = 0;
+ T3CONbits.TMR3ON = 0;
+}
+#ifdef __XC
+void EXINT_Handler(void)
+#else
+SIGHANDLER(EXINT_Handler)
+#endif
+{
+ INTCONbits.INT0IE = 0;
+ INTCONbits.INT0IF = 0;
+ INTCON3bits.INT1IF = 0;
+ INTCON3bits.INT2IF = 0;
+ INTCON3bits.INT1IE = 0;
+ INTCON3bits.INT2IE = 0;
+}
+#ifdef __XC
+void RBIF_handler(void)
+#else
+SIGHANDLER(RBIF_handler)
+#endif
+{
+ power_on_inthook();
+// if(chk_powerbutton(0, 0) != 0) { // If pressed on
+// power_off(1); //
+// }
+}
+#ifdef __XC
+void EEPROM_handler(void)
+#else
+SIGHANDLER(EEPROM_handler)
+#endif
+{
+ PIR2bits.EEIF = 0;
+ EECON1bits.WREN = 0;
+// if(chk_powerbutton(0, 0) != 0) { // If pressed on
+// power_off(1); //
+// }
+}
+
+#ifdef __XC
+void INADC_handler(void)
+#else
+SIGHANDLER(INADC_handler)
+#endif
+{
+// unsigned int a;
+// a = polladc();
+// if(a != 0xffff) {
+// battlevel = adc_rawtobatt(a);
+// }
+ PIR1bits.ADIF = 0;
+}
+#ifdef __XC
+void I2C_handler(void)
+#else
+SIGHANDLER(I2C_handler)
+#endif
+{
+ PIR1bits.SSPIF = 0;
+}
+#ifdef __XC
+void I2CBus_handler(void)
+#else
+SIGHANDLER(I2CBus_handler)
+#endif
+{
+ PIR2bits.BCLIF = 0;
+}
+
+
+
+#ifdef __SDCC
DEF_INTLOW(intlow_handler)
DEF_HANDLER(SIG_TMR0, TMR0_handler)
+ DEF_HANDLER(SIG_INT0, EXINT_Handler)
+// DEF_HANDLER(SIG_TMR3, I2C_handler)
END_DEF
+DEF_INTHIGH(inthigh_handler)
+ DEF_HANDLER(SIG_RBIF, RBIF_handler)
+ DEF_HANDLER(SIG_EEIF, EEPROM_handler)
+ DEF_HANDLER(SIG_TMR3, TMR3_Handler)
+ DEF_HANDLER(SIG_INT1, EXINT_Handler)
+ DEF_HANDLER(SIG_INT2, EXINT_Handler)
+ DEF_HANDLER(SIG_AD, INADC_handler)
+ //DEF_HANDLER(SIG_SSP, I2C_handler)
+ //DEF_HANDLER(SIG_BCOL, I2CBus_handler)
+END_DEF
+#else
+void interrupt low_priority intlow_handler(void)
+{
+ if(INTCONbits.TMR0IF) TMR0_handler();
+ if(INTCONbits.INT0IF) EXINT_Handler();
+}
-unsigned int amfreq;
-unsigned int fmfreq;
-unsigned char amband;
-unsigned char fmband;
-unsigned char fm;
-unsigned char am_mode3k;
-int recv_signal;
+void interrupt high_priority inthigh_handler(void)
+{
+ if(INTCONbits.RBIF) RBIF_handler();
+ if(PIR2bits.EEIF) EEPROM_handler();
+ if(PIR2bits.TMR3IF) TMR3_Handler();
+ // if(INTCONbits.TMR0IF) TMR0_handler();
+ if(INTCON3bits.INT1IF) EXINT_Handler();
+ if(INTCON3bits.INT2IF) EXINT_Handler();
+ if(PIR1bits.ADIF) INADC_handler();
+
+// if(PIR1bits.SSPIF) I2C_handler();
+}
+
+#ifdef __XC
+#endif
+#endif
-static void update_display(void)
+void lowbatt(void)
{
- if(fm != 0){ // FM
- _LOCATE(0,0);
- if(fmband < AKC6955_BAND_TV1) {
- printstr("FM");
- _PUTCHAR('1' + (fmband & 7));
- } else if(fmband < AKC6955_BAND_FMUSER){
- printstr("TV");
- _PUTCHAR('1' + fmband - AKC6955_BAND_TV1);
- } else { // USER
- printstr("FMUSR");
- }
- } else { // AM
- _LOCATE(0,1);
- if(amband == AKC6955_BAND_LW) {
- printstr("LW");
- } else if(amband <AKC6955_BAND_SW1) { //MW
- printstr("MW");
- _PUTCHAR('1' + amband - AKC6955_BAND_MW1);
- } else if(amband < AKC6955_BAND_AMUSER) { //MW
- printstr("SW");
- _PUTCHAR('1' + amband - AKC6955_BAND_SW1);
- } else if(amband == AKC6955_BAND_MW4){
- printstr("MW4");
- } else {
- printstr("AMUSR");
- }
- }
- _LOCATE(16-4 ,1);
- if(fm != 0){
- printstr("MHz");
- } else {
- printstr("KHz");
- }
- _LOCATE(16-5, 1);
- if(fm != 0){
- int freq_lo = fmfreq % 100;
- int freq_hi = fmfreq / 100;
- print_numeric(freq_hi);
- _PUTCHAR('.');
- print_numeric(freq_lo);
- } else {
- int freq = amfreq;
- print_numeric(freq);
- }
- // Signal
- _LOCATE(0, 0);
- printstr("S=");
- print_numeric(recv_signal);
+// _CLS();
+// idle_time_ms(100);
+ printhelp_2lines("Low battery X)", "Press key to suspend");
+ shutdown(1);
}
-
-static void setfreq_updown(unsigned char ctlword)
+int main(void)
{
- switch(ctlword){
- case charcode_8: // Change band
- if(fm != 0){
- amband++;
- if(amband > 18) amband = 0;
-// amfreq = akc6955_setfreq(amfreq)
- akc6955_set_amband(amband);
- delay1ktcy(500); // 62.5ms
- amband = akc6955_get_amband();
- amfreq = akc6955_get_freq();
- } else {
- fmband++;
- if(fmband > 7) fmband = 0;
-// amfreq = akc6955_setfreq(amfreq)
- akc6955_set_fmband(fmband);
- delay1ktcy(500); // 62.5ms
- fmband = akc6955_get_fmband();
- fmfreq = akc6955_get_freq();
- }
- break;
- case charcode_2: // Change band
- if(fm != 0){
- amband--;
- if(amband == 0) amband = 18;
- if(amband >= 18) amband = 18;
-// amfreq = akc6955_setfreq(amfreq)
- akc6955_set_amband(amband);
- delay1ktcy(500); // 62.5ms
- amband = akc6955_get_amband();
- amfreq = akc6955_get_freq();
- } else {
- fmband--;
- if(fmband == 0) fmband = 7;
- if(fmband >= 7) fmband = 7;
-// amfreq = akc6955_setfreq(amfreq)
- akc6955_set_fmband(fmband);
- delay1ktcy(500); // 62.5ms
- fmband = akc6955_get_fmband();
- fmfreq = akc6955_get_freq();
- }
- break;
- case charcode_4: // Down Freq;
- if(fm != 0){
- fmfreq = akc6955_down_freq(10); // DOWN 100KHz
- } else {
- amfreq = akc6955_down_freq(10); // DOWN 10KHz
- }
- break;
- case charcode_6: // Down Freq;
- if(fm != 0){
- fmfreq = akc6955_up_freq(10); // UP 100KHz
- } else {
- amfreq = akc6955_up_freq(10); // UP 10KHz
- }
- break;
- case charcode_7: // Down Fast;
- if(fm != 0){
- fmfreq = akc6955_down_freq(50); // DOWN 500KHz
- } else {
- amfreq = akc6955_down_freq(50); // DOWN 50KHz
- }
- break;
- case charcode_9: // Down Fast;
- if(fm != 0){
- fmfreq = akc6955_up_freq(50); // UP 100KHz
- } else {
- amfreq = akc6955_up_freq(50); // UP 10KHz
- }
- break;
- case charcode_1: // Down Slow;
- if(fm != 0){
- fmfreq = akc6955_down_freq(5); // DOWN 50KHz
- } else {
- amfreq = akc6955_down_freq(5); // DOWN 50KHz
- }
+ unsigned char c;
+ unsigned char pbutton;
+ unsigned char reset_status;
+ unsigned char p;
+ unsigned char lvcount = 0;
+ unsigned char dispf = 0xff;
+
+ OSCCON = (0x80 & 0b11111100) | 0b00111000;
+// OSCCON = (0x80 & 0b11111100) | 0b00110010; // 8MHz
+ idle_init();
+ keyin_init();
+ keyin_ioinit();
+ i2c1_init();
+ reset_status = chk_reset();
+ idle_time_ms(300); // Wait for setup.
+ WDTCONbits.SWDTEN = 0; // WDT OFF.
+ switch(reset_status){
+ case RESET_MCLR:
+ case RESET_BOR:
+ shutdown(0); // Save and halt on BOR.
break;
- case charcode_3: // Down Slow;
- if(fm != 0){
- fmfreq = akc6955_up_freq(5); // UP 50KHz
- } else {
- amfreq = akc6955_up_freq(5); // UP 5KHz
- }
+ case RESET_SOFTWARE: //
+ RCONbits.RI = 0;
+ pbutton = chk_powerbutton();
+ if(pbutton == 0) shutdown(0); // Not-Pressed power-button -> shutdown( not save).
break;
- case charcode_0: // Step
- if(fm == 0){
- if(am_mode3k == 0) {
- am_mode3k = 0xff;
- } else {
- am_mode3k = 0;
- }
- amfreq = akc6955_mode3k(am_mode3k);
- }
+ case RESET_POR:
+ case RESET_WDT: // Workaround random reset.
+ // shutdown(0);
break;
default:
break;
}
-}
-/*
- *
- */
-int main(void)
-{
- char readchar;
- unsigned char input_flag;
-
- keyin_init();
- keyin_ioinit();
- idle_init();
-
- i2c1_init();
-
- delay1ktcy(1000); // Wait 125ms
-
- acm1602_init(0xa0, 1); //Init LCD
-
- delay1ktcy(1000); // Wait 125ms
-
-
- // Init AKC6955
- amfreq = 954;
- fmfreq = 8000; // 10KHz order.
- amband = AKC6955_BAND_MW2;
- fmband = AKC6955_BAND_FM2;
- am_mode3k = 0xff;
- fm = 0;
- recv_signal = 0;
-
+ WDTCONbits.SWDTEN = 1; // WDT ON.
+ power_on(1);
+ //intadc_init();
+ set_powerlamp(1);
+ valinit();
+ acm1602_init(LCD_I2CADDR, 1); //Init LCD
+ lcd_setbacklight(0xff, 255);
/* Check EEPROM */
- /* Push default parameters to AKC6955*/
-
- akc6955_chg_fm(fm); // Set to AM
- akc6955_set_amband(amband);
- akc6955_set_freq(amfreq); // Dummy, TBS (954KHz)
- akc6955_set_power(0xff); // Power ON
- idle(0xff00);
+ check_eeprom();
+ /* Push default parameters to AKC6955*/
+ setup_akc6955();
+ _CLS();
+ //_LOCATE(0,0);
+ _PUTCHAR(' ');
+ update_status();
+ update_display();
+ ClrWdt();
do {
+#if 1
+ if(battlevel < 330) { // 3.3V
+ lvcount++;
+ if(lvcount > 4) {
+ if(dispf == 0) {
+ acm1602_resume(LCD_I2CADDR);
+ dispf = 0xff;
+ }
+ lowbatt(); //Zap 4Times on LowVoltage.
+ }
+ } else {
+ lvcount = 0;
+ }
+#endif
/* Main routine*/
- input_flag = readkey_compare();
- if(input_flag != 0){
- readchar = pop_keyinfifo();
- switch(readchar) {
- // Top of input-tree.
- case charcode_s0:
- // Change FM/AM
- if(fm != 0){
- fm = 0;
- akc6955_chg_fm(fm);
- akc6955_set_amband(amband);
- akc6955_set_freq(amfreq);
- } else {
- fm = 0xff;
- akc6955_chg_fm(fm);
- akc6955_set_fmband(fmband);
- akc6955_set_freq(fmfreq);
- }
- break;
- case charcode_s1:
- //
- break;
- case charcode_s2:
- // ENTER
- break;
- case charcode_s3:
- // Reserve
- break;
- case charcode_null: // None
- break;
- default:
- // Numeric 0to9, or a to f.
- setfreq_updown(readchar);
- break;
+ c = pollkey_single_timeout(41, 1); // 23*41 = 943ms
+ p = 0;
+ if(c != charcode_null) {
+ ClrWdt();
+ if(dispf == 0) {
+ acm1602_resume(LCD_I2CADDR);
+ dispf = 0xff;
+ }
+ setfreq_updown(c);
}
- }
- recv_signal = akc6955_read_level();
- // Check battery (include idle?)
- // Read AKJC6955's status
- // Putstring to LCD.
- update_display();
- idle(0xff00);
+ ClrWdt();
+ update_status();
+ dispf = backlight_dec(dispf); // 48ms
+ if(dispf != 0) update_display();
+ idle_time_ms(9); // Pad 9ms, 1Loop = 1000ms.
+ ClrWdt();
} while(1);
-
}