'{$STAMP BS2} ' Date: April 19, 2003 ' File: PL-DDS-ver3.bs2 ' Gary S. Kath ' N2OT ' ' This program will send a Morse Code Character given an ASCII character. The program 'stores a special 8-bit code into the BasicStamp EEPROM for each of the characters. 'The special 8-bit code contains the Morse code for the character in the 5 MSBs 'and stores the number of dots/dashes in the Morse code for the remaining 3 LSBs. 'Characters with more than 5 dots/dashes are handled differently. ' The special codes are arranged in memory sequencially idential to the ASCII character set. 'When a ASCII character is passed to the Send routine it first subtracts 40 from the decimal 'equilvalent of the ASCII character. This value is then a pointer address to the special code 'stored in the EEPROM. The special character is retrieved from EEPROM and the Morse Code 'bits and number of dots/dashes are stripped off. ' For example to send the Morse Code character "C": 'the decimal value of the ASCII code "C" is 67. 67-40 = 27. Retrieve the 27nd 'special character in EEPROM at address 27: %01010100. The 3 LSBs: %100 = 4 indicate 'there will be 4 dots/dashes. The 4 MSBs: %0101 is the Morse Code where a logic '1 = dot and logic 0 = dash. ' 'Once the Morse Code is retrieved the software checks each bit and then sends out the 'Morse Code. ' 'NOTE: Characters must be in capital letters !!!!!!!!! ' '*********************************************************************************************** 'Declare variables & contants DEFINE OSC 4 'set osc freq to 4 MHz include "modedefs.bas" SideTonePitch con 2500 'This constant set the pitch of the side tone DitDuration con 37 'The duration of the dit is milliseconds DahDuration con DitDuration * 3 'The duration of the dah in milliseconds SidetonePin con 0 'Sidetone connected to this pin LEDPin con 4 'LED connected to this pin IDTimeOut con 9 'number of minutes to wait before sendin ID reminder ASCII_Char var byte 'This is the ASCII Character to be sent x var byte 'General purpose loop variable y var word 'General purpose variable Code var byte NoOfDotsDashes var byte 'Variable containing number of dots/dashes in Morse Code MorseCode var byte 'The Morse Code of the char where 1=dit, 0=dah DitOrDah var byte CodeStartEEAdr var word 'Address pointer to Morse Code in EEPROM StrAddr var word char var byte result var word 'Temperature sensor result TimeOutIncrement var byte 'Keeps track of number of seconds mic PTT is pressed ' PLToneFreq var word 'PL Tone frequency in Hertz PLToneAdr var byte 'Adr of tone frequency in memory Junk var word IDTimeOutCounter var word 'Variable keeping track of number of minutes before ID counter var word DataP con 2 Clock con 1 Latch con 3 '------------------------------------------------------------------------------------ 'The following data values are stored in EEPROM. Each byte contains 'the Morse Code and the number of dots & dashes of the ASCII character 'shown in the comments. The right 3-bits of the byte tell how many 'dots & dashes in the Morse Code. The left 5-bits is the Morse Code 'where 0=dash and 1=dot. For example: ' Y = 01000100 'There are a few Morse Code characters that have more than 5 dots & 'dashes (i.e. ?, .). These are handled by "if" statements in the SendChar 'subroutine where if the right 3-bits = 110 then a dit is sent at the '6th position and if the right 3-bits = 111 then a dah is sent at the '6th poistion data %01001111, %01001111, %00000000, %00000000, %00110111 '()* + , ', data %01110101, %10101111, %01101101, %00000101, %10000101, %11000101 '-./012 data %11100101, %11110101, %11111101, %01111101, %00111101, %00011101 '345678 data %00001101, %00011110, %01010110, %00000000, %00000000, %00000000 '9:;<=> data %11001110, %00000000 '?@ data %10000010, %01110100, %01010100, %01100011, %10000001, %11010100 'ABCDEF data %00100011, %11110100, %11000010, %10000100, %01000011, %10110100 'GHIJKL data %00000010, %01000010, %00000011, %10010100, %00100100, %10100011 'MNOPQR data %11100011, %00000001, %11000011, %11100100, %10000011, %01100100 'STUVWX data %01000100, %00110100 'YZ DefaultPLToneEEAdr data %00000000 'Power up PL Tone '-------------------------------------------------------------------------------------- ' 'Place your messages here F1 data "N2OT%" F2 data "PL %" '--------------------------------------------------------------------------------------- '--------------------------------------------------------------------------------------- Start: IDTimeOutCounter = 0 junk = 0 ' Send my call sign StrAddr = F1 gosub SendMessageString pause 1000 'Get default PL Tone READ DefaultPLToneEEAdr, PLToneAdr gosub GetTone 'Turn on default PL Tone counter = (PLToneFreq * 200)/190 'calculate divider for ML2036 chip Shiftout DataP,Clock,lsbfirst,[counter\16] 'program ML2036 pulsout Latch,1 'Send default PL Tone via CW message StrAddr = F2 gosub SendMessageString gosub SendDigits pause 400 junk = 0 Main: 'Check if port 1 is logic low. If so change the PL Tone if PORTB.7 = 0 then ChangeTone if PORTB.6 = 0 then ChangeTone if PORTA.1 = 0 then MainContu2 TimeOutIncrement= 0 MainContu1: pause 1000 IDTimeOutCounter = IDTimeOutCounter + 1 if IDTimeOutCounter/60 >= IDTimeOut then SendIDReminder goto Main MainContu2: TimeOutIncrement = TimeOutIncrement + 1 if TimeOutIncrement >= 60 then SendTimeOutReminder goto MainContu1 '*************************** Change Tone ****************************** 'Increment to the next tone value. When done save PLToneAdr in EEPROM '********************************************************************** ChangeTone: pause 500 gosub GetTone gosub SendDigits pause 600 if PORTB.7 = 0 then IncUP if PORTB.6 = 0 then IncDWN goto SaveToneAdr IncUP: pause 10 if PLToneAdr > 37 then ResetToMax PLToneAdr = PLToneAdr + 1 goto ChangeTone ResetToZero: PLToneAdr = 0 goto ChangeTone IncDWN: pause 10 if PLToneAdr < 1 then ResetToZero PLToneAdr = PLToneAdr - 1 goto ChangeTone ResetToMax: PLToneAdr = 38 goto ChangeTone SaveToneAdr: Junk = PLToneAdr WRITE DefaultPLToneEEAdr, Junk pause 200 counter = (PLToneFreq * 200)/190 'calculate divider for ML2036 chip Shiftout DataP,Clock,lsbfirst,[counter\16] 'program ML2036 pulsout Latch,1 goto Start '******************************************************************************* ' Send ID Reminder after IDTimeOutCounter number of minutes SendIDReminder: StrAddr = F1 gosub SendMessageString IDTimeOutCounter = 0 goto Main SendTimeOutReminder: junk = junk + 1 ASCII_Char = junk + 48 gosub SendChar TimeOutIncrement = 0 goto Main '************************** GetTone ********************************************* ' 'This subroutine will get PL Tone frequency give the PLToneAdr. 'The tone is return in the variable PLToneFreq ' '******************************************************************************** GetTone: If PLToneAdr > 12 then GetToneContu2 Junk = PLToneAdr LOOKUP Junk, [0, 67, 72, 74, 77, 80, 83, 85, 89, 92, 95, 97, 100], PLToneFreq goto GetToneDone GetToneContu2: If PLToneAdr > 25 then GetToneContu3 Junk = PLToneAdr - 13 LOOKUP Junk, [104, 107, 111, 115, 119, 123, 127, 132, 137, 141, 146, 151, 157], PLToneFreq goto GetToneDone GetToneContu3: Junk = PLToneAdr - 26 LOOKUP Junk, [162, 168, 174, 180, 186, 193, 204, 211, 218, 226, 234, 242, 250], PLToneFreq GetToneDone: return '********************** Send Message String ************************** ' 'This routine will send a message string of ASCII characters in Morse Code. 'Prior to use the user must specify a pointer to the message string using 'the variable StrAddr. The routine continues to send the characters until 'a "%" is reached in the message string. ' '********************************************************************* SendMessageString: READ StrAddr, ASCII_Char 'Retrieve a character if ASCII_Char = "%" then SMScont1 'Check for if last character "%" gosub SendChar 'Send the Morse Code StrAddr = StrAddr + 1 'Advance to next character in string goto SendMessageString 'Continue until done SMScont1: return '********************** Send Digits ****************** ' 'This routine will send the Morse Code PL Tone digits one by one. 'Leading zero is removed. ' '********************************************************************* SendDigits: result = PLToneFreq/100 if result = 0 then SendDigitsContu1 ASCII_Char = result + 48 gosub SendChar SendDigitsContu1: result = (PLToneFreq//100)/10 ASCII_Char = result + 48 gosub SendChar result = (PLToneFreq//100)//10 ASCII_Char = result + 48 gosub SendChar return '********************** SendChar *********************************** ' 'This subroutine will send the Morse code of the ASCII character 'in the variable x. The routine handles . & ? in a special manner 'because the number of dots & dashes exceeds 5. Since the 'Morse Code characters are stored in the same order as ASCII characters, '40 is subtracted from the ASCII character and this provides a 'pointer to the data in EEPROM of the Morse Code equivalent. 'The routine then retrieves this value strips off the Morse Code 'and the number of dots & dashes and then one by one shifts 'the bits to the left. Each time it checks if the bit is logic 1 'which corresponds to a dit and logic 0 which corresponds to a dah. '********************************************************************* SendChar: if ASCII_Char = " " then Space 'Pause if space CodeStartEEAdr = ASCII_Char - 40 'Subtracting 40 from ASCII character results in 'a pointer to the equivalent Morse code stored in EEPROM READ CodeStartEEAdr,Code 'Get Morse Code from EEPROM NoOfDotsDashes = Code & %00000111 'Strip off right 3-bits which equals number of dots & dashes MorseCode = Code & %11111000 'Strip off left 5-bits which equals the Morse Code StartSendChar: if NoOfDotsDashes = 0 then EndSendChar 'Check for invalid character if NoOfDotsDashes = 6 then SpecialCharDit 'Char with 6 dots/dashes and with dot at end if NoOfDotsDashes = 7 then SpecialCharDah 'Char with 6 dots/dashes and with dash at end Begin: for x = 1 to NoOfDotsDashes 'Check left bit; if 1 send dit if 0 send dah DitOrDah = MorseCode & %10000000 If DitOrDah = 0 then contu0 gosub SendDit goto contu1 contu0: gosub SendDah contu1: pause ditDuration 'Pause between dot/dashes should be 1 dit duration MorseCode = MorseCode << 1 'Move bits left by 1 position and repeat next pause ditDuration * 3 'Pause between characters should be 3 dit durations goto EndSendChar SpecialCharDah: MorseCode = MorseCode & %11111000 NoOfDotsDashes = 6 goto Begin SpecialCharDit: MorseCode = MorseCode | %00000100 NoOfDotsDashes = 6 goto Begin Space: pause ditduration * 7 'Pause between words should be 7 bit durations EndSendChar: return '********************** SendDit *********************************** 'This routine will send a dit out pin LEDPin of duration DitDuration. It also 'with send a tone of SideTonePitch to an AC coupled speaker connected to SidetonePin '******************************************************************* SendDit: low LEDPin FREQOUT SidetonePin,DitDuration,SideTonePitch high LEDPin return '********************** SendDah *********************************** 'This routine will send a dah out pin LEDPin of duration DahDuration. It also 'with send a tone of SideTonePitch to an AC coupled speaker connected to SidetonePin '******************************************************************* SendDah: low LEDPin FREQOUT SidetonePin,DahDuration,SideTonePitch high LEDPin return end