// // Ten-Tec 1254 CPU // // Version 1.5(量産バージョン) // // MCU: ATmega8 // FUSE: D1E3h(internal CR osc. 4MHz) // Compiler: AVR-GCC // // 2003.10.14 KAWAKAMI Yukio // 2004.8.26 FM-IFを10.7MHz以上にした場合のVCO切り換え不具合対策 // #include #include #include #include #define LF 10 #define ON 1 #define OFF 0 #define TRUE 1 #define FALSE 0 #define NOP asm volatile("nop\n"::) #define WDR asm volatile("wdr\n"::) #define SLEEP asm volatile("sleep\n"::) #define RESET asm volatile("rjmp\t0\n"::) typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned long ulong; // ポート割り当て 配線を優先したのでバラバラ #define SEG_A 5 // PD5 #define SEG_B 7 // PB7 #define SEG_C 6 // PB6 #define SEG_D 1 // PD1 #define RE_B 4 // PB4 #define RE_A 5 // PB5 #define ADIN 4 // PC4 #define POWER_OFF 2 // PD2 #define ENABLE 3 // PD3 #define CLK 4 // PD4 #define DIN 5 // PC5 #define VCO 3 // PC3 #define AM 2 // PC2 #define SSB 1 // PC1 #define FM 0 // PC0 #define LED1 3 // PB3 #define LED2 2 // PB2 #define LED3 1 // PB1 #define LED4 0 // PD0 #define LED5 6 // PD6 #define LED6 7 // PD7 #define LED7 0 // PB0 #define MODE_AM 0 #define MODE_SSB 1 #define MODE_MW 2 #define MODE_FM 3 #define LED_AM 12 // AM LED 点灯パターン #define LED_SSB 10 // SSB LED 点灯パターン #define LED_FM 11 // 真ん中の LED点灯パターン #define FREQ_MIN 1000 // AM/SSBモードの下限 #define FREQ_MAX 300000 // 〃 上限 #define MW_MIN 5220 // 中波の下限(0.1kHz単位) #define MW_MAX 16290 // 〃 上限( 〃 ) #define FM_MIN 760000 // FMモードの下限 #define EEPROM_MODE 1 // POWER-OFF時のモード #define EEPROM_FREQ1_H 2 // 〃 周波数(AM/SSB) #define EEPROM_FREQ1_M 3 #define EEPROM_FREQ1_L 4 #define EEPROM_FREQ2_H 5 // 〃 周波数(MW/FM) #define EEPROM_FREQ2_M 6 #define EEPROM_FREQ2_L 7 #define EEPROM_MEMORY 8 // メモリーch #define EEPROM_CLOCK 9 // 動作クロック補正値 #define EEPROM_CH_WAIT 10 // ch表示時間(100mS単位) #define EEPROM_FM_MAX 11 // FMモード時の最大周波数(MHz) #define EEPROM_FM_STEP 12 // 〃 ステップ(kHz) #define EEPROM_ENCORDER 13 // ロータリーエンコーダのタイプ #define EEPROM_FM_IF 14 // FMの IF周波数(100kHz単位) #define EEPROM_VCO 15 // VCO切替え周波数 #define EEPROM_MEM_START 20 // メモリー 1chあたり 4byte × MEM_MAX ch #define MEM_MAX 50 // メモリーの数 #define CONFIG_ENCORDER 1 // ロータリーエンコーダ選択 #define CONFIG_CH_WAIT 2 // ch表示時間 #define CONFIG_FM_MAX 3 // FMモード時の最大周波数 #define CONFIG_FM_STEP 4 // 〃 ステップ #define CONFIG_FM_IF 5 // 〃 IF周波数 #define CONFIG_VCO 6 // VCO切替え周波数 #define CONFIG_CLOCK 7 // 動作クロック微調整 #define CONFIG_CLEAR 8 // EEPROMオールクリア void write_eeprom(uint adrs, uchar data); uchar read_eeprom(uint adrs); void set145170(uchar bit, uint data); void set_freq(ulong freq); void set_mode(uchar mode); void print_freq(ulong freq); void print_ch(char ch); ulong formal_freq(ulong freq, ulong step); ulong read_memory_freq(char ch); uchar read_memory_mode(char ch); void write_memory(char ch, uchar mode, ulong freq); void set_switch(volatile uchar *flag, volatile uchar *old); uchar read_encorder(void); void config(void); void print_config(uchar id, uchar data); void config_encorder(uchar menu, uchar com); void config_ch_wait(uchar menu, uchar com); void config_fm_max(uchar menu, uchar com); void config_fm_step(uchar menu, uchar com); void config_fm_if(uchar menu, uchar com); void config_clock(uchar menu, uchar com); void config_clear(uchar menu, uchar com); void config_vco(uchar menu, uchar com); #define ENC_NOP 0 #define ENC_UP 1 #define ENC_DOWN 2 #define ENTER 3 #define INIT 4 PROGMEM uchar EncData[] = { // ロータリーエンコーダの動作シーケンス ENC_NOP, ENC_UP, ENC_DOWN, ENC_NOP, // 0 → 0, 1, 2, 3 ENC_DOWN, ENC_NOP, ENC_NOP, ENC_UP, // 1 → 0, 1, 2, 3 ENC_UP, ENC_NOP, ENC_NOP, ENC_DOWN, // 2 → 0, 1, 2, 3 ENC_NOP, ENC_DOWN, ENC_UP, ENC_NOP // 3 → 0, 1, 2, 3 }; ulong Freq_min; ulong Freq_max; uint Freq_step; ulong Freq; // 現在の周波数 100Hz単位であることに注意 uchar Mode; // 現在のモード uchar Mode_bak; ulong Freq_SW; // AM/SSBモードの周波数 ulong Freq_MW; // MW/FMモードの周波数 uchar Fast; char Memory; uchar Mem_write; // メモリー書き込みモード uint Mem_timer; // EEPROMから読みだした値を使う uint CH_wait; // チャンネル表示時間 ulong FM_max; // FMモード時の最大周波数 uchar FM_step; // 〃 周波数ステップ uchar FM_IF; // 〃 IF周波数 uchar Enc_type; // ロータリーエンコーダのタイプ ulong change_VCO; // VCO切替え周波数 volatile uchar SW_mode; volatile uchar SW_mode_old; volatile uchar SW_mw; volatile uchar SW_mw_old; volatile uchar SW_vm; volatile uchar SW_vm_old; volatile uchar SW_speed; volatile uchar SW_speed_old; volatile uchar LED_scan; volatile uchar LED_buff[7]; // LED表示バッファ volatile uchar Mode_Bit_buff; // 割込み処理中に MC145170に volatile uint Mode_Data_buff; // データをセットする為のバッファ volatile uchar Freq_Bit_buff; volatile uint Freq_Data_buff; volatile uchar Debug; //********************************* // タイマー2比較一致割り込み // 4MHz/64/125=500 約500Hz(内蔵CR発振なので誤差あり) //********************************* SIGNAL(SIG_OUTPUT_COMPARE2) { uchar led; // LEDを一旦消す cbi(PORTB, LED1); cbi(PORTB, LED2); cbi(PORTB, LED3); cbi(PORTD, LED4); cbi(PORTD, LED5); cbi(PORTD, LED6); cbi(PORTB, LED7); if (++LED_scan > 6){ LED_scan = 0; } if (LED_scan == 0){ // dpの点灯を防ぐ為にこのタイミングでPLL設定 // モード変更があれば実行 if (Mode_Bit_buff){ set145170(Mode_Bit_buff, Mode_Data_buff); Mode_Bit_buff = 0; } // 周波数変更があれば実行 if (Freq_Bit_buff){ set145170(Freq_Bit_buff, Freq_Data_buff); Freq_Bit_buff = 0; } } // 7SEG出力 led = LED_buff[LED_scan]; if (led & 1){ sbi(PORTD, SEG_A); } else { cbi(PORTD, SEG_A); } if (led & 2){ sbi(PORTB, SEG_B); } else { cbi(PORTB, SEG_B); } if (led & 4){ sbi(PORTB, SEG_C); } else { cbi(PORTB, SEG_C); } if (led & 8){ sbi(PORTD, SEG_D); } else { cbi(PORTD, SEG_D); } if (led & 0x80){ sbi(PORTD, CLK); } else { cbi(PORTD, CLK); } // スキャン出力・スイッチ入力 cbi(DDRC, DIN); switch(LED_scan){ case 0: sbi(PORTB, LED7); break; case 1: sbi(PORTD, LED6); break; case 2: sbi(PORTD, LED5); break; case 3: sbi(PORTD, LED4); set_switch(&SW_mode, &SW_mode_old); break; case 4: sbi(PORTB, LED3); set_switch(&SW_mw, &SW_mw_old); break; case 5: sbi(PORTB, LED2); set_switch(&SW_vm, &SW_vm_old); break; default: sbi(PORTB, LED1); set_switch(&SW_speed, &SW_speed_old); break; } } //********************************* // スイッチ処理 //********************************* void set_switch(volatile uchar *flag, volatile uchar *old){ *old <<= 1; if (inp(PINC)&(1<> 16); write_eeprom(EEPROM_FREQ1_M, Freq_SW >> 8); write_eeprom(EEPROM_FREQ1_L, Freq_SW); write_eeprom(EEPROM_FREQ2_H, Freq_MW >> 16); write_eeprom(EEPROM_FREQ2_M, Freq_MW >> 8); write_eeprom(EEPROM_FREQ2_L, Freq_MW); write_eeprom(EEPROM_MEMORY, (uchar)Memory); read_eeprom(0); // 書込み終了まで待つ SLEEP; // 停止 } //********************************* // メインルーチン //********************************* int main (void) { uint i; uchar osc, *p; cli(); // 割込み禁止 // ATmega8 SRAMクリア p = (uchar *)0x60; for (i = 0; i < 1024; i++){ *p++ = 0; } for (i = 0; i < 7; i++){ LED_buff[i] = 0x0F; } sbi(ACSR, ACD); // アナログコンパレータ禁止 // ポートの入出力設定 outp((1<= 50)&&(osc <= 200)){ outp(osc, OSCCAL); } // EEPROMから各種設定読み込み CH_wait = (uint)read_eeprom(EEPROM_CH_WAIT) * (100/2); if (CH_wait > (5000/2)) CH_wait = 1500/2; FM_max = (ulong)read_eeprom(EEPROM_FM_MAX) * 10000; if (FM_max > 1080000) FM_max = 900000; FM_step = read_eeprom(EEPROM_FM_STEP); if ((FM_step != 50)&&(FM_step != 100)) FM_step = 50; Enc_type = read_eeprom(EEPROM_ENCORDER); if (Enc_type > 1) Enc_type = 0; FM_IF = read_eeprom(EEPROM_FM_IF); if ((FM_IF < 100)||(FM_IF == 255)) FM_IF = 107; i = read_eeprom(EEPROM_VCO); switch(i){ case 12: change_VCO = 125000; break; case 14: change_VCO = 145000; break; case 15: change_VCO = 159000; break; case 16: change_VCO = 165000; break; case 17: change_VCO = 179500; break; case 18: change_VCO = 185000; break; case 19: change_VCO = 195000; break; case 20: change_VCO = 205000; break; default: change_VCO = 132400; break; } // EEPROMから周波数読み込み Mode = read_eeprom(EEPROM_MODE); if (Mode == 0xFF){ // プログラム書き換え直後 Freq_SW = FREQ_MIN; Freq_MW = MW_MIN; Freq = Freq_SW; Mode = MODE_AM; Memory = -1; } else { Freq_SW = ((ulong)read_eeprom(EEPROM_FREQ1_H) << 16) + ((ulong)read_eeprom(EEPROM_FREQ1_M) << 8) + ((ulong)read_eeprom(EEPROM_FREQ1_L)); Freq_MW = ((ulong)read_eeprom(EEPROM_FREQ2_H) << 16) + ((ulong)read_eeprom(EEPROM_FREQ2_M) << 8) + ((ulong)read_eeprom(EEPROM_FREQ2_L)); Memory = (char)read_eeprom(EEPROM_MEMORY); if (Memory > 0){ Mode_bak = Mode; Mode = read_memory_mode(Memory); Freq = read_memory_freq(Memory); } else { if ((Mode == MODE_MW)||(Mode == MODE_FM)){ Freq = Freq_MW; } else { Freq = Freq_SW; } } } outp(0x18, WDTCR); // WDCEとWDEを1にしてタイマー変更をする outp(0x1F, WDTCR); // ウォッチドッグタイマーセット 約2秒/5V outp(0x83, MCUCR); // INT0(POWER-OFF)立ち上がり割り込み,スリープ許可 sbi(GICR, INT0); // 許可 outp(0x0C, TCCR2); // 比較一致動作, プリスケーラ 1/64 outp(125-1, OCR2); // タイマカウント最大値 4MHz/64/125=500 sbi(TIMSK, OCIE2); // 比較割り込み許可 sei(); // 割り込み許可 // 起動時のスイッチチェック for (i = 0; i < 50; i++){ SLEEP; } if (SW_mw){ config(); // MWボタンが押されていたら設定モード // ボタンが放されるまで待つ while (SW_mode || SW_mw || SW_vm || SW_speed) SLEEP; RESET; } set_mode(Mode); set_freq(Freq); if (Memory > 0){ print_ch(Memory); // ch表示 } else { print_freq(Freq); // 周波数表示 } read_encorder(); // エンコーダ初期値設定 for (;;){ // ボタンが放されるまで待つ while (SW_mode || SW_mw || SW_vm || SW_speed) SLEEP; WDR; SLEEP; // エンコーダ読み込み switch (read_encorder()){ case ENC_UP: if (Memory > 0){ if (++Memory > MEM_MAX) Memory = 1; if (!Mem_write){ Mode = read_memory_mode(Memory); Freq = read_memory_freq(Memory); // PLL設定 set_mode(Mode); set_freq(Freq); } print_ch(Memory); // ch表示 } else { if (Fast){ Freq += 1000; Freq = formal_freq(Freq, 1000); } else { Freq += (ulong)Freq_step; } if ((Mode == MODE_MW)&&(Freq > MW_MAX)&&(FM_max != 0)){ Mode = MODE_FM; Freq = FM_MIN; set_mode(Mode); } Freq = formal_freq(Freq, (ulong)Freq_step); set_freq(Freq); // PLL設定 print_freq(Freq); // LED表示 } break; case ENC_DOWN: if (Memory > 0){ if (--Memory < 1) Memory = MEM_MAX; if (!Mem_write){ Mode = read_memory_mode(Memory); Freq = read_memory_freq(Memory); // PLL設定 set_mode(Mode); set_freq(Freq); } print_ch(Memory); // ch表示 } else { if (Fast){ Freq -= 1000; Freq = formal_freq(Freq, 1000); } else { Freq -= (ulong)Freq_step; } if ((Mode == MODE_FM)&&(Freq < FM_MIN)){ Mode = MODE_MW; Freq = MW_MAX; set_mode(Mode); } Freq = formal_freq(Freq, (ulong)Freq_step); set_freq(Freq); // PLL設定 print_freq(Freq); // LED表示 } break; default: // メモリーモードでタイマーが切れたら周波数表示 if ((Memory > 0) && Mem_timer && (--Mem_timer == 0)){ print_freq(Freq); } break; } if (SW_mw){ // MWボタンが押された if ((Memory <= 0) && !Mem_write){ Mem_write = TRUE; Memory *= -1; if (Memory == 0) Memory = 1; if ((Memory < 1)||(Memory > MEM_MAX)) Memory = 1; print_ch(Memory); // ch表示 } else if (Mem_write){ Mem_write = FALSE; write_memory(Memory, Mode, Freq); // メモリーをEEPROM書き込み Memory *= -1; print_freq(Freq); // LED表示 } } else if (SW_vm){ // V/Mボタンが押されてた Fast = FALSE; if (Mem_write){ // メモリー書き込みモードで押された場合は書き込みキャンセル Mem_write = FALSE; Memory *= -1; print_freq(Freq); // LED表示 } else { if (Memory <= 0){ if ((Mode == MODE_MW)||(Mode == MODE_FM)){ Freq_MW = Freq; } else { Freq_SW = Freq; } Mode_bak = Mode; Memory *= -1; if ((Memory < 1)||(Memory > MEM_MAX)) Memory = 1; Mode = read_memory_mode(Memory); Freq = read_memory_freq(Memory); // PLL設定 set_mode(Mode); set_freq(Freq); print_ch(Memory); // ch表示 } else { Memory *= -1; Mode = Mode_bak; if ((Mode == MODE_MW)||(Mode == MODE_FM)){ Freq = Freq_MW; } else { Freq = Freq_SW; } set_mode(Mode); set_freq(Freq); // PLL設定 print_freq(Freq); // LED表示 } } } else if ((Memory <= 0) && SW_speed && ((Mode == MODE_AM)||(Mode == MODE_SSB))){ // スピードボタンが押された Fast ^= 1; if (Fast){ LED_buff[6] |= 0x80; } else { LED_buff[6] &= 0x7F; } } else if ((Memory <= 0) && SW_mode){ // MODEボタンが押された Fast = FALSE; if (Mode == MODE_AM){ Mode = MODE_SSB; Freq_SW = Freq; } else if (Mode == MODE_SSB){ Freq_SW = Freq; Freq = Freq_MW; if (Freq > MW_MAX){ Mode = MODE_FM; } else { Mode = MODE_MW; } } else { Freq_MW = Freq; Freq = Freq_SW; Mode = MODE_AM; } set_mode(Mode); // Freq = formal_freq(Freq, Freq_step); set_freq(Freq); // PLL設定 print_freq(Freq); // LED表示 } } } //********************************* // 設定モード //********************************* void config(void){ uchar com; uchar menu; read_encorder(); // エンコーダ初期値 menu = 1; config_encorder(menu, INIT); // 初期表示 for (;;){ // ボタンが放されるまで待つ while (SW_mode || SW_mw || SW_vm || SW_speed) SLEEP; WDR; SLEEP; com = ENC_NOP; if (SW_mw){ // [MW] データ書きこみ com = ENTER; } else if (SW_mode){ // [MODE] 次のメニュー if (++menu > CONFIG_CLEAR) menu = 1; com = INIT; } else if (SW_vm){ // [V/M] 設定モードを抜ける read_eeprom(0); // EEPROM書込み終了まで待つ return; } if (com == ENC_NOP){ // エンコーダ読み込み com = read_encorder(); } if (com != ENC_NOP){ switch(menu){ case CONFIG_ENCORDER: config_encorder(menu, com); break; case CONFIG_CH_WAIT: config_ch_wait(menu, com); break; case CONFIG_FM_MAX: config_fm_max(menu, com); break; case CONFIG_FM_STEP: config_fm_step(menu, com); break; case CONFIG_FM_IF: config_fm_if(menu, com); break; case CONFIG_VCO: config_vco(menu, com); break; case CONFIG_CLOCK: config_clock(menu, com); break; case CONFIG_CLEAR: config_clear(menu, com); break; default: menu = 1; break; } } } } //********************************* // 動作クロック微調整 //********************************* void config_clock(uchar menu, uchar com){ uchar osc; osc = inp(OSCCAL); if (com == ENC_UP){ if (osc < 200) osc++; outp(osc, OSCCAL); } else if (com == ENC_DOWN){ if (osc > 50) --osc; outp(osc, OSCCAL); } else if (com == ENTER){ write_eeprom(EEPROM_CLOCK, osc); } else if (com == INIT){ osc = read_eeprom(EEPROM_CLOCK); if ((osc >= 50)&&(osc <= 200)){ outp(osc, OSCCAL); } else { osc = inp(OSCCAL); } } print_config(menu, osc); } //********************************* // ch表示時間設定 //********************************* void config_ch_wait(uchar menu, uchar com){ static uchar tm = 15; if (com == ENC_UP){ if (tm < 50) tm++; } else if (com == ENC_DOWN){ if (tm > 0) --tm; } else if (com == ENTER){ write_eeprom(EEPROM_CH_WAIT, tm); } else if (com == INIT){ tm = read_eeprom(EEPROM_CH_WAIT); if (tm > 50){ tm = 15; } } print_config(menu, tm); if (LED_buff[4] == 0x0F){ LED_buff[4] = 0; } LED_buff[4] |= 0x80; // 小数点表示 } //********************************* // FMモード上限周波数設定 //********************************* void config_fm_max(uchar menu, uchar com){ static uchar freq = 0; if (com == ENC_UP){ if (freq < 108) freq++; if (freq < 77) freq = 77; } else if (com == ENC_DOWN){ if (freq > 0) --freq; if (freq < 77) freq = 0; } else if (com == ENTER){ write_eeprom(EEPROM_FM_MAX, freq); } else if (com == INIT){ freq = read_eeprom(EEPROM_FM_MAX); if (freq < 77) freq = 0; if (freq > 108) freq = 90; } print_config(menu, freq); } //********************************* // FMモードステップ設定 //********************************* void config_fm_step(uchar menu, uchar com){ static uchar freq = 50; if (com == ENC_UP){ freq = 100; } else if (com == ENC_DOWN){ freq = 50; } else if (com == ENTER){ write_eeprom(EEPROM_FM_STEP, freq); } else if (com == INIT){ freq = read_eeprom(EEPROM_FM_STEP); if ((freq != 50)&&(freq != 100)){ freq = 50; } } print_config(menu, freq); } //********************************* // FMモード IF周波数設定 //********************************* void config_fm_if(uchar menu, uchar com){ static uchar freq = 107; if (com == ENC_UP){ if (freq < 254) freq++; } else if (com == ENC_DOWN){ if (freq > 100) --freq; } else if (com == ENTER){ write_eeprom(EEPROM_FM_IF, freq); } else if (com == INIT){ freq = read_eeprom(EEPROM_FM_IF); if ((freq < 100)||(freq == 255)){ freq = 107; } } print_config(menu, freq); LED_buff[4] |= 0x80; } //********************************* // ロータリーエンコーダ選択 //********************************* void config_encorder(uchar menu, uchar com){ static uchar sel = 0; if (com == ENC_UP){ sel = 1; } else if (com == ENC_DOWN){ sel = 0; } else if (com == ENTER){ write_eeprom(EEPROM_ENCORDER, sel); Enc_type = sel; // すぐに反映 } else if (com == INIT){ sel = read_eeprom(EEPROM_ENCORDER); if (sel > 1){ sel = 0; } } if (sel == 0){ print_config(menu, 1); // デフォルト } else { print_config(menu, 4); // 秋月タイプ } } //********************************* // EEPROM オールクリア //********************************* void config_clear(uchar menu, uchar com){ static uchar clr = 99; if (com == ENC_UP){ if (clr < 99) clr++; } else if (com == ENC_DOWN){ if (clr > 0) --clr; } else if (com == ENTER){ if (clr == 0){ int i; for (i = 0; i < 512; i++){ write_eeprom(i, 0xFF); } } } else if (com == INIT){ clr = 99; } print_config(menu, clr); } //********************************* // VCO切替え周波数選択 //********************************* void config_vco(uchar menu, uchar com){ static uchar freq = 13; if (com == ENC_UP){ if (freq < 20) freq++; } else if (com == ENC_DOWN){ if (freq > 12) --freq; } else if (com == ENTER){ write_eeprom(EEPROM_VCO, freq); } else if (com == INIT){ freq = read_eeprom(EEPROM_VCO); if ((freq < 12)||(freq > 20)){ freq = 13; } } print_config(menu, freq); } //********************************* // モード設定 //********************************* void set_mode(uchar m){ cli(); // 割り込み禁止 switch (m){ case MODE_SSB: cbi(PORTC, FM); cbi(PORTC, AM); // 基準周波数 3.58MHz/1432 = 2.5kHz Mode_Bit_buff = 15; Mode_Data_buff = 1432; Freq_min = FREQ_MIN; Freq_max = FREQ_MAX; Freq_step = 25; LED_buff[6] = LED_SSB; sbi(PORTC, SSB); break; case MODE_MW: cbi(PORTC, FM); cbi(PORTC, SSB); // 基準周波数 3.58MHz/3580 = 1kHz Mode_Bit_buff = 15; Mode_Data_buff = 3580; Freq_min = MW_MIN; Freq_max = MW_MAX; Freq_step = 90; LED_buff[6] = LED_AM; sbi(PORTC, AM); break; case MODE_FM: cbi(PORTC, AM); cbi(PORTC, SSB); // 基準周波数 3.58MHz/1432 = 2.5kHz Mode_Bit_buff = 15; Mode_Data_buff = 1432; Freq_min = FM_MIN; Freq_max = FM_max; Freq_step = (uint)FM_step * 10; LED_buff[6] = LED_FM; sbi(PORTC, FM); break; default: cbi(PORTC, FM); cbi(PORTC, SSB); // 基準周波数 3.58MHz/1432 = 2.5kHz Mode_Bit_buff = 15; Mode_Data_buff = 1432; Freq_min = FREQ_MIN; Freq_max = FREQ_MAX; Freq_step = 50; LED_buff[6] = LED_AM; sbi(PORTC, AM); break; } sei(); // 割り込み許可 } //********************************* // 周波数を正規化 //********************************* ulong formal_freq(ulong freq, ulong step){ ulong mod; if (freq < Freq_min){ return Freq_min; } else if (freq > Freq_max){ return Freq_max; } mod = freq % step; if (mod == 0){ return freq; } if (mod >= (step / 2)){ freq += step - mod; } else { freq -= mod; } return freq; } //********************************* // PLL 周波数設定 //********************************* void set_freq(ulong freq){ if (freq < FM_MIN){ // 短波帯以下 if (freq >= change_VCO){ cbi(PORTC, VCO); } else { sbi(PORTC, VCO); } freq += 450000; // 1st IF = 45MHz if (Mode == MODE_MW){ freq /= 10; // PLL基準周波数 1kHz } else { freq /= 25; // PLL基準周波数 2.5kHz } } else { // FMバンド freq -= (ulong)FM_IF * 1000; // IF補正 if (freq >= (change_VCO + 450000)){ cbi(PORTC, VCO); } else { sbi(PORTC, VCO); } freq /= 25; // PLL基準周波数 2.5kHz } Freq_Bit_buff = 16; Freq_Data_buff = (uint)freq; } //********************************* // 周波数を LED表示 //********************************* void print_freq(ulong freq){ uchar i; uchar buff[6]; if (freq < FM_MIN){ // 短波帯以下 for (i = 5; i != 0xFF; --i){ buff[i] = (uchar)(freq % 10); freq /= 10; } if (((Memory <= 0)&&(Mode == MODE_MW)) ||((Memory > 0) && !Mem_write && (read_memory_mode(Memory) == MODE_MW)) ||((Memory > 0) && Mem_write && (Mode == MODE_MW))){ if (buff[1] == 0){ buff[1] = 0x0f; } } else { buff[1] |= 0x80; } if (buff[0] == 0){ buff[0] = 0x0f; } buff[4] |= 0x80; } else { // FMバンド freq /= 10; for (i = 5; i != 0xFF; --i){ buff[i] = (uchar)(freq % 10); freq /= 10; } if (buff[0] == 0){ buff[0] = 0x0f; } buff[2] |= 0x80; } if (Memory <= 0){ buff[5] |= 0x80; // ダイレクトチューニング時は最下位dpが点灯 } // LEDバッファへ転送 for (i = 0; i <= 5; i++){ LED_buff[i] = buff[i]; } } //********************************* // 設定モード表示 //********************************* void print_config(uchar id, uchar data){ uchar i; uchar buff[6]; buff[0] = id / 10; if (buff[0] == 0) buff[0] = 0x0F; buff[1] = (id % 10) | 0x80; buff[2] = 0x0F; buff[3] = data / 100; if (buff[3] == 0) buff[3] = 0x0F; data = data % 100; buff[4] = data / 10; if ((buff[4] == 0)&&(buff[3] == 0x0F)) buff[4] = 0x0F; buff[5] = data % 10; // LEDバッファへ転送 for (i = 0; i <= 5; i++){ LED_buff[i] = buff[i]; } } //********************************* // メモリーchを LED表示 //********************************* void print_ch(char ch){ LED_buff[0] = 0x0F; LED_buff[1] = 0x0F; LED_buff[2] = 0x0F; LED_buff[3] = 0x0A; // c 表示 LED_buff[4] = ch / 10; LED_buff[5] = ch % 10; if (read_memory_freq(ch) != FREQ_MIN){ LED_buff[5] |= 0x80; // メモリー済みな場合は最下位dp点灯 } Mem_timer = CH_wait; // 表示タイマーセット } //********************************* // MC145170コマンド出力 // 割込み禁止状態で実行すること //********************************* void set145170(uchar bit, uint data){ uchar i; cbi(PORTD, CLK); // CLK = L sbi(DDRC, DIN); // DIN = out cbi(PORTD, ENABLE); // ENABLE = L for (i = 16; i > 0; --i){ if (i <= bit){ if (data >= 0x8000){ sbi(PORTC, DIN); } else { cbi(PORTC, DIN); } sbi(PORTD, CLK); cbi(PORTD, CLK); } data <<= 1; } sbi(PORTD, ENABLE); // ENABLE = H cbi(PORTC, DIN); cbi(DDRC, DIN); // DIN = in } //********************************* // メモリー周波数読み込み //********************************* ulong read_memory_freq(char ch){ ulong f; ch = (ch - 1) * 4 + EEPROM_MEM_START + 1; f = (ulong)read_eeprom(ch++) << 16; f += (ulong)read_eeprom(ch++) << 8; f += (ulong)read_eeprom(ch); if (f >= 0xFFFFFF){ return FREQ_MIN; } else { return f; } } //********************************* // メモリーモード読み込み //********************************* uchar read_memory_mode(char ch){ uchar mode; ch = (ch - 1) * 4 + EEPROM_MEM_START; mode = read_eeprom(ch); if (mode == 0xFF){ return MODE_AM; } else { return mode; } } //********************************* // ロータリーエンコーダ読み込み //********************************* uchar read_encorder(void){ static uchar enc = 0; enc = ((enc & 3) << 2) | ((inp(PINB) & 0x30)>>4); if (!Enc_type){ return PRG_RDB(&EncData[enc]); } else { if (enc == 0x01){ return ENC_UP; } else if (enc == 0x0B){ return ENC_DOWN; } else { return ENC_NOP; } } } //********************************* // メモリー書き込み //********************************* void write_memory(char ch, uchar mode, ulong freq){ ch = (ch - 1) * 4 + EEPROM_MEM_START; write_eeprom(ch++, mode); write_eeprom(ch++, freq >> 16); write_eeprom(ch++, freq >> 8); write_eeprom(ch, freq); } //******************************************************* // EEPROM 書き込み //******************************************************* void write_eeprom(uint adrs, uchar data){ // 同じ内容なら書き込み動作を行わない if (read_eeprom(adrs) != data){ while(inp(EECR) & (1<> 8, EEARH); outp(adrs, EEARL); outp(data, EEDR); sbi(EECR, EEMWE); sbi(EECR, EEWE); } } //******************************************************* // EEPROM 読み込み //******************************************************* uchar read_eeprom(uint adrs){ while(inp(EECR) & (1<> 8, EEARH); outp(adrs, EEARL); sbi(EECR, EERE); return inp(EEDR); }