First SX Assembler Program on an SX48 Module

All--
While I'm waiting other developments, I decided to try to cut a little SX assembler code. The last assembler I used was either·for the·8080 or Z80 instruction set. This was a long time ago.
In any case, I was rather amazed at how the rudiments returned to me! All the code listed below does is blink an LED and call a subroutine for the pause. The environment is a PDB with one of RobotWorkshop's SX48 modules,·a USB SX-Key Rev. B and the SX-Key v3.3.0 IDE.
If you have time to look at the code, I would appreciate comments. I would PARTICULARLY like to learn how to time instructions so I could write a good delay routine, instead of empirically figuring it out. Plus, I am sure the code could be shortened a bunch. I would really like to see how one might do that. (It would be cool if I knew how to make these little code segments look neat in a post like everyone else does, too.)
Thanks!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
Post Edited (Bill Chennault) : 1/16/2010 8:49:26 PM GMT
While I'm waiting other developments, I decided to try to cut a little SX assembler code. The last assembler I used was either·for the·8080 or Z80 instruction set. This was a long time ago.
In any case, I was rather amazed at how the rudiments returned to me! All the code listed below does is blink an LED and call a subroutine for the pause. The environment is a PDB with one of RobotWorkshop's SX48 modules,·a USB SX-Key Rev. B and the SX-Key v3.3.0 IDE.
If you have time to look at the code, I would appreciate comments. I would PARTICULARLY like to learn how to time instructions so I could write a good delay routine, instead of empirically figuring it out. Plus, I am sure the code could be shortened a bunch. I would really like to see how one might do that. (It would be cool if I knew how to make these little code segments look neat in a post like everyone else does, too.)
Thanks!
--Bill; Program name: 01-16-10 SX48 First Assembly Code.SRC
;
; Author: Bill Chennault
;
; Date: 01/16/10
;
; Description: This program blinks an LED and uses a subroutine for delay
device··sx48,oschs3
IRC_CAL··IRC_SLOW
reset··start_point
freq··50_000_000
org··0···; place assembled code beginning at address 0
start_point·
Main
··mov ·!rb,#0··; make port B pins all output
··mov·rb,#0··; make all port B pins high (turn LED on)
··call·Delay··; pause
··mov·rb,#1··; make all port B pins low (turn LED off)
··call ·Delay··; delay
··jmp·Main··; do this forever
; subroutine: Delay
Delay··mov·$0f,#$ff·; set fr 0fh to ffh
··mov·$10,#$ff·; set fr 10h to ffh
··mov·$11,#$14·; set fr 11h to 14h
pause··decsz·$0f··; decrement fr 0fh; if 0, skip the next instruction
··jmp·pause··; it wasn't 0, stay in the loop
··decsz·$10··; decrement fr 10h; if 0, skip the next instruction
··jmp·pause··; it wasn't 0, stay in the loop
··decsz·$11··; decrement fr 101; if 0, skip the next instruction
··jmp·pause··; it wasn't 0, stay in the loop
··ret
jmp start_point
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
Post Edited (Bill Chennault) : 1/16/2010 8:49:26 PM GMT
Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon McPhalen
Hollywood, CA
When I was writing the code above, I looked at a PAUSE in SX/B using Ctrl-L. I thought I would just copy and paste it into my program. Ha! No such luck! First, copy doesn't appear functional·from within·a Ctrl-L listing. Second, the code must use the compiler (at least in that particular case) in a way that makes it useless as an example.
Of course, I will continue to use the Ctrl_L function to get hints, but it did not work out for me with the PAUSE statement.
If each instruction executes in one tick of the clock, then to determine timing·do I just·count the instructions and call that the denominator of frequency/number of instructions?
--Bill
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
A second look at the Ctrl-L listing shows I was wrong in my assumptions about the code not being valuable in the PAUSE case. I just did not understand all the system variables automatically defined upon SX/B compilation.
Thanks!
--Bill
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
You may find, as I did, that a hybrid program of SX/B and Assembly will work well. At the beginning I started with pure SX/B; over the last 24 months everything has been hybrid. When I started using the Propeller I immediately started writing support objects (e.g., SIRCS stuff in this month's N&V) in Assembly -- which is far easier on the Propeller than on the SX.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon McPhalen
Hollywood, CA
Hmmm. Easier on the Propeller, huh?
For now, I am bedeviled by merely calculating the timing involved in my little Delay subroutine. It can't be hard! One cycle for all but the branching instructions and four cycles for DJNZ if it branches and two cycles if it doesn't makes it seem easy to calculate. Maybe I will have an epiphany soon.
--Bill
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon McPhalen
Hollywood, CA
Please give me a hand with this timing calculation on a 20MHz SX28! Here's the code and my calculations . . .
; subroutine: Delay
Delay
··· mov __param1,#255
··· mov __param2,#255
··· mov __param3,#80
d1· djnz __param1,d1
··· djnz __param2,d1
··· djnz __param3,d1
··· ret
========================================================
Given:·mov················ =·2 cycles
······ djnz without branch = 2 cycles
······ djnz with branch··· = 4 cycles
·
Therefore, the calculations are . . .
2·+·2 +·2··········· =··········6 mov cycles
2 * 80 * 255·········=···· 40,800 djnz non branch cycles
4 * 255 * 255 * 80· ·= 20,808,000 djnz branch cycles
······················
······················ 20,848,806 cycles
At 20MHz each cycle takes 50ns and there are 20,848,806 cycles. Therefore . . .
50 * 20,848,806 = 1,042,440,300ns or 1,042,440.300us or 1,042.440ms or 1.042s.
Is this ABOUT right?
Thanks (A LOT)!
[noparse][[/noparse]EDIT: Changed·mov instruction cycles from·1 to 2 and all involved calculations.]
--Bill
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
Post Edited (Bill Chennault) : 1/17/2010 5:41:35 PM GMT
Give the attached scheduling program kernels·a shot. One is for SX28, and·the other for SX48. They should run right off the bat, flashing LEDs. The scheduler kernels·allow independent co-operative programs to be operated with little interaction between different applications. The kernels permit programs to be executed at various rates, from microseconds to seconds.
Also take a look at my (2004?) Parallax contest submission that explains the concept of co-operative programs.
Cheers,
Peter (pjv)
This morning, I figured out the correct way to use the $ operator and thereby eliminated the label "d1" in my delay routine. A little victory for me, but no help in figuring out the total time the delay routine consumes. I THINK it is correct that the delay routine causes a delay of 1 second (1.042). If anyone can confirm my number or calculations shown above, I would appreciate it. If there is a better was to calculate it, I would like to know.
pjv, I downloaded your code this morning and will work with it now. I am sure I will learn a lot. (It is clear and concise.)
--Bill
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
PJV's scheduler is very helpful, though it will take wrapping your mind around it's structure and adapting to it. I have incorporated some of Peter's style into many of my programs.
On your calculation, this instruction:
...is actually 2 cycles because it breaks down to:
This is why I have never tried to do timing loops -- I don't have the patience. With Peter's scheduler an interrupt creates a base "tick" rate that you can build on.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon McPhalen
Hollywood, CA
Peter, I printed off your article. Unfortunately, since I do not have Office on this machine, or anything else that might get in the way of my robotics efforts, except Windows itself, of course, I could not get your picture! I'm desolated! (I will print it off again with the machine at my reading desk!) Peter, do you like my hat? [noparse]:)[/noparse]
Thank you very much for the advice . . . in the 30 seconds I've looked at the code, I can tell it is going to help a lot.
Jon, I understand--at least a light is glowing dimly at the end of the tunnel--about the difficulty of calculating timing. I may never be its master, but I refuse to be its slave! [noparse]:)[/noparse] Thanks for the feedback on the mov instruction. That will add 3 additional cycles. Not much. But, it is my nature to know things exactly if I am capable of comprehension in the first place. (Of course, nothing I am going to do with a microcontroller will require that precision.)
--Bill
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
Peter, your RTOS code is beautiful.
Where would one stick an application program's power-up initialization routine?·Between the "Initialize" label and the "InitLevels" label?
For example, my code has to initialize a parallel 2x16 LCD upon power-up. It seems that the spot I mentioned above is the correct place.
Thanks for suggesting this approach!
--Bill
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
I would do that right after all the RTOS initialization is complete, so, immediately before starting the scheduling kernel running.
Cheers,
Peter (pjv)