・通信技術の基本中の基本であるモールス符号を練習するための機械。
・ボタンを短く押すと「トン」、長く押すと「ツー」の音が発生して、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); } }}