Atmega328P Morse Code /w 4 digits

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, 

 

I am trying to figure this whole assembly language. I have the manual and a strong understanding of c++ but haven't played with assembly before. I am simply trying to feed the Atmega328 4 digits and have it produce Morse code with the led light by simply blinking. It would be standard Morse Code U.S. I am just lost to even how to start or what to use. I have the Arduino software but that is for c++. So I guess how would I start this like what is the int main(), and basics of starting up. Also may I please have some sample code such as to make the led blink. I have heard on forums that you have to convert the input into an output? Sorry to be such a noob and like I said if this was c++ it would be easier. Please reply with assembly code and perhaps explain what is going on. 

 

 

Sincerely,

 

Jeff

Old Army Vet

Last Edited: Tue. Nov 28, 2017 - 08:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is no advantage in using ASM for Morse Code.

 

I suggest that you start with existing Arduino library examples.   Then study how the library works.

If you are more familiar with C than C++,   you can probably find C code instead of the Arduino C++.

 

There are very few places where ASM is "better" than C/C++ e.g. a fast interrupt service routine.

Your time is better spent in gaining experience with High Level Languages.

 

Only learn ASM if you have a real-life project that would "notice" the difference.

 

Does "vet" mean Veterinary Surgeon or Army Veteran?

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you really feel the need for pure Asm I'd get a copy of Studio 7. You'll find it a lot easier to do "pure Asm" in that rather than trying to bend the Arduino IDE to your will. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Veteran, I would love to use c++/c but I am required by my assignment given to me to use assembly. I was thinking something like.

 

Psudo Code;

 

.section .data

 

n1:   .byte 4

n2:   .byte 2

n3:   .byte 1

n4:   .byte 0

 

.section .text

    .global main

 

main:

 

    LDS R24,n1

    LDS R25,n2

    LDS R26,n3

    LDS R27,n4

 

led:

 

    R24 -> Send to LED to Blink in Morse Code

    Loop and R++

 

.end

 

 

0 DASH DASH DASH DASH DASH END

1 DOT DASH DASH DASH DASH END

2 DOT DOT DASH DASH DASH END

3 DOT DOT DOT DASH DASH END

4 DOT DOT DOT DOT DASH END 

5 DOT DOT DOT DOT DOT END

6 DASH DOT DOT DOT DOT END

7 DASH DASH DOT DOT DOT

8 DASH DASH DASH DOT DOT 

9 DASH DASH DASH DASH DOT

 

DOT = 1 cycle/ 1 second (on) 

1 cycle/second (off)

DASH = 3 x (1 cycle/ 1 second (on) )

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have the AVR instruction set document? ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf

There's also an AVR assembler document http://ww1.microchip.com/downloa...

 

Here's a thread on getting an LED to blink

http://www.avrfreaks.net/forum/n...

 

And there's a few assembly threads in the tutorial forum.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I noticed that a second would be 16 million cycles so would this loop/delay for the off for 1 second?

 

.global _start

_start:

MOV R0, #0

MOV R1, #1

B _continue_loop

_loop:

ADD R0, R0, R1

_continue_loop:

CMP R0, #16,000,000

BLE _loop

end:

MOV R7, #1

SWI 0

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do and I am only allowed to use...

 

 

ADC

ADD

 AND

ANDI

ASR

 CALL

COM

CP

CPI

EOR

IN

JMP

LDI

LDS

LSR

MOV

NEG

NOP

OR

ORI

OUT

POP

PUSH

RCALL

RET

RETI

RJMP

STS 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I strongly advise doing the project in C/C++.   

 

When everything is working 100%,   start to port to ASM.

We are happy to show how to translate line by line.

 

I am sure that this approach would be more effective than trying to teach ASM from scratch.

Yes,  pseudo-code is a good way to express ideas.   A flowchart is even better.

 

But I really think that a Blinky would be more appropriate as a first ASM assignment.

 

David.

 

Edit.   Perhaps it would be wiser to shoot your Teacher.

Last Edited: Tue. Nov 28, 2017 - 10:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To make an AVR do anything with Morse Code in assembler can be tricky because each Morse character can have a variable number of elements with each element being either a dash or a dot.
If I recall correctly, there can be from one to six elements in a Morse character.  The "e" is one element [ a single dot] and the numbers and punctuations have five to six elements [a mixture of dots and dashes].
Let's assume that there are no more than eight elements in each Morse character. Now we set up a table for the entire set of all possible Morse characters.  Since computers already use a table for characters called ASCII (aka Unicode), we will use that.
We make each entry into this table be eight bytes long. When we output a Morse character, to an LED in this case, we take the ASCII value of the char that we are sending, multiply it by eight, and add the result to the beginning of the table in order to get the place in the table where the Morse char will begin.
Each entry in the Morse char table will have eight bytes. Starting at the first byte, if the byte value is zero, then it represents a dot. If it is one, then it is a dash (the LED is lighted about three times as long as a dot's interval).  If the byte value is 255 or 0xff in hex, then the char is finished.

The Morse char table would look something like this:
;    0      1    2    3    4    5    6    7
.db 0x01,0x00,0xff,0xff,0xff,0xff,0xff,0xff
.db 0x01,0x01,0x00,0xff,0xff,0xff,0xff,0xff
.db 0x01,0x01,0x00,0xff,0xff,0xff,0xff,0xff
.db 0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff
.db 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff
.db 0x01,0x00,0x01,0x00,0x00,0xff,0xff,0xff
.db 0x00,0x01,0x00,0xff,0xff,0xff,0xff,0xff
.db 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since you're allowed to use call/rcall and ret, I'd suggest you write a few of functions first.  One to flash the LED for a dash, one to flash the LED for a dot, and one to pause at the end of a letter.

 

While this may not be the 'optimal' approach (e.g. there's an argument to be made for a single function which takes a parameter specifying either, dash, or dot, or end), it is a manageable task to begin with.

 

Breaking that down further, those functions could call a delay routine, perhaps specifying the number of milliseconds to delay.  That delay routine could itself call a routine which delays 1 ms.

 

So I would start there.  Write a routine which delays 1 ms.  Call it 'delay_one_ms' or some such.

 

Your first test could be the ubiquitous 'blink' program which flashes an LED for 1 second (1000 ms) on, then 1 second off, forever.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Tue. Nov 28, 2017 - 10:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To input Morse code, we first set up one of the timers to overflow a hundred times a second.  Then we convert the dashes and dots that we receive into logic levels.  If the receiver is active, say if the LED is on for 0.2 seconds for a dot and 0.7 seconds for a dash (roughly), or a speaker is beeping for those intervals, then we need to convert the lighted LED and/or beeping into logic level high for "line mark".  No beep or LED lighting is logic 0 or "line space".   This logic level is on an AVR input pin.

  Every timer overflow (each 0.01 second) we test the AVR input pin.  If it is logic zero, or "line space", we ignore it.  If it is logic one, then we start a count of how many timer overflow intervals that it remains at logic one.  If the number of intervals is between 10 and 30, then it is a dot.   If the number of intervals is between 50 and 80, then it is a dash.  After each logic high count, we check the interval that the Morse receiver is at logic zero.  If it is longer than 150 or so, then it is the interval between characters.

  Then we go to the beginning of the table and compare the elements (dots and dashes) in the received char to the entries in the table.  If the first received element is dot, then starting at the beginning of the table, if the first table entry is a dash, then we skip that entry and go the next Morse Table entry, which is eight bytes away.  We compare each element in the Morse Table to the elements in the received character.  When the elements are the same and the length of the received char matches the length in the table, then we have found the character.  It is the character for the ASCII value of the offset into the Morse Character Table (divided by eight).  Then the AVR UART can send that character to a terminal and we can read on the terminal the characters that the AVR is receiving in Morse code.  This does mean that the sender has to be rather precise in his "hand", as the ham radio people refer to how a person sends Morse code with a keyer machine.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, 
Not sure if it would help, but here is my code for a morse code watch I made. You can take bits and pieces as you see fit. It uses a 32.768 KHz oscillator so you'll need to adjust the timing. 

The code seems too long to post in here, so here's a link to pastebin: https://pastebin.com/Wr46reiD

It uses an AtTiny24A and timer 0 for counting seconds.

 

Also,
I'd strongly suggest using international morse code instead of US morse code because US morse code is dead, to say the least. 

-Matt (N2EEE) dit dit dit

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N2EEE,  the OP has stated that this is an assignment, so US morse code is likely a requirement.

 

And by the way, it's bad form around here to spoon feed the students by giving them a complete solution ;-)

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

N2EEE,  the OP has stated that this is an assignment, so US morse code is likely a requirement.

 

And by the way, it's bad form around here to spoon feed the students by giving them a complete solution ;-)

 

 

Ah, you're right, didnt realise this may be a constraint of the assignment. The code I provided hopefully aims them in the right direction instead of giving them an answer. 

-From a fellow student (Electrical/Computer Engineering)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Some years ago I built an AVR-based gadget (designed for a 90S1200, and written in assembler) that flashed my Christmas lights in Morse Code.  It had [A-Z, 0-9] but no punctuation or  'special' characters.  It flipped a relay for the 110VAC line  (yeah, a Triac would have been better).  The first year it said "IF YOU CAN READ THIS SEND ME EMAIL"* and gave my email address.  Nobody sent me anything.  crying

 

Miserably slowly, of course.  Maybe 1 or 2 wpm.  It still works.  Maybe I'll string it up in my lights again this year.  Knowing that nobody (around here) can read it, I could make them say something remarkably rude...  Any suggestions?

 

It has an RS-232 port for putting in new messages, which are kept in the EEPROM.

 

So kudoes to our student!  It can be done.  I could cut'n'paste my entire code**, but on the grounds that it's an assignment, it's "left as an exercise for the student".  So there...  cheeky

 

S.

 

* Sorry for the SHOUTING but Morse Code doesn't have lower case.  S.

** It also uses the LPM instruction for the RS-232 interface (menu strings written out in flash), so our student can't use it anyhow.  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:

It had [A-Z, 0-9]

 

* Sorry for the SHOUTING but Morse Code doesn't have lower case.  

 

Well why would anyone want to send SOS quietly?

 

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:

If I recall correctly, there can be from one to six elements in a Morse character

 

The 'Error' or 'backslash' characters include seven dots.  Not that my gizmo cared much - I highly inefficiently stuffed every symbol into an eight-element array.  S.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That looks like ARM or maybe AVR32 assembler!
Note that the AVR (8 bit) works in 8 bit chunks, so to hold 16000000, you’ll need at least 3 registers.

I’d suggest if you can code it in C/C++, then converting it to assembler should be straightforward.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well why would anyone want to send SOS quietly?

Correct! When I forget the BBQ at high temp and the sausages burn I get screamed at: Save Our Sausages......

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
then converting it to assembler should be straightforward.
Even more straightforward because the C/C++ compiler will just do that naturally anyway (use -save-temps to see what it comes up with)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,   I disagree with the assumption that it is bad form to provide students with the code needed for their assignments.  Students, by definition, are trying to learn how to do this and the best way to learn is to have someone show you fully working code that does exactly what you need done, and then either study it, or have some tutor explain it to you. 

 

 We are entering an era where engineers won't write their own code for most applications, but rather will study and adapt some pre-written open-source code to their application.  And the best way to do this is to examine code that already works.

 

Schools in general and American universities in particular are losing their status of being primarily educational institutions and are beginning to function more as $50000 a year indoctrination centers.  While this situation affects the Engineering colleges less than the other colleges, nevertheless there are many people entering the embedded systems field who have had little or no formal education in embed sys development.  Goodness knows, the entire field didn't exist when I was in technical college.  People need to learn how to do this from wherever they can: formal classwork or not.

 

So, yes, go ahead and send us your homework assignments.  I will help you with them if I can, even if I'm the only one here who will.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If I had the choice between hiring a student who only knew how to bolt the bigger pieces together, and hiring a student who knew how each piece itself works and could build one from scratch if needed, guess which one I'd hire.  Now, guess what approach to teaching I would use.

 

I will help you with them if I can, even if I'm the only one here who will.

Rubbish.  History suggests, if anything, you'll tell them all to go out and buy and Arudino, and then 'job done'.

 

I think perhaps we should return to the subject of the OP, and stop debating the finer points of pedagogy, as this street car is about to take a short turn to a political discussion.  None of it helps the OP achieve his task, which is to complete an assignment.  Handing him a completed assignment subverts that process, and were I his instructor (or another student in his class) I would like to have a word with whoever does.

 

By the way, anyone heard from the OP lately...? ;-)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:
I will help you with them if I can, even if I'm the only one here who will.

 

Thats nonsense!

Everyone here helps for the most part.  But very few will just "GIVE" up the answer.  Thats why we ask "Show what you have done" to see where the OP is at in everything.  Sure there is some learning in reading a completed answer instead of figuring it out on ones own with assistance from a very talented pool of individuals like we have here.  But one usually retains more by working THROUGH a problem, and hopefully knowing how to spot the same problem in the future, instead of simply looking at the answer. done by someone else.

 

Now I will throw one caveat to that last statement.... Alpha-Numeric 16x2/20x4/et. al. LCD screens.  Many of us are guilty of simply telling a noob to go find Peter Fleurys code and move on with their lives.  In that case His code is pretty well commented that it should be in textbooks(do they still exist BTW?), as you can actually learn from it.  At the same time, most of the LCD routines I see in projects are simply copy>paste it simply does not make sense to re-invent the wheel.  I2C/TWI as well.  

 

But in the case of TWI/I2C we generally do recommend that the OP use a PROVEN library first to get a better understanding of whats going on before they roll their own.  THis could be debated for quite some time.

 

joeymorin wrote:
I think perhaps we should return to the subject of the OP, and stop debating the finer points of pedagogy, as this street car is about to take a short turn to a political discussion.  None of it helps the OP achieve his task, which is to complete an assignment. 

Agreed.

 

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To be perfectly fair (and go back to the 'helping!' thing) I came up with just about the same thing as Simonetta, although I used $01 as a dot, $02 as a dash, and $00 as a terminator and space-filler.

 

 

.db $01,$02,$00,$00,$00,$00,$00,$00        ; A
.db $02,$01,$01,$01,$00,$00,$00,$00        ; B
.db $02,$01,$02,$01,$00,$00,$00,$00        ; C
.db $02,$01,$01,$00,$00,$00,$00,$00        ; D
.db $01,$00,$00,$00,$00,$00,$00,$00        ; E
.db $01,$01,$02,$01,$00,$00,$00,$00        ; F
I wish the 'code' window worked for me.

 

 

I also had the whole thing running off a 'one dot time' timer.  Everything was done at a multiple of 'one dot time'.

 

But there is a better way!  Poking through my files I found I'd tried to get more clever too (Hey, want a good grade?)

 

MORSE_CODE:

; 1st byte is 'how many elements (dots + dashes)
; 2nd byte is 'what are the elements? 0 = dot, 1 = dash,
    ; bits after #element_num are ignored (but set to 0 anyhow)

.db $02, 0b01000000        ; A
.db $04, 0b10000000        ; B
.db $04, 0b10100000        ; C
.db $03, 0b10000000        ; D
.db $01, 0b00000000        ; E
.db $04, 0b00100000        ; F

 

I also found some more punctuation marks that involve seven elements.  Talk about a dramatic space saving!!

 

S.

 

Edited to add:  The 2nd version is particularly fun in assembler because you can decrement one register while bit-shifting another, and branch based on the carry flag.  S.

Last Edited: Thu. Nov 30, 2017 - 11:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Further space economy...

One byte per letter/digit.

.db 0b00001001        ; Dollar sign [$] (Not in ITU-R recommendation)
.db 0b11111001        ; A
.db 0b11101000        ; B
.db 0b11101010        ; C
.db 0b11110100        ; D
.db 0b11111100        ; E
.db 0b11100010        ; F

skip ones (if any), skip 0 (starting indicator), transmit rest bits