/******************************************************************************** * DSP RADIO BK1088 * 受信バンド:FM * 音量:受信局は EEPROM に保存され、電源OFF時でも失われない * 選局を長押しすると、ホーム局 stHome に戻る * 受信周波数:presetFreq に設定する * * BK_FM プログラムは、BK_Simple を基本に、PushSW を3ケ追加し、 * 音量の増減、受信FM局の変更 を可能にしました。 * 受信局は、東京地区で受信できる周波数jを書き込んであります。 * ほかの地区では、プログラム11行目の presetFreq を地元FM局に周波数 * に変更してPICに書き込んでください。 * 音量や、受信局を変更すると変更内容をPIC内のEEPROMに書き込んでいます。 * このため、電源をOFFしても、その設定は保存され、次に電源をONとした * とき前の状態が再現されます。 * さらに、選局ボタン(station) を長押しすると、常に homeSt でプログラム上に * 指定した局が受信するようプログラムされています。 * また、変更動作が完了すると、省電力と雑音防止を兼ねPICはスリープ状態になり、 * クロックも停止します。 * PushSWのどれかを押すことでPICはスリープが解除され、ボタンの処理を * 再開します。 * * PIC18F14K50 MPLAB X IDE with XC8 Ver1.32 * Copyright (c) 2014 iwamoto All Rights Reserved * * ここまで「初めてのPIC」サイト、岩本さんコメント * ------------------------------------------------------------------------------ * <オリジナルとの相違点> * (1) PICの、MCLRピンを、RA3(選局SW)ポートとして使っているが * 外部リセットピンとして使うように変更。 * (2) 選局SWは、RA5に変更した。 * (3) デバッグ用のLEDポート(RC2)を追加 * (4) 音量調整は、追加したパワーアンプのハードVRにて行うように *    したので、VOL UP/DOWNのSWは削除した。(DAC出力レベルは固定にした) * (5) 受信周波数と、放送局名を、I2C液晶(ストリナ)に表示 * * 2016/6/2 N.Ishii * 2016/6/9 更新 * ワイドFMを受信出来るようにした。 ********************************************************************************/ //#define presetFreq 7610,7710,7950,8000,8130,8250,8470,0 #define presetFreq 7610,7710,7950,8000,8130,8250,8470,9050,9160,9300,0 // ワイドFM 3局追加 160609 #define long_ms 1000 // 長押し時間 ms //#define homeSt 1 // 長押しで選局する局番号 #define homeSt 3 // 長押しで選局する局番号 //#define minFreq 7600 // 最低周波数 #define minFreq 6400 // 最低周波数 //#define maxFreq 9000 // 最高周波数 #define maxFreq 9300 // 最高周波数:得にこれを参照してない 160608 #define stepFreq 10 // ステップ周波数 //#define SWs (PORTA|0b11000111) // SW 3ケの状態 #define SWs (PORTA|0b11011111) // RA5の選局SWのみ接続されている //#define VolUp !PORTAbits.RA5 // SW 音量 大 //#define Voldn !PORTAbits.RA4 // SW 音量 大 //#define station !PORTAbits.RA3 // SW 選局 #define station !PORTAbits.RA5 // SW 選局 #include #include "L_i2cLCD.h" //I2C接続LCD関数 //******************* コンフィグレーション **************************** #pragma config FOSC = IRC // 内部クロック #pragma config USBDIV = OFF, CPUDIV = NOCLKDIV #pragma config IESO = OFF, FCMEN = OFF, PLLEN = ON #pragma config BORV = 30, BOREN = OFF, PWRTEN = OFF #pragma config WDTPS = 32768, WDTEN = OFF //#pragma config MCLRE = OFF, HFOFST = OFF, XINST = OFF #pragma config HFOFST = OFF, MCLRE = ON, XINST = OFF #pragma config BBSIZ = OFF, LVP = OFF, STVREN = ON #pragma config CP1 = OFF, CP0 = OFF, CPD = OFF, CPB = OFF #pragma config WRT1 = OFF, WRT0 = OFF, WRTB = OFF, WRTC = OFF #pragma config EBTR1 = OFF, EBTR0 = OFF, EBTRB = OFF // //******************* 定義 ******************************************* #define _XTAL_FREQ 4000000 #define i2cStart() SSPCON2bits.SEN=1;while(SSPCON2bits.SEN) #define i2cStop() SSPCON2bits.PEN=1;while(SSPCON2bits.PEN) #define LED LATCbits.LATC2 //******************* プロトタイプ *********************************** void delay_ms (int); void i2cintl(void); void Bk1088_Write(unsigned int, unsigned int); void i2cTxData(char); void Freq_set(int); void Disp_Station(char); /* ********** EEROM に設定する 初期周波数番号 *********** */ //__EEPROM_DATA(1,22,0,0,0,0,0,0); //0番地:局、1番地:音量 __EEPROM_DATA(3,28,0,0,0,0,0,0); //0番地:局、1番地:音量 // ******************* main ****************************************** void main() { int FM_FREQ[] = {presetFreq}; // 周波数プリセット char st; // 受信中の局番号 signed char vol; // 音量 int SwTime; // SW を押している時間 char dummy; // 作業変数 OSCCON = 0b01010010; // 内部クロック4Mhz UCONbits.USBEN = 0 ; // USBは使用しない PORTA = 0x00; PORTB = 0x00; PORTC = 0x00; // 全ポート 0 // TRISA = 0xFF; TRISB = 0xFF; TRISC = 0xFF; // PortC すべて入力 TRISA = 0xFF; TRISB = 0xFF; TRISC = 0xFB; //RC2以外、すべて入力 ANSEL = 0x00; ANSELH = 0x00; // すべてデジタル // WPUA = 0xFF; WPUB = 0xFF; // 弱プルアップするピンを選択 WPUA = 0xFF; WPUB = 0xAF; // RB4:SDAと、RB6:SCL以外(外部でプルアップ)、弱プルアップ指定 INTCON2bits.nRABPU = 0; // 弱プルアップ有効 LED = 1; // Green LED ON delay_ms(1000); LED = 0; // Green LED OFF IOCA = 0b00111000; // PORTA 状態変化割り込み INTCONbits.RABIE = 1; // PIC側のI2C初期化:SSPを I2C Master mode、SCL 100kHz @ 4MHz に設定------ i2cintl(); // I2C液晶の初期化 LCD_int(); // LCDを初期化 LCD_ROMstr("Start DSP Radio"); // LCD上段にスタートメッセージ delay_ms(1000); // DSP初期化 受信バンド:FM 音量:28 ----------------------------- st = eeprom_read(0); // 起動時受信局番号 3:FM東京 vol = eeprom_read(1); // 起動時音量:28 Bk1088_Write(0x02, 0x6281); // power config //Bk1088_Write(0x05, 0x3740 + vol); // system config2:受信エリア日本=76 - 91MHz Bk1088_Write(0x05, 0x3640 + vol); // system config2:受信エリアFULL=64 - 108MHz 160609 Bk1088_Write(0x06, 0x0930); // system config3 Bk1088_Write(0x07, 0x0901); // test1 Bk1088_Write(0x14, 0x878E); // boot config 5 Bk1088_Write(0x1A, 0x0001); // boot config 11 Bk1088_Write(0x1B, 0x48D4); // analog config 1 Bk1088_Write(0x1D, 0x0200); // analog config 3 Bk1088_Write(0x1E, 0x80AA); // Bk1088_Write(0x20, 0x0EF7); // Bk1088_Write(0x21, 0x0600); // 33番地のレジスタに0x0600を書込まないととワイドFM受信不可 160609 Bk1088_Write(0x26, 0x8400); // delay_ms(500); // 遅延 Freq_set(FM_FREQ[st]); // 指定する局の周波数をセット Disp_Station(st); // 放送局名+周波数表示 Bk1088_Write(0x02,0x0281); // mute off 音を出す //******************************************************************** while(1){ while(SWs == 0xFF); // SW が押されるのを待つ delay_ms(5); // チャタリング防止 if(station){ // -------- 局を変更 ------------------------ st++; // 局番号を更新する if(FM_FREQ[st]==0)st=0; // 局番号の範囲確認 Freq_set(FM_FREQ[st]); // 指定する局の周波数をセット Disp_Station(st); // 放送局名+周波数表示 eeprom_write(0, st); // EEPROM 0番地 書込み } /* if(VolUp){ // -------- 音量 大 ------------------------ vol++; // 音量を上げる if(vol > 28)vol = 28; // 上限の確認 Bk1088_Write(0x05,0x3740 + vol); // 音量をセット eeprom_write(1, vol); // EEPROM 1番地 書込み } if(Voldn){ // -------- 音量 小 ---------------- vol--; // 音量を上げる if(vol < 0)vol = 0; // 下限の確認 Bk1088_Write(0x05,0x3740 + vol); // 音量をセット eeprom_write(1, vol); // EEPROM 1番地 書込み } */ SwTime = 0; while(SWs != 0xFF){ // SW が押されているなら delay_ms(1); // 離れるのを待つ if(!station)continue; // 選局 SW なら以下を実施 if(SwTime < long_ms){ // 長押しより 短いなら SwTime++; // 長押し時間を増やす }else if(SwTime == long_ms){ // 長押し指定時間なら SwTime++; // 長押し時間を増やし st = homeSt; // ホーム局を Freq_set(FM_FREQ[homeSt]); // 選局する Disp_Station(st); // 放送局名+周波数表示 eeprom_write(0, st); // EEPROM 0番地 書込み } // SW が離れるのを待つ } delay_ms(5); // チャタリング防止 dummy=PORTA; // 状態変化割込み準備 INTCONbits.RABIF = 0; // 状態変化割込み準備 NOP(); SLEEP(); // SW が押されるまでスリープ NOP(); } } //******************************************************************** // mS 単位の遅延 //******************************************************************** void delay_ms (int ms){ while(ms-- > 0)__delay_ms(1); } //******************************************************************** // SSPを I2C Master mode、SCL 100kHz @ 4MHz に設定 //******************************************************************** void i2cintl(void){ SSPCON1 = 0b00001000; // I2C Master modeにする SSPCON2 = 0x00; // PowerOn初期値にする SSPSTAT = 0b10000000; // スルーレート制御はOff // SSPADD = 9; // クロックの設定 100k@4MHz SSPADD = BaudConst; // クロックの設定 100k@4MHz SSPCON1bits.SSPEN = 1; // SSP 有効にする bit5 delay_ms(100); // PIC側のI2C初期化後、0.1秒後にスレーブ側の初期化を行う } //******************************************************************** // Bk1088_のレジスタに書き込む //******************************************************************** void Bk1088_Write(unsigned int add, unsigned int data) { i2cStart(); // 送信開始 i2cTxData(0x80); // Chipアドレス送信 i2cTxData(add << 1); // RegAdd + Write i2cTxData(data >> 8); // Register data MSB i2cTxData(data & 0xff); // Register data LSB i2cStop(); // 送信終了 __delay_us(500); } //******************************************************************** // SSPBUF に1文字保存し送信終了を待つ //******************************************************************** void i2cTxData(char data){ PIR1bits.SSPIF = 0; // 終了フラグクリア SSPBUF = data; // データセット while(!PIR1bits.SSPIF); // 送信終了待ち } //*****************************************************************/ // 新しい周波数をセットする // 引数は、freq //*****************************************************************/ void Freq_set(int freq){ signed int reg_val; reg_val=(freq - minFreq)/stepFreq; Bk1088_Write(0x0003, reg_val); // 周波数セット Bk1088_Write(0x0003, reg_val | 0x8000); // TUNEビットを立てる } //*****************************************************************/ // 受信周波数と、放送局名を、I2C液晶(ストリナ)に表示 // 引数は、st_num //*****************************************************************/ void Disp_Station(char st_num){ LCD_clr(); switch(st_num){ case 0: LCD_ROMstr("Inter-FM"); LCD_posyx(1,0); LCD_ROMstr("76.1MHz"); break; case 1: LCD_ROMstr("Housou_Daigaku"); LCD_posyx(1,0); LCD_ROMstr("77.1MHz"); break; case 2: LCD_ROMstr("NACK5"); LCD_posyx(1,0); LCD_ROMstr("79.5MHz"); break; case 3: LCD_ROMstr("TOKYO-FM"); LCD_posyx(1,0); LCD_ROMstr("80.0MHz"); break; case 4: LCD_ROMstr("J-WAVE"); LCD_posyx(1,0); LCD_ROMstr("81.3MHz"); break; case 5: LCD_ROMstr("NHK-FM"); LCD_posyx(1,0); LCD_ROMstr("82.5MHz"); break; case 6: LCD_ROMstr("Yokohama-FM"); LCD_posyx(1,0); LCD_ROMstr("84.7MHz"); break; /// ワイドFM 3局追加 160609 case 7: LCD_ROMstr("Wide_FM-TBS"); LCD_posyx(1,0); LCD_ROMstr("90.5MHz"); break; case 8: LCD_ROMstr("Wide_FM-Bunka"); LCD_posyx(1,0); LCD_ROMstr("91.6MHz"); break; case 9: LCD_ROMstr("HappyFM93"); LCD_posyx(1,0); LCD_ROMstr("93.0MHz"); break; default: break; } }