/******************************************************************************** * 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を受信出来るようにした。 * 2016/6/14 更新:_V1aとした。 * 液晶に、RSSI(電界強度値)を、suatus2レジスタから読取り、HEX表示及び、 * 3段階の受信レベルバーを表示。また同レジスタからstereo/monoビットを読取り、 * stereo/monoの表示("s:"/"m:")を追加。 * 尚、ステータス表示をメインループで常時行うため、スリープ機能は削除した。 ********************************************************************************/ #define presetFreq 7610,7710,7950,8000,8130,8250,8470,9050,9160,9300,0 // ワイドFM 3局追加 160609 #define long_ms 1000 // 長押し時間 ms #define homeSt 3 // 長押しで選局する局番号 #define minFreq 6400 // 最低周波数 #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 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 i2c_Ack() SSPCON2bits.ACKDT=0;SSPCON2bits.ACKEN=1;while(SSPCON2bits.ACKEN) #define i2c_NAck() SSPCON2bits.ACKDT=1;SSPCON2bits.ACKEN=1;while(SSPCON2bits.ACKEN) #define bk88_status2 0x0a //status2レジスタアドレス #define stereo_indi 0x0080 //stereo indicaterビット位置(bit7:'1'stereo, '0'mono)マスク定数 #define rx_level 0x007f //受信レベルビット位置(bit0-6:0x7f(127)がmaxレベル)マスク定数 #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); unsigned int Bk1088_Read(unsigned int); unsigned char i2c_Read( void ); /* ********** EEROM に設定する 初期周波数番号 *********** */ __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; // 作業変数 unsigned int read_buf; OSCCON = 0b01010010; // 内部クロック4Mhz UCONbits.USBEN = 0 ; // USBは使用しない TRISA = 0xFF; TRISB = 0xFF; TRISC = 0xFB; //RC2以外、すべて入力 ANSEL = 0x00; ANSELH = 0x00; // すべてデジタル WPUA = 0xFF; WPUB = 0xAF; // RB4:SDAと、RB6:SCL以外(外部でプルアップ)、弱プルアップ指定 INTCON2bits.nRABPU = 0; // 弱プルアップ有効 LED = 1; // Green LED ON delay_ms(1000); LED = 0; // Green LED OFF // PIC側のI2C初期化:SSPを I2C Master mode、SCL 100kHz @ 4MHz に設定 i2cintl(); // I2C液晶の初期化 LCD_int(); // LCDを初期化 LCD_ROMstr("Start DSP Radio"); // LCD上段にスタートメッセージ LCD_cg_ram_user_set(); // ユーザーキャラクタセット LCD_cmd(DDRAM_START_ADDRESS_SET); //change CGRAM -> DDRAM 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, 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){ 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); // チャタリング防止 /// ステータス表示 // stereo/mono表示 read_buf= Bk1088_Read(bk88_status2) & stereo_indi; LCD_posyx(0,12); if(read_buf == stereo_indi) LCD_ROMstr("s:"); else LCD_ROMstr("m:"); /// 受信レベル表示(レジスタ読み値+バー表示) read_buf= Bk1088_Read(bk88_status2) & rx_level; // 00〜 7Fの、RSSI値(BK1088の、10番地status2レジスタ、bit7〜 0の値)を表示 LCD_hex((char)read_buf); // 3段階のバー表示 if(read_buf <= 25){ // 0min LCD_posyx(1,13); LCD_ROMstr(" "); } else{ if((read_buf >= 26) && (read_buf <= 39)){ LCD_posyx(1,13); LCD_dat(0x03); // 低レベル・バー表示 LCD_ROMstr(" "); } if((read_buf >= 40) && (read_buf <= 53)){ LCD_posyx(1,13); LCD_dat(0x03); // 低レベル・バー表示 LCD_dat(0x04); // 中レベル・バー表示 LCD_ROMstr(" "); } if(read_buf >= 54){ // 127max LCD_posyx(1,13); LCD_dat(0x03); // 低レベル・バー表示 LCD_dat(0x04); // 中レベル・バー表示 LCD_dat(0x05); // 高レベル・バー表示 } } } } //******************************************************************** // 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); // 送信終了待ち } //******************************************************************** // Bk1088_のレジスタを読込む 16bit //******************************************************************** unsigned int Bk1088_Read(unsigned int add) { unsigned char msb, lsb; unsigned int ret_dat; i2cStart(); // 送信開始 i2cTxData(0x80); // Chipアドレス送信 ここまで書込みと共通 i2cTxData((add << 1) + 1); // RegAdd + Read msb= i2c_Read(); // read 1st 8bit i2c_Ack(); // ACK送信 lsb= i2c_Read(); // read 2st 8bit i2c_NAck(); // NACK送信 i2cStop(); // 送信終了 ret_dat= (msb << 8) + lsb; // return data return ret_dat; } //******************************************************************** // SSPBUF から1文字受信 //******************************************************************** unsigned char i2c_Read( void ){ SSPCON2bits.RCEN = 1; // データ受信を指示 while ( !SSPSTATbits.BF ); // 8ビット受信の完了を待つ return SSPBUF; // 受信データで復帰 } //*****************************************************************/ // 新しい周波数をセットする // 引数は、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("ホウソウ ダイガク"); 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("WideFM-TBS"); LCD_posyx(1,0); LCD_ROMstr("90.5MHz"); break; case 8: LCD_ROMstr("WideFM-ブンカ"); 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; } LCD_posyx(1,12); // 周波数表示横にアンテナ表示 LCD_dat(0x02); }