・通信技術の基本中の基本であるモールス符号を練習するための機械。
・ボタンを短く押すと「トン」、長く押すと「ツー」の音が発生して、LEDが点滅する。
・モールス符号は「トン」「ツー」の音の組み合わせで、アルファベットと数字を表す。液晶画面には、押したモールス符号に対応する文字が表示される。
・通信では、「電鍵」とよばれる高級なスイッチを使うが、あまりにも高価なものであるため、ゲーム用の押しボタンスイッチで代用した。
・ケースには100円均一ショップにあったコレクションボックスを利用した。
トランジスタ 2SC1815GR
カーボン抵抗器 10kΩ x 2個、1kΩ x 2個
セラミックコンデンサ 0.022uF (223) x 2個、0.22uF (224)
オーディオパワーアンプIC HOLTEK HT82V739
ICソケット 8PIN
積層セラミックコンデンサ 1uF x 2個、47uF
可変抵抗器(ボリウム) 10kΩ Bカーブ
スピーカー Φ50mm, 8Ω, 8W
PICマイコン PIC12F1822
ICソケット 8PIN
カーボン抵抗器 10kΩ x 2個
積層セラミックコンデンサ 1uF x 2個、0.1uF
押ボタンスイッチ(電鍵代用)
I2C接続小型8文字x2行液晶ディスプレイ AQM0802A-RN-GBW
バッテリースナップ
電池ボックス 単3×3本用(ニッケル水素電池使用)
トグルスイッチ 基板・パネル両用
ユニバーサル基板 片面ガラス・ユニバーサル基板(ブレッドボード配線パターンタイプ)[AZ0526]
ピンヘッダ、ボックスヘッダ
スペーサー、ネジ類
ケース類
I2C接続液晶の制御関数は、【きむ茶工房ガレージハウス】(http://www.geocities.jp/zattouka/GarageHouse/index.htm)のコードを"skI2Clib.h", "skI2Clib.c", "skI2CLCDlib.h", "skI2CLCDlib.c"を利用させていただいた。
(XC8コンパイラ用)
/* * File:   cw-asc-i2c-lcd8x2-12f1822.c * Author: kaimu * * Created on 2015/06/28, 9:08 *//* * Push switch : PIN 4 (RA3) * Tone generator On/Off : PIN 3 (RA4) : 0-ON, 1-off * SCL : PIN 6 (RA1) * SDA : PIN 5 (RA2) * */#include <xc.h>#include <stdlib.h>#include "skI2Clib.h"#include "skI2CLCDlib.h"/* *  I/O port name */#define isSwitchOff() (RA3)#define isSwitchOn() (!RA3)#define toneOn()    (RA4 = 0)#define toneOff()    (RA4 = 1)// Configuration 1#pragma config FOSC     = INTOSC   // Internal Clock#pragma config WDTE     = OFF      // NO Watchdog timer#pragma config PWRTE    = ON       // Program start at Power on after 64ms#pragma config MCLRE    = OFF      // No Ext Reset, Enable RA3 input pin#pragma config CP       = OFF      // No Code protect#pragma config CPD      = OFF      // No Data Protect#pragma config BOREN    = ON       // Brown out enable#pragma config CLKOUTEN = OFF      // CLKOUT as RA4#pragma config IESO     = OFF      // No Internal External clock#pragma config FCMEN    = OFF      // No FCM// Configuration 2#pragma config WRT    = OFF        // No Write Protect#pragma config PLLEN  = OFF        // No PLL#pragma config STVREN = ON         // Reset on Stack over / under flow#pragma config BORV   = HI         // Watch Voltage drop (2.5V = HI)#pragma config LVP    = OFF        // No Low Voltage Programming/* *  Interrupt */volatile int TimerCounter; //void interrupt InterFunction( void ){    if (TMR0IF == 1) { // Timer 0 interrupt        TMR0 = 0 ; // initialize TIMER0          TimerCounter++ ;        // update Timer Counter          TMR0IF = 0 ;            // reser TIMER0 interrupt flag    }    // I2C Interrupt    InterI2C() ;}void msgReady(void){     LCD_SetCursor(0,0) ;        // set locatin ( 1st column, 1st row. )     LCD_Puts(">") ;}void msgOn(void){     LCD_SetCursor(0,0) ;        // set locatin ( 1st column, 1st row. )     LCD_Puts("ON.") ;}void msgOff(void){     LCD_SetCursor(0,0) ;        // set locatin ( 1st column, 1st row. )     LCD_Puts("OFF") ;}void msgClear(int row)/** * clear LCD at row * @param row : row cleard  (0 or 1) */{     LCD_SetCursor(0, row) ;        // set locatin ( 1st column, row row. )     LCD_Puts("        "); // clear line}void msgNum(int i)/* * Output number on LCD * * @param i : number */{    char buf[9] = {0};    itoa(buf, i, 10);    LCD_SetCursor(0,1) ;        // set locatin ( 1st column, 2nd row. )    LCD_Puts(buf);}void putDotBar(unsigned short mcode){    int col;    int i;    unsigned short m;    char dotbar[9];    msgClear(1); // message clear ( 2nd row )    for (col = 0, i = 0; i < 8 ; i++, mcode >>= 2 ) {        m = mcode & 0b11;        switch(m) {            case 0b01 :                dotbar[7 - i] = '.';                break;            case 0b11 :                dotbar[7 - i] = '-';                break;            default :                dotbar[7 - i] = ' ';        }    }    dotbar[8] = '\0';    LCD_SetCursor(0, 1);    LCD_Puts(dotbar);}void putAlNum(unsigned short mcode)/** * put Alphabet & Number on LCD * @param mcode : morse code   '.' 0b01,  '-' 0b11 */{    static int c = 0; // column of LCD    if (c > 7) { LCD_Clear(); c = 0;}        LCD_SetCursor(c, 0);    switch (mcode) {            case 0b000000000111 :            LCD_Putc('A');            break;        case 0b0000000011010101 :            LCD_Putc('B');            break;        case 0b0000000011011101 :            LCD_Putc('C');            break;        case 0b0000000000110101 :            LCD_Putc('D');            break;        case 0b0000000000000001 :            LCD_Putc('E');            break;        case 0b0000000001011101 :            LCD_Putc('F');            break;        case 0b0000000000111101 :            LCD_Putc('G');            break;        case 0b0000000001010101 :            LCD_Putc('H');            break;        case 0b0000000000000101 :            LCD_Putc('I');            break;        case 0b0000000001111111 :            LCD_Putc('J');            break;        case 0b0000000000110111 :            LCD_Putc('K');            break;        case 0b0000000001110101 :            LCD_Putc('L');            break;        case 0b0000000000001111 :            LCD_Putc('M');            break;        case 0b0000000000001101 :            LCD_Putc('N');            break;        case 0b0000000000111111 :            LCD_Putc('O');            break;        case 0b0000000001111101 :            LCD_Putc('P');            break;        case 0b0000000011110111 :            LCD_Putc('Q');            break;        case 0b0000000000011101 :            LCD_Putc('R');            break;        case 0b0000000000010101 :            LCD_Putc('S');            break;        case 0b0000000000000011 :            LCD_Putc('T');            break;        case 0b0000000000010111 :            LCD_Putc('U');            break;        case 0b0000000001010111 :            LCD_Putc('V');            break;        case 0b0000000000011111 :            LCD_Putc('W');            break;        case 0b0000000011010111 :            LCD_Putc('X');            break;        case 0b0000000011011111 :            LCD_Putc('Y');            break;        case 0b0000000011110101 :            LCD_Putc('Z');            break;        case 0b0000001111111111 :            LCD_Putc('0');            break;        case 0b0000000111111111:            LCD_Putc('1');            break;        case 0b0000000101111111 :            LCD_Putc('2');            break;        case 0b0000000101011111 :            LCD_Putc('3');            break;        case 0b0000000101010111 :            LCD_Putc('4');            break;        case 0b0000000101010101 :            LCD_Putc('5');            break;        case 0b0000001101010101 :            LCD_Putc('6');            break;        case 0b0000001111010101 :            LCD_Putc('7');            break;        case 0b0000001111110101 :            LCD_Putc('8');            break;        case 0b0000001111111101 :            LCD_Putc('9');            break;        default :            LCD_Putc('?');    }    c++; // next column of LCD}void initIO(void){     OSCCON     = 0b01110010 ;   // Internal clock 8MHz     OPTION_REG = 0b00000000 ;   // Weak Pull up Resistor ON     ANSELA     = 0b00000000 ;   // NO Analog PORT     TRISA      = 0b00001110 ;   // Input : RA1, RA2, RA3    Output: others     WPUA       = 0b00000110 ;   // Weak pullup : RA1, RA2     PORTA      = 0b00000000 ;   // Initialize PORTA}void initTimer0(void){     OPTION_REG = 0b00000110 ; // TIMER0 enable, internal clock 、prescaler 1:128     TMR0   = 0 ;               // initialize TIMER0 Counter     TMR0IF = 0 ;               // reset TIMER0 flag     TimerCounter  = 0 ;        // reset Timer Counter     TMR0IE = 1 ;               // Enable Timer1 Interrupt     GIE    = 1 ;               // Enable Interrupt}void outReadySignal(void){    toneOn();   TimerCounter = 0;   while (TimerCounter < 50);    toneOff();  TimerCounter = 0;   while (TimerCounter < 10);    toneOn();   TimerCounter = 0;   while (TimerCounter < 10);    toneOff();  TimerCounter = 0;   while (TimerCounter < 50);}/* *  main function */void main(){    unsigned short mcode; // Morse code 01 = . , 11 = -    int flag; // flag = 1 ... code reading    int i; // index of morse code bit                // Initialize I/O ports    initIO();    // Initialize TIMER0    initTimer0();     // Initialize I2C ( 100kHz )     InitI2C_Master(0) ;     toneOff();     // Initialize LCD module     // Arguments : ICON OFF, Contrast(0-63), VDD=3,3V, LCD 8 characters     LCD_Init(LCD_NOT_ICON,16,LCD_VDD3V,8) ;     msgReady(); // output "RDY"     outReadySignal(); // Start up signal     while(1) {         if (isSwitchOn()) { // when switch is ON             for (flag = 1, mcode = 0, i = 0;                     flag == 1 && i < 8; i++) {                 TimerCounter = 0;                 toneOn();                 while (isSwitchOn());                 if ( TimerCounter < 3) {                     i --; // Too short signal is ignored as chattering noise                 } else if ( TimerCounter < 10 ) {                     mcode <<= 2;                     mcode |= (0b01); // .                 } else {                     mcode <<= 2;                     mcode |= (0b11); // -                 }                 toneOff();                 TimerCounter = 0;                 while (isSwitchOff()) {                     if (TimerCounter > 42 ) {                         flag = -1; // A Word end                         break;                     } else if (TimerCounter > 18) {                         flag = 0; // A character end                         break;                     }                 }             }             putAlNum(mcode);             putDotBar(mcode);         }     }}