少年カメラ・クラブ

子供心を失わない大人であり続けたいと思います。

FT-817コントローラ

2010-12-07 22:37:55 | アマチュア無線
大分苦戦したが、なんとかFT-817controllerが完成した。やはり無線機とArduinoの通信部分で苦労した。結果的には、コマンドを送るときに少し余裕を持ってdelayを入れてやることによってうまく通信ができるようになった。あまり急いでコマンドを送ると無線機側がbusyになってしまうらしい。あっちこっちをつぎはぎだらけになってみっともないソースだが、備忘録がわりに貼りつけておこうと思う。結構なサイズにはなった。

//FT-817 CONTROLLER
// FT_817CONTROLLER 2010/12/6
//
#include <LiquidCrystal.h>

//Constants for variable-register
#define POTENTIO 2 // ANALOG input for variable-register
#define POTVALUE_NUL 530 //variable-register center value
#define POTVALUE_NUL_ZONE 50 //variabe-register nul zone width
#define FACTOR 1 //variable-register conversion factor

//Dial scan speed
#define SLOW_DOWN1 20 //dial slow down near0
#define SLOW_DOWN2 15 //dial slow down away form 0
#define FM_LARGE 10000 //144/430FM large increment
#define FM_SMALL 1000 //144/430FM small increment

//Constants for keypad
#define KEYPAD_PIN 1 // ANALOG input
#define KEYPAD_NUM 12 // KeyPad number
#define NO_KEY 99 //key off reterun value
#define KEY_ASTERISK 11 //key value for asterisk
#define KEY_DELAY 130 //waiting time foe key
#define KEY_SHARP 12 //key value for sharp

//FT-817 Commands
#define SET_FREQ 1 //Command for sending frequency to FT-817
#define FTYPE 7 //Command for transmission type change
#define PTT_ON 8 //Command for PTT ON
#define PTT_OFF 0x88 //Command for PTT OFF
#define RECEIVE_STATUS 0xE7 //Command for Receiving satus

//Frequency Boundary for Amature Bands
#define LOW_LIMIT1P8 180000 //Lowest Frequency at 1.8MHz Band
#define HIGH_LIMIT1P8 191250 //Highest frequency at 1.8MHz Band
#define LOW_LIMIT3P5 350000 //Lowest Frequency at 3.5MHz Band
#define HIGH_LIMIT3P5 368700 //Highest frequency at 3.5MHz Band
#define LOW_LIMIT3P8 370200 //Lowest Frequency at 3.8MHz Band
#define HIGH_LIMIT3P8 380500 //Highest frequency at 3.8MHz Band
#define LOW_LIMIT7 700000 //Lowest Frequency at 7MHz Band
#define HIGH_LIMIT7 720000 //Highest frequency at 7MHz Band
#define LOW_LIMIT10 1010000 //Lowest Frequency at 10MHz Band
#define HIGH_LIMIT10 1015000 //Highest frequency at 10MHz Band
#define LOW_LIMIT14 1400000 //Lowest Frequency at 14MHz Band
#define HIGH_LIMIT14 1435000 //Highest frequency at 14MHz Band
#define LOW_LIMIT18 1806800 //Lowest Frequency at 18MHz Band
#define HIGH_LIMIT18 1816800 //Highest frequency at 18MHz Band
#define LOW_LIMIT21 2100000 //Lowest Frequency at 21MHz Band
#define HIGH_LIMIT21 2145000 //Highest frequency at 21MHz Band
#define LOW_LIMIT24 2489000 //Lowest Frequency at 24MHz Band
#define HIGH_LIMIT24 2499000 //Highest frequency at 24MHz Band
#define LOW_LIMIT28 2800000 //Lowest Frequency at 28MHz Band
#define HIGH_LIMIT28 2897000 //Highest frequency at 28MHz Band
#define LOW_LIMIT50 5000000 //Lowest Frequency at 14MHz Band
#define HIGH_LIMIT50 5400000 //Highest frequency at 14MHz Band
#define LOW_LIMIT144 14400000 //Lowest Frequency at 430MHz Band
#define HIGH_LIMIT144 14600000 //Highest frequency at 430MHz Band
#define LOW_LIMIT430 43000000 //Lowest Frequency at 430MHz Band
#define HIGH_LIMIT430 44000000 //Highest frequency at 430MHz Band

byte bar[8] = { //Character for signal bar
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
};

//Masks or BCDto BIN conversion
#define HighMask B11110000
#define LowMask B00001111

LiquidCrystal lcd(7,8,9,10,11,12,13);

// static
int incomingByte=0;
int i;
int k;
float potvalue; //return value of variable regisiter
int potentio_in; //AD data from the variable regisiter
int sensorPin = 2; // select the input pin for the potentiometer
byte Bcdvalue; //1 byte BCD value from FT-817
int Binvalue; //1 byte converted frequency data
int Up_Freq; //Upper frequency data
int Mega_Freq; //Mega heltz conponent
int Freq100k; //100kHz conponent
int Low_Freq; //Lower frequency data
long Freq=700000; //Frequency (8 digits)
byte ftype = 0; //Transmission type
char lcd_buff[7]; //LCD display buffer
int P[4]; //FT-817に送られるパラメータ群
int inc_freq; //frequency increment
int band; //band flag
int keyvalue;
int key_value=0;
int freqfactor =1; //dial factor for each band
int click =200; //dial wait time when near 0
int ptt; //toggle PTT
int signal; //signal strength

int msg_keypad[KEYPAD_NUM]
={1,2,3,4,5,6,7,8,9,11,0,12}; // 11:*,12:#
int keypad_val[KEYPAD_NUM]
={210,230,250,270,300,330,370,400,500,600,700,800};
int ftype_code[8] ={0,1,2,3,4,8,10,12}; //transmission type codes
char* ftype_name[]={"LSB","USB","CW ","CWR","AM ","FM ","DIG","PKT"};

int keypad_in; // Keypad input
int key = 0;

void setup(){
Serial.begin(4800);
lcd.begin(2,16);
for(int i=0;i<=6;i++){
pinMode(i,OUTPUT);
}
lcd.createChar(0, bar);//assign character 0
lcd.clear();
band=3; //default band = 7MHz
ftype=0; //default ftpe=LSB
lcd.setCursor(13,0);
lcd.print(ftype_name[ftype]);
Serial.print(ftype_code[ftype],BYTE); //Change transmission type
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(FTYPE,BYTE);
ptt = PTT_OFF; //PTT off
}

void loop(){
get_keypad();//read keypad
switch(key_value){
case 1: { band=band+1; // 1 -> band up
if(band > 12) band=0;
break;
}
case 2: { band=band-1; // 2 -> band down
if(band < 0) band=12;
break;
}
case 3: {ftype =ftype+1; // 3 -> transmission mode change
if (ftype > 7)ftype=0;
lcd.setCursor(13,0);
lcd.print(ftype_name[ftype]); //display Ftype
delay(100);
Serial.print(ftype_code[ftype],BYTE); //Change transmission type
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(FTYPE,BYTE);
break;
}
case KEY_SHARP: {
if(ptt==PTT_OFF)ptt=PTT_ON;else ptt=PTT_OFF; //toggle ptt
lcd.setCursor(0,1);
if(ptt == PTT_OFF)lcd.print(" ");else lcd.print("ON AIR ");
delay(100);
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(ptt,BYTE);
break;
}
}
if(ptt == PTT_OFF){
delay(200);
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(0,BYTE);
Serial.print(RECEIVE_STATUS,BYTE);//send receive status
lcd.setCursor(0,1);
lcd.print("SIG: ");
lcd.setCursor(4,1);
signal=Serial.read() & LowMask;// read signal strength
if (signal > 1)lcd.write(0); // plot bar graph
if (signal > 3)lcd.write(0);
if (signal > 5)lcd.write(0);
if (signal > 7)lcd.write(0);
if (signal > 10)lcd.write(0);
if (signal > 13)lcd.write(0);
}
//Calculate frequency incremet value depending on Pot value
get_pod();//read variable register
if(abs(potvalue)<100){delay(click);inc_freq=potvalue/SLOW_DOWN1;} //dial slow down nerar 0
else if(abs(potvalue)<150){ delay(50);inc_freq=potvalue/SLOW_DOWN2;} //dial slow down away from 0
else if(abs(potvalue)<250) {delay(5);inc_freq=potvalue;}
else inc_freq=potvalue;
if(band == 11 || band ==12){if( abs(potvalue) > 100)inc_freq=FM_LARGE*sgn(potvalue);//FM large increment
else inc_freq=FM_SMALL*sgn(potvalue);}//FM small increment
if(potvalue == 0)inc_freq=0;
Freq=Freq+inc_freq;

//Check band limit
switch(band){
case 0: { if(Freq<LOW_LIMIT1P8)Freq=LOW_LIMIT1P8; //1.8MHz
if(Freq>HIGH_LIMIT1P8)Freq=HIGH_LIMIT1P8;
freqfactor=1;click=200;
break;
}
case 1: { if(Freq<LOW_LIMIT3P5)Freq=LOW_LIMIT3P5; //3.5MHz
if(Freq>HIGH_LIMIT3P5)Freq=HIGH_LIMIT3P5;
click=200;
break;
}
case 2: { if(Freq<LOW_LIMIT3P8)Freq=LOW_LIMIT3P8; //3.8MHz
if(Freq>HIGH_LIMIT3P8)Freq=HIGH_LIMIT3P8;
click=200;
break;
}
case 3: { if(Freq<LOW_LIMIT7)Freq=LOW_LIMIT7; //7MHz
if(Freq>HIGH_LIMIT7)Freq=HIGH_LIMIT7;
click=200;
break;
}
case 4: { if(Freq<LOW_LIMIT10)Freq=LOW_LIMIT10; //10MHz
if(Freq>HIGH_LIMIT10)Freq=HIGH_LIMIT10;
click=200;
break;
}
case 5: { if(Freq<LOW_LIMIT14)Freq=LOW_LIMIT14; //14MHz
if(Freq>HIGH_LIMIT14)Freq=HIGH_LIMIT14;
click=200;
break;
}
case 6: { if(Freq<LOW_LIMIT18)Freq=LOW_LIMIT18; //18MHz
if(Freq>HIGH_LIMIT18)Freq=HIGH_LIMIT18;
click=200;
break;
}
case 7: { if(Freq<LOW_LIMIT21)Freq=LOW_LIMIT21; //21MHz
if(Freq>HIGH_LIMIT21)Freq=HIGH_LIMIT21;
click=200;
break;
}
case 8: { if(Freq<LOW_LIMIT24)Freq=LOW_LIMIT24; //24MHz
if(Freq>HIGH_LIMIT24)Freq=HIGH_LIMIT24;
click=200;
break;
}
case 9: { if(Freq<LOW_LIMIT28)Freq=LOW_LIMIT28; //28MHz
if(Freq>HIGH_LIMIT28)Freq=HIGH_LIMIT28;
click=200;
break;
}
case 10: { if(Freq<LOW_LIMIT50)Freq=LOW_LIMIT50; //50MHz
if(Freq>HIGH_LIMIT50)Freq=HIGH_LIMIT50;
click=200;
break;
}
case 11: { if(Freq<LOW_LIMIT144)Freq=LOW_LIMIT144; //144MHz
if(Freq>HIGH_LIMIT144)Freq=HIGH_LIMIT144;
click=280;
break;
}
case 12: { if(Freq<LOW_LIMIT430)Freq=LOW_LIMIT430; //430MHz
if(Freq>HIGH_LIMIT430)Freq=HIGH_LIMIT430;
click=280;
break;
}
}
bintobcd();
SendFreq(); //send frequency data to the radio

Up_Freq=0;
for(i=0;i<2;i++){
Bcdvalue = P[i];//read data from the radio
bcdtobin();//1 byte bcd to bin conversion
Up_Freq=Up_Freq*100+Binvalue;//Upper 4 digits
}
// Read lower frequency data
Low_Freq=0;
for(i=2;i<4;i++){//transform 4 byte bcd to bin
Bcdvalue =P[i];//read data from the radio
bcdtobin();//1 byte bcd to bin conversion
Low_Freq=Low_Freq*100+Binvalue;//Lower 4 digits
}
//Display MHz digits
lcd.setCursor(0,0);
Mega_Freq=Up_Freq/10;
sprintf(lcd_buff,"%3d.",Mega_Freq);
lcd.print(lcd_buff);
//Display 100kHz digit
Freq100k=Up_Freq-Mega_Freq*10;
lcd.print(Freq100k);
//Display Lower frequency components
sprintf(lcd_buff,"%04dMHz",Low_Freq);
lcd.print(lcd_buff);
delay(30); //wait for sending next command
}

// Get potentiometer value
int get_pod(){
// KEYPAD input
potentio_in = analogRead(POTENTIO);
// Serial.println(potentio_in);
potvalue=(potentio_in -POTVALUE_NUL);
// Serial.println(potvalue);
if (abs(potvalue) < POTVALUE_NUL_ZONE)potvalue=0; //ポテンショが中央付近なら数値をゼロに。
potvalue= FACTOR*potvalue; //係数をかける。
}
// Transforn 1 byte bcd(Bcdvalue) to bin(Binvalue)
int bcdtobin(){
int highvalue;
int lowvalue;
highvalue=(Bcdvalue & HighMask) >> 4; //Mask lower bists and shift 4 bits
lowvalue= Bcdvalue & LowMask; //Mask higher 4 bits
Binvalue=highvalue*10+lowvalue; //calculate binary value
}
//Transform Freq(long binary frequency) to BCD(P[1]-P[4])
int bintobcd(){
int bcd[8];
long Tfreq;
Tfreq=Freq;
//Generate 8 BCD digits
for(i=0;i<8;i++){
bcd[i]=Tfreq % 10; //modulo 10
Tfreq=Tfreq/10;//shift 1 digit
}
//Generate 4 sets of 2 BCD digits
for(i=0;i<4;i++){
P[i]=(bcd[7-i*2]<<4)+bcd[6-i*2];
}
}

int SendFreq(){
int k;
Serial.print(P[0],BYTE); //周波数の送出
Serial.print(P[1],BYTE);
Serial.print(P[2],BYTE);
Serial.print(P[3],BYTE);
Serial.print(SET_FREQ,BYTE);
}

int sgn(float val) {
if (val < 0) return -1;
if (val==0) return 0;
return 1;
}

//Read key pad
int get_keypad(){
// KEYPAD input
keypad_in = analogRead(KEYPAD_PIN);
{
if(keypad_in >= 190 && keypad_in <= 800){
key = get_KEYPAD_PIN(keypad_in);
key_value = msg_keypad[key]; //key_valueに押されたキーの数値を返す。
}
else key_value=NO_KEY; //キーが押されていなければNO_KEYを返す。
// 「msg_keypad[key]」で入力キーを取得(11,12は*,#に読替)
}
}

// Convert ADC value to key number (KEYPAD_PIN)
int get_KEYPAD_PIN(unsigned int input){
for(k = 0; k < KEYPAD_NUM; k++)
{
if(input < keypad_val[k]){return k;}
}
if(k >= KEYPAD_NUM){k = -1; return k;}
}