I need some help condensing a program. This is a program spelling out 42 PSI in morse code. I programmed it the long way. I am sure there are tricks and smarter things that can be done to shorten it. I am about 7 lines short of being able to fit it in a prop-1, and of course I am on site installing it right now. Any help would be appreciated.
' =========================================================================
'
' File...... MorseCodeMessage.BS1
' Purpose...
' Author....
' E-mail....
'
' Started...
' Updated...
'
' {$STAMP BS1}
' {$PBASIC 1.0}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
SYMBOL Blink = PIN0
' -----[ Constants ]-------------------------------------------------------
SYMBOL IsOn = 1 ' for active-high in/out
SYMBOL IsOff = 0
SYMBOL Letter = 3000
SYMBOL Word = 7000
SYMBOL Dot = 1000
SYMBOL Dash = 3000
' -----[ Variables ]-------------------------------------------------------
' -----[ Initialization ]--------------------------------------------------
Reset:
PINS = %00000000 ' clear all outputs
DIRS = %00000001 ' make P0 output
' -----[ Program Code ]----------------------------------------------------
Main:
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
Blink = IsOn
PAUSE Letter
Blink = IsOff
PAUSE Letter
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
Blink = IsOn
PAUSE Word
Blink = IsOff
PAUSE Word
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Letter
Blink = IsOff
PAUSE Letter
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Letter
Blink = IsOff
PAUSE Letter
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Word
Blink = IsOff
PAUSE Word
GOTO Reset
' -----[ Subroutines ]-----------------------------------------------------
' -------------------------------------------------------------------------
' -----[ User Data ]-------------------------------------------------------
Could probably get this even smaller but this will work.
' {$STAMP BS1}
' {$PBASIC 1.0}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
SYMBOL Blink = PIN0
' -----[ Constants ]-------------------------------------------------------
SYMBOL IsOn = 1 ' for active-high in/out
SYMBOL IsOff = 0
SYMBOL Letter = 3000
SYMBOL Word = 7000
SYMBOL Dot = 1000
SYMBOL Dash = 3000
' -----[ Variables ]-------------------------------------------------------
SYMBOL counter = B2
' -----[ Initialization ]--------------------------------------------------
Reset:
PINS = %00000000 ' clear all outputs
DIRS = %00000001 ' make P0 output
' -----[ Program Code ]----------------------------------------------------
Main:
FOR counter = 1 TO 4
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
NEXT
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
Blink = IsOn
PAUSE Letter
Blink = IsOff
PAUSE Letter
FOR counter = 1 TO 2
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
NEXT
FOR counter = 1 TO 3
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
NEXT
Blink = IsOn
PAUSE Word
Blink = IsOff
PAUSE Word
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
FOR counter = 1 TO 2
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
NEXT
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
Blink = IsOn
PAUSE Letter
Blink = IsOff
PAUSE Letter
FOR counter = 1 TO 3
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
NEXT
Blink = IsOn
PAUSE Letter
Blink = IsOff
PAUSE Letter
FOR counter = 1 TO 2
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
NEXT
Blink = IsOn
PAUSE Word
Blink = IsOff
PAUSE Word
GOTO Reset
Here's one that's smaller yet.
' {$STAMP BS1}
' {$PBASIC 1.0}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
SYMBOL Blink = PIN0
' -----[ Constants ]-------------------------------------------------------
SYMBOL IsOn = 1 ' for active-high in/out
SYMBOL IsOff = 0
SYMBOL Letter = 3000
SYMBOL Word = 7000
SYMBOL Dot = 1000
SYMBOL Dash = 3000
' -----[ Variables ]-------------------------------------------------------
SYMBOL counter = B2
' -----[ Initialization ]--------------------------------------------------
Reset:
PINS = %00000000 ' clear all outputs
DIRS = %00000001 ' make P0 output
' -----[ Program Code ]----------------------------------------------------
Main:
FOR counter = 1 TO 4
GOSUB Do_Dot
NEXT
GOSUB Do_Dash
GOSUB Do_Letter
FOR counter = 1 TO 2
GOSUB Do_Dot
NEXT
FOR counter = 1 TO 3
GOSUB Do_Dash
NEXT
GOSUB Do_Word
GOSUB Do_Dot
FOR counter = 1 TO 2
GOSUB Do_Dash
NEXT
GOSUB Do_Dot
GOSUB Do_Letter
FOR counter = 1 TO 3
GOSUB Do_Dot
NEXT
GOSUB Do_Letter
FOR counter = 1 TO 2
GOSUB Do_Dot
NEXT
GOSUB Do_Word
GOTO Reset
Do_Dot:
Blink = IsOn
PAUSE Dot
Blink = IsOff
PAUSE Dot
RETURN
Do_Dash:
Blink = IsOn
PAUSE Dash
Blink = IsOff
PAUSE Dash
RETURN
Do_Letter:
Blink = IsOn
PAUSE Letter
Blink = IsOff
PAUSE Letter
RETURN
Do_Word:
Blink = IsOn
PAUSE Word
Blink = IsOff
PAUSE Word
RETURN
Your first one worked great. I really should have thought of that, but it's dark, and I am inside a haunt working, so my brain isn't functioning 100% with all the noise. Thanks alot!
Your welcome. I'm sure Jon has a way to make this fit on a post stamp though!
Lucky for you, my friend Scott Edwards wrote a neat App Note on sending Morse Code with the BS1 processor. I have updated that code (still uses his clever encoding scheme) to make sending Morse messages easy. The problem with one-offs like you've done above is that changing the message leads to a lot of work. Not so with Scott's/my version.
BTW... this only uses 39% of the memory.
' =========================================================================
'
' File...... morse_code.bs1
' Purpose... Output Morse Code message
' Author.... Scott Edwards (updated/reformatted by Jon McPhalen)
' E-mail....
' Started...
' Updated... 26 SEP 2015
'
' {$STAMP BS1}
' {$PBASIC 1.0}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
SYMBOL Blinker = PIN0
' -----[ Constants ]-------------------------------------------------------
SYMBOL YES = 1
SYMBOL NO = 0
SYMBOL IS_ON = 1 ' active-high I/O
SYMBOL IS_OFF = 0
SYMBOL DIT_TM = 250
SYMBOL DAH_TM = 750 ' 3x dit timing
SYMBOL WRD_TM = 1750 ' 7x dit timing
' -----[ Morse Code Table ]------------------------------------------------
' Encoding:
' -- upper five bits = code (0 = dit, 1 = dah)
' -- lower three bits hold # of elements
' * 6-element chars ending in dit use count 6
' * 6-element chars ending in dah use count 7
SYMBOL _A = %01000010 ' dit dah
SYMBOL _B = %10000100 ' dah dit dit dit
SYMBOL _C = %10100100 ' dah dit dah dit
SYMBOL _D = %10000011 ' dah dit dit
SYMBOL _E = %00000001 ' dit
SYMBOL _F = %00100100 ' dit dit dah dit
SYMBOL _G = %11000011 ' dah dah dit
SYMBOL _H = %00000100 ' dit dit dit dit
SYMBOL _I = %00000010 ' dit dit
SYMBOL _J = %01110100 ' dit dah dah dah
SYMBOL _K = %10100011 ' dah dit dah
SYMBOL _L = %01000100 ' dit dah dit dit
SYMBOL _M = %11000010 ' dah dah
SYMBOL _N = %10000010 ' dah dit
SYMBOL _O = %11100011 ' dah dah dah
SYMBOL _P = %01100100 ' dit dah dah dit
SYMBOL _Q = %11010100 ' dah dah dit dah
SYMBOL _R = %01000011 ' dit dah dit
SYMBOL _S = %00000011 ' dit dit dit
SYMBOL _T = %10000001 ' dah
SYMBOL _U = %00100011 ' dit dit dah
SYMBOL _V = %00010100 ' dit dit dit dah
SYMBOL _W = %01100011 ' dit dah dah
SYMBOL _X = %10010100 ' dah dit dit dah
SYMBOL _Y = %10110100 ' dah dit dah dah
SYMBOL _Z = %11000100 ' dah dah dit dit
SYMBOL _0 = %11111101 ' dah dah dah dah dah
SYMBOL _1 = %01111101 ' dit dah dah dah dah
SYMBOL _2 = %00111101 ' dit dit dah dah dah
SYMBOL _3 = %00011101 ' dit dit dit dah dah
SYMBOL _4 = %00001101 ' dit dit dit dit dah
SYMBOL _5 = %00000101 ' dit dit dit dit dit
SYMBOL _6 = %10000101 ' dah dit dit dit dit
SYMBOL _7 = %11000101 ' dah dah dit dit dit
SYMBOL _8 = %11100101 ' dah dah dah dit dit
SYMBOL _9 = %11110101 ' dah dah dah dah dit
SYMBOL Space = %00000000 ' word spacing in message
' -----[ Variables ]-------------------------------------------------------
SYMBOL char = B0 ' must use B0 for char!
SYMBOL elements = B1 ' elements in character
SYMBOL chcount = B2 ' character count
SYMBOL cidx = B3 ' character index
SYMBOL midx = B4 ' Morse element index
SYMBOL millis = W5 ' output pulse timing
' -----[ Initialization ]--------------------------------------------------
Reset:
PINS = %00000000 ' all off
DIRS = %00000001 ' P0 is an output
' -----[ Program Code ]----------------------------------------------------
Main:
READ 0, chcount ' read # of chars
cidx = 1 ' point to first
Another:
READ cidx, char ' read char from message
GOSUB Morse ' output
cidx = cidx + 1 ' point to next
IF cidx <= chcount THEN Another ' do another if not done
GOTO Main
' -----[ Subroutines ]-----------------------------------------------------
Morse:
IF char = Space THEN Word_Space ' check for space in message
elements = char & %00000111 ' isolate element count
IF elements < 6 THEN Bang_Key ' standard character
IF elements = 7 THEN Adjust_2 ' 6-element char ends in dah
Adjust_1: ' 6-element char ends in dit
char = char & %11111011 ' put dit in 6th position
GOTO Bang_Key
Adjust_2: ' 6-element char ends in dah
elements = 6 ' correct count
Bang_Key:
FOR midx = 1 TO elements ' loop through char elements
LOOKUP BIT7, (DIT_TM, DAH_TM), millis ' convert bit7 to timing
Blinker = IS_ON ' do the output
PAUSE millis
Blinker = IS_OFF
PAUSE DIT_TM
char = char * 2 ' left shift by 1 bit
NEXT
Char_Space:
PAUSE DAH_TM
RETURN
' -------------------------------------------------------------------------
Word_Space:
PAUSE WRD_TM
RETURN
' -----[ User Data ]-------------------------------------------------------
Message_Len:
EEPROM (8) ' address 0 in EEPROM
Message_Data:
EEPROM (_4, _2, Space, _P, _S, _I)
EEPROM (Space, Space)
This is a fun one to think about. I always enjoy following along as these solutions are done.
Brian...you're going to have to tell us what you're using the morse code for!
Those that monitor my Prop-1 coding style will know that I typically start defining byte variables at B2. Here is an example where B0 is a great choice. With B0 and B1 (combined as W0), we also have access to the individual bits (BIT0..BIT15).
The characters are encoded with the upper five bits holding dits (0) and dahs(1), and the lower three holding the elements count. Let's say we want to send a 2 (_2 in my constants). The internal value for _2 is %00111101. If we break that apart we get
%00111 (Morse code for 2 in binary form)
%101 (five elements in the code)
For 2 we have to send dit dit dah dah dah. Note that these are encoded left-to-right with the first element in BIT7 of char. This is why I chose B0 for char: it gives me direct access to BIT7 (standard variable in PBASIC). To me, Scott's original program was a little less clear, but it didn't rely on a specific variable like I do. Scott's code looked something like this:
IF char >= 128 THEN Dah
GOTO Dit
This make sense to me because I live and breath code, and I automatically associate 128 with BIT7 -- but most people don't. My goal is to write code that is clear and easy to understand. In this case, the only difference between dit and dah is the timing. One of the wonderful features of PBASIC is LOOKUP, which lets use one value as an index into table of values. In Scott's code he has separate Dit and Dah routines -- the only difference between them is timing. I chose to create an integrated routine and set the timing like this:
LOOKUP BIT7, (DIT_TM, DAH_TM), millis
In some programs we have to worry about the index value not fitting into the table, but that's not the case here because BIT7 can only have one of two values: 0 or 1.
Keep in mind that the BS1 processor has been around for 20 years now and there is a lot of code floating around. When you find it, try it and then modify it to see if you can make it smaller and more efficient. The Memory Map feature of the IDE is a valuable tool for doing this.
That's great code Jon, I look forward to studying it more and learning from it. And I agree, that's a ton easier to adjust the message when needed.
Yeah, after the Halloween season I have to study this one too. While I consider myself fairly good at writing BS1 code (thanks to Jon!) I'm by no means an expert, but this one is WAY over my head!