// // Ten-Tec 1254 CPU // // MCU: AT90S4433 // Compiler: AVR-GCC // // 2003.9.25 KAWAKAMI Yukio // #define ENCODER_TYPE 0 // 0:通常 1:秋月で売ってるALPS製 #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; // 7SEG出力(PB) #define SEG_A 2 // PB #define SEG_B 3 #define SEG_C 4 #define SEG_D 5 // LED COMMON(PC, PB) #define LED1 0 // PC #define LED2 1 #define LED3 2 #define LED4 3 #define LED5 4 #define LED6 5 #define LED7 0 // PB0 #define VCO 1 // PB1 #define ENABLE 7 // PD7 #define CLK 6 // PD6 #define DIN 5 // PD5 #define SSB 4 // PD4 #define AM 3 // PD3 #define POWER_OFF 2 // PD2 #define RE_B 1 // PD1 #define RE_A 0 // PD0 #define MODE_AM 0 #define MODE_SSB 1 #define MODE_MW 2 #define LED_AM 12 // AM LED 点灯パターン #define LED_SSB 10 // SSB LED 点灯パターン #define LED_MID 11 // 真ん中の LED点灯パターン #define MW_MIN 5220 // 中波の下限(0.1kHz単位) #define MW_MAX 16290 // 〃 上限( 〃 ) #define FREQ_MIN 1000 // AM/SSBモードの下限 #define FREQ_MAX 300000 // 〃 上限 #define MEM_TIME 1500 // メモリーモード時のチャンネル表示時間(mS) #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) #define EEPROM_FREQ2_M 6 #define EEPROM_FREQ2_L 7 #define EEPROM_MEMORY 8 // メモリーch #define EEPROM_MEM_START 10 // メモリー 1chあたり 4byte × MEM_MAX ch #define MEM_MAX 50 // メモリーの数 void write_eeprom(uchar adrs, uchar data); uchar read_eeprom(uchar 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); #define ENC_NOP 0 #define ENC_UP 1 #define ENC_DOWN 2 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モードの周波数 uchar Fast; char Memory; //char Memory_bak; uchar Mem_write; // メモリー書き込みモード uint Mem_timer; 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 Debug; //********************************* // タイマー0オーバーフロー割り込み // 3.58MHz/64/112=499.44 約500Hz //********************************* SIGNAL(SIG_OVERFLOW0) { // 次の割り込み設定 outp((uchar)(256-112), TCNT0); if (++LED_scan > 6){ LED_scan = 0; } // LEDを一旦消す outp((inp(PORTB)&(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, Memory); read_eeprom(0); // 書込み終了まで待つ // 電圧が上がるまで待つ while(inp(PIND)&(1< 0){ Mode_bak = Mode; Mode = read_memory_mode(Memory); Freq = read_memory_freq(Memory); } else { if (Mode == MODE_MW){ Freq = Freq_MW; } else { Freq = Freq_SW; } } } set_mode(Mode); set_freq(Freq); if (Memory > 0){ print_ch(Memory); // ch表示 } else { print_freq(Freq); // 周波数表示 } sei(); // 割り込み許可 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; } 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; } 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){ 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){ 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; } else if (Mode == MODE_SSB){ Freq_SW = Freq; Freq = Freq_MW; 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 set_mode(uchar m){ cli(); // 割り込み禁止 switch (m){ case MODE_SSB: cbi(PORTD, AM); set145170(15, 1432); // 基準周波数 3.58MHz/1432 = 2.5kHz Freq_min = FREQ_MIN; Freq_max = FREQ_MAX; Freq_step = 25; LED_buff[6] = LED_SSB; sbi(PORTD, SSB); break; case MODE_MW: cbi(PORTD, SSB); set145170(15, 3580); // 基準周波数 3.58MHz/3580 = 1kHz Freq_min = MW_MIN; Freq_max = MW_MAX; Freq_step = 90; LED_buff[6] = LED_AM; sbi(PORTD, AM); break; default: cbi(PORTD, SSB); set145170(15, 1432); // 基準周波数 3.58MHz/1432 = 2.5kHz Freq_min = FREQ_MIN; Freq_max = FREQ_MAX; Freq_step = 50; LED_buff[6] = LED_AM; sbi(PORTD, 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 >= 132400){ cbi(PORTB, VCO); } else { sbi(PORTB, VCO); } freq += 450000; // 1st IF = 45MHz if (Mode == MODE_MW){ freq /= 10; // 基準周波数 1kHz } else { freq /= 25; // 基準周波数 2.5kHz } cli(); set145170(16, (uint)freq); sei(); } //********************************* // 周波数を LED表示 //********************************* void print_freq(ulong freq){ int i; cli(); // 割込み禁止 for (i = 5; i >= 0; --i){ LED_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 (LED_buff[1] == 0){ LED_buff[1] = 0x0f; } } else { LED_buff[1] |= 0x80; } if (LED_buff[0] == 0){ LED_buff[0] = 0x0f; } LED_buff[4] |= 0x80; if (Memory <= 0){ LED_buff[5] |= 0x80; // ダイレクトチューニング時は最下位dpが点灯 } sei(); // 割り込み許可 } //********************************* // メモリーchを LED表示 //********************************* void print_ch(char ch){ cli(); // 割込み禁止 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点灯 } sei(); // 割り込み許可 Mem_timer = MEM_TIME/2; // 表示タイマーセット } //********************************* // MC145170コマンド出力 // 割込み禁止状態で実行すること //********************************* void set145170(uchar bit, uint data){ uchar i; uchar clk; clk = inp(PIND)&(1< 0; --i){ if (i <= bit){ if (data >= 0x8000){ sbi(PORTD, DIN); } else { cbi(PORTD, DIN); } sbi(PORTD, CLK); cbi(PORTD, CLK); } data <<= 1; } sbi(PORTD, ENABLE); // ENABLE = H cbi(PORTD, DIN); cbi(DDRD, DIN); // DIN = in if (clk){ sbi(PORTD, CLK); // CLK復元 } // スキャン出力 if (LED_scan == 0){ sbi(PORTB, LED7); } else { outp(1 << (6 - LED_scan), PORTC); } } //********************************* // メモリー周波数読み込み //********************************* 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); return f; } //********************************* // メモリーモード読み込み //********************************* uchar read_memory_mode(char ch){ ch = (ch - 1) * 4 + EEPROM_MEM_START; return read_eeprom(ch); } //********************************* // ロータリーエンコーダ読み込み //********************************* uchar read_encorder(void){ static uchar enc = 0; enc = ((enc & 3) << 2) | (inp(PIND) & 3); #if ENCOEDER_TYPE if ((enc & 7) == 1){ return ENC_UP; } else if ((enc & 7) == 3){ return ENC_DOWN; } else { return ENC_NOP; } #else return PRG_RDB(&EncData[enc]); #endif } //********************************* // メモリー書き込み //********************************* 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(uchar 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(uchar adrs){ while(inp(EECR) & (1<> 8, EEARH); outp(adrs, EEARL); sbi(EECR, EERE); return inp(EEDR); }