//*********************************************************************
// Program name : morse_trainer.c
// Start date : 2019.08.01
// Author : Kato
// Compile : cc -o morse_trainer morse_trainer.c -l wiringPi
// Excute : sudo ./morse_trainer
//*********************************************************************
#include <wiringPi.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <softTone.h>
#define tone 1 //software toneの時は0とする
#define speed_up_sw 2
#define speed_down_sw 3
#define continuous_sw 4
#define mode_sw 6
#define busy_led 13
#define one_code_sw 17
#define speaker 19
#define shut_down_sw 26
#define stop_sw 27
#define freq 800
int speed_para = 100 ;
int count = 0 ;
char check[51] ;
//*********************************************************************
// 出力済みデータチェックテーブルクリヤー
//*********************************************************************
void table_clear(){
int i;
for(i=0; i<51; i++)
check[i]= 0 ;
}
//*********************************************************************
// 引数で渡されたデータの長さの信号を出力
// toneが1の時はハードウェア発振音、0の時はソフトウェア発振音
//*********************************************************************
void sig_out(int para){
int length ;
length=speed_para * para;
if(tone){ // ハードウェア発振音を使用
digitalWrite(speaker,1) ;
delay(length) ;
digitalWrite(speaker,0) ;
}
else{ // ソフトウェア発振音を使用
softToneWrite(speaker,freq) ;
delay(length) ;
softToneWrite(speaker,0) ;
}
delay(speed_para) ; //1ドット分のスペース出力
}
//*********************************************************************
// 引数で示されるデータをモールス符号へ変換し、sig_outをコール
//*********************************************************************
void morse_out(char dt){
char morse_code[44] = // 欧文モールス符号配列
{0xb4,0xb6,0xce,0x86,0x56,0x94,0xfc,0x7c,0x3c,
0x1c,0x0c,0x04,0x84,0xc4,0xe4,0xf4,0x8c,0x32,0x60,0x88,
0xa8,0x90,0x40,0x28,0xd0,0x08,0x20,0x78,0xb0,0x48,0xe0,
0xa0,0xf0,0x68,0xd8,0x50,0x10,0xc0,0x30,0x18,0x70,0x98,
0xb8,0xc8} ;
char morse_code_wabun[49] = // 和文モールス符号配列
{0xdc,0x40,0x30,0xbc,0x44,0x48,0xa2,0x18,
0xb8,0xf8,0xac,0xd4,0xec,0x74,0xe8,0xa0,0x28,0x68,0x5c,
0x24,0x50,0xa8,0x08,0xd8,0x38,0x88,0xcc,0xc8,0x40,0x90,
0x98,0x2c,0xc0,0x8c,0x94,0x70,0x9c,0xe0,0x10,0xd0,0xb4,
0xf0,0x58,0xb0,0x78,0x54,0x34,0x20,0x6c} ;
char wk ;
if(digitalRead(mode_sw) == 0) //mode SWオン和文モールス符号を使用
wk = morse_code_wabun[dt] ;
else
wk = morse_code[dt] ; //欧文モールス符号を使用
while(wk != 0x80){ //モールス符号が0x80になるまで繰り返す
if((wk & 0x80) == 0) //上位ビットが1なからばドットを出力
sig_out(1) ; //ドット出力
else
sig_out(3) ; //ダッシュ出力
wk = wk << 1 ;
if(digitalRead(speed_up_sw) == 0) //speed up SWが押された
if(speed_para > 10)
speed_para -= 1 ;
}
if(digitalRead(speed_down_sw) == 0){ //speed down SWが押された
if(speed_para<200)
speed_para +=1 ;
}
}
delay(speed_para * 2) ; //文字間スペース 2ドット分の時間をおく
}
//*********************************************************************
// ランダムによる連続したモールス符号を出力
//*********************************************************************
void rand_continuous(){
char data ;
char num ;
count =0 ;
digitalWrite(busy_led,1) ; //busy LEDを点灯
if(digitalRead(mode_sw) == 0)
num = 49 ; //和文の文字数を設定
else
num = 44 ; //欧文の文字数を設定
while(1){
data=rand() % num ; //numに示される範囲の乱数を設定
if(check[data] == 0){ //既に出力済みがチェック
check[data] = 1 ;
morse_out(data) ;
count ++ ;
if(count == num){ //全て出力済みならばテーブルクリヤー
table_clear() ;
break ;
}
}
if(digitalRead(stop_sw) == 0 || digitalRead(shut_down_sw) == 0)
break ; //stop SWまたはshutdown SW押されたループを抜ける
}
digitalWrite(busy_led,0) ; //busy LEDを消灯
}
//*********************************************************************
// 乱数により1文字のモールス符号を出力
//*********************************************************************
void morse_one_code(){
char data ;
char num ;
int i ;
digitalWrite(busy_led,1) ; //busy LEDを点灯
if(digitalRead(mode_sw) == 0) //mode SWオンならば和文モールス符号
num = 49 ; //和文の文字数を設定
else
num = 44 ; //欧文の文字数を設定
while(1){
data=rand() % num ; //numに示される範囲の乱数を設定
if(check[data] == 0){ //既に出力済みがチェック
check[data] = 1 ;
morse_out(data) ;
count ++ ;
if(count == num){ //全て出力済みならばテーブルクリヤー
table_clear() ;
break ;
}
}
}
digitalWrite(busy_led,0) ; //busy LEDを消灯
}
//*********************************************************************
// GPIO、時刻の初期化処理
//*********************************************************************
int init(){
if(wiringPiSetupGpio() == -1) //wiringPiのセットアップ
return(-1) ; //エラーの時は戻る
pinMode(speaker,OUTPUT) ; //使用するGPIOを出力または入力に設定
pinMode(continuous_sw,INPUT) ;
pinMode(one_code_sw,INPUT) ;
pinMode(speed_up_sw,INPUT) ;
pinMode(speed_down_sw,INPUT) ;
pinMode(stop_sw,INPUT) ;
pinMode(mode_sw,INPUT) ;
pinMode(shut_down_sw,INPUT) ;
pinMode(busy_led,OUTPUT) ;
pullUpDnControl(continuous_sw,PUD_UP) ; //入力のGPIOをプルアップする
pullUpDnControl(one_code_sw,PUD_UP) ;
pullUpDnControl(speed_up_sw,PUD_UP) ;
pullUpDnControl(speed_down_sw,PUD_UP) ;
pullUpDnControl(stop_sw,PUD_UP) ;
pullUpDnControl(mode_sw,PUD_UP) ;
pullUpDnControl(shut_down_sw,PUD_UP) ;
time_t timer ; //時刻情報を得る
struct tm *t_st ;
time(&timer) ;
t_st = localtime(&timer) ;
srand(t_st->tm_sec) ; //時刻の秒で乱数を初期化
softToneCreate(speaker) ; //softToneの初期化
return(1) ;
}
//*********************************************************************
// メイン処理
// 初期化処理をコール LED5回点滅、スイッチが押されるのを監視、shutdown
// スイッチが3秒以上押されたらshutdownする、3秒以下の時はOSへ戻る
//*********************************************************************
int main(){
int i ;
if(init() == -1) //初期化処理をコール
return(-1) ; //初期化処理でエラー
table_clear() ; //出力済みチェックテーブルクリヤー
for(i=0; i<=4; i++){ //LEDを5回点滅
digitalWrite(busy_led,1) ;
delay(200) ;
digitalWrite(busy_led,0) ;
delay(200) ;
}
count = 0 ;
while(1){
if(digitalRead(continuous_sw) == 0){ //連続出力SWをチェック
delay(100) ; //100ms時間をおいて再度SWチの状態をチェック
if(digitalRead(continuous_sw) == 0){
table_clear() ; //連続出力SW押されたテーブルクリヤー
rand_continuous() ; //連続出力をコール
}
}
if(digitalRead(one_code_sw) == 0){ //1文字出力SWが押されたか
delay(100) ; //100ms時間をおいて再度SWの状態をチェック
if(digitalRead(one_code_sw) == 0)
morse_one_code() ; //1文字出力をコール
}
if(digitalRead(shut_down_sw) == 0) //shutdown SW押されたか
break ;
}
count = 0 ;
while(digitalRead(shut_down_sw) == 0){ //shutdown SWが押されたか
delay(100) ; //100ms待つ
count++ ;
}
if(count >= 30) //3秒以上押されたいたらshutdowmコマンドを発行する
system("sudo shutdown -h now") ; //shutdown コマンド
else
return(1) ; //3秒以下の時はOSに戻る
}
//************************** End of Program *****************************