電波社

  • HOME
  • 会社概要
  • お問い合わせ
//*********************************************************************
// 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 *****************************