Would you please, if I may, seriously consider opting out of this discussion.
Sorry, I'm not opting out.
Look, you said: "This is at least 50 times more difficult than writing in SPIN. I have to feel my way through the haze." It's not really that hard, but that is your perception because you have lots of work to do.
You are on a big learning curve. If you are not willing to dig in and CAREFULLY read the data-sheets, manuals, and tutorials discussed at the start of this thread regarding PASM, you will FAIL.
As for examples, there are literally hundreds of code examples out there to read. The OBEX and the Propeller Tool libraries offer wonderful examples. All you have to do is have a look.
Why don't you move the conversation forward by posting your broken code and let us help you learn from your mistakes? Don't spend all afternoon on something without reaching out. Hopefully your learning curve will get smaller with that. Everyone has broken code from time to time. Everyone finds ways around it or just gives up.
Regarding RES. You can use RES for uninitialized variables, but there are dangers in using it. I've already mentioned one of them below to try and save you from the grief that comes from it.
It truly amazes me that you have divined that I am planning to write a book on PASM for beginners without reading anything!
What a fantastic idea. I have read, scanned and searched more pages than you can possibly imagine.
The documentation provided by sophisticated code writers is so sparse and hard to decipher that I am left scratching my head.
Lines upon lines are left undocumented. Often comments don't explain anything to me. The posted stuff is not for beginners. No way.
My SPIN book has well over 120 pages of just SPIN code in it and each and ever line is carefully documented for beginners.
My PASM book will have over a hundred of pages of PASM code in it and every line will be understood by me and every line will
be followed by documentation that anyone can understand. There will be no short hand code that is hard to understand by beginners.
You gave me pages of hard to understand, complicated code on how to share a variable between PASM and SPIN and I
could not understand any of it. Hardly a way of explaining it to a beginner.
It was I, who after reading the manuals and data sheets, who wondered if one could not read and write the same register in the two languages.
Then...
Kuroneko showed us all how to do it in a few lines and I could understand every line. Even a dynamic demonstration of the code on the Demo board.
Fantastic. Crystal clear. No high flying confusing code.
Kuroneko showed us all how to do it in a few lines and I could understand every line. Even a dynamic demonstration of the code on the Demo board.
Fantastic. Crystal clear. No high flying confusing code.
There is little difference between the two examples. If you understand one you can understand the other.
Why don't you make kuroneko's code your first example of variable sharing. Then move on to a more advanced version. If you want to share more than a few variables, you'll have to store multiple pointers. How you do it is up to you.
You gave me pages of hard to understand, complicated code on how to share a variable between PASM and SPIN and I could not understand any of it. Hardly a way of explaining it to a beginner.
Considering the volume of study you have claimed to have enjoyed, my example should have been easy.
I eliminated the last two lines of your program as I could not understand what they did. I still works but I wondered of I had missed something. Did I do it right?
No problem. The fit just makes sure that the program fits (who would have thought) into the cog user area (0..495). Not too important for just a few lines but I made it a habit. As for the trailing DAT (another habit), the propeller tool eats empty lines from the end of the file when saving. This really gets up my nose. Nothing essential ...
I feel that if you try and write a book as you learn a subject you are bound to end up including the typical misconceptions we all have as we learn. In your spin book, the section on PID is totally incorrect (I assume for this reason) and I fear this could also happen for this book. I think you need to be extremely careful when you write this book, assembly is difficult enough for those with a fear of it.
I think you are a little unfair on the available documentation, I think that DeSilva's tutorial is pretty helpful, there is also Potatoheads which is more digestible, I made my simple set of examples for the stuff I found the hardest at the start too: http://forums.parallax.com/showthread.php?94027-Assembly-step-by-step&p=647408 which has helped a lot of people get started. But I agree there is a space for a nice book on the subject.
Can one say that the RES area has to list all variables that will be used in the program and that all constants have to be listed as " value long 2000" which means that these are the equivalent of the VAR and CON areas of a SPIN program?
Important, res should always come last (every then and now I look for an exception but haven't found anything useful yet).
As for usage, res covers uninitialised variables whereas long & Co are responsible for constants AND preset variables, e.g.
' initialised data and/or presets
[COLOR="orange"]addr long 0 ' preset variable
mask long 1 ' preset variable[/COLOR]
mono long -4 ' constant
[COLOR="orange"]dist long dist_preset ' preset variable[/COLOR]
sign long sign_preset ' constant
frqb_ long frqb_preset ' constant
phsb_ long frqb_preset * (-2) ' constant
' uninitialised data and/or temporaries
[COLOR="blue"]eins res 1 ' temporaries
zwei res 1 '
drei res 1 '
vier res 1 '[/COLOR]
fit
Using res:
Your program will be writing a value first before it ever reads from it.
Using res will let your assembler calculate the address it will represent
but the data will not be included in the program itself, making it shorter.
Though you will not gain any cog ram, so in theory you could instead use
labelname long 0-0 , but you would make the code longer and it may also take longer time
to set up the new cog (I'm not sure if 496 longs is always transferred even if code is shorter?)
Using res, will force you to both iniate and reset the value for a loop etc, making for less buggy program.
... but you would make the code longer and it may also take longer time
to set up the new cog (I'm not sure if 496 longs is always transferred even if code is shorter?)
That would be brilliant but we are stuck with 8K cycles (512 hub windows). Besides, you'd have to indicate the length somehow.
So it always sends 512 longs, in that case can even the shadow registers be initiated?
If code it cramped I guess you could skip: mov cnt,#5
and have it set at start up of cog.
Yes! I think something like SPIN has some variance in what people might need to get it to "click" for them. Truth is, SPIN is pretty easy. Somebody can just jump in and do stuff and have some shot at success. It's pretty easy to poke around, change stuff, and watch what happens. That's what I did on the first day, and it was a total kick!
I don't think PASM shares that quality, though I personally think it's one of the most fun and easy to code assembly languages I've seen. Clean. Poking around requires some playground that's setup with strong expectations set so people know what to poke around on, and how to "see what it does". Honestly, that's a significant work right there.
I've had a work in progress for a while now, a follow on to the tutorial mentioned here. Over the few years that's been up, I've received e-mails from people saying, "I got it", or "thanks". Personally, I always thought the thing was too wordy and short on visuals. (I have found it challenging to change both, but I think I'm on a good path at present.)
That said, just look at the number of words to introduce the very basics, and I mean basics as it's really only a primer meant to kick somebody off into exploring more PASM. Given those things, it's very easy to see that boot-strapping newbies to assembly language requires a lot of context. Assembly language is basic, and very abstract in many ways.
And there are two kinds of people to write to, well maybe three, you tell me.
One is the person who has dealt with assembly before somewhat successfully. The other is the person who has no assembly language experience at all.
These are two very different user experience states to write for, which is exactly why DeSilva and I decided to break it where we did. At the time those were written, I was still coming up to speed on PASM. (Still am today, frankly --and it's a lotta fun) DeSilva had reached a nice level of mastery, and found it difficult to write for the newbie because of that. Made perfect sense for me to introduce the thing, in the hopes they could get far enough to jump into the other material out there. And the three things, including Grahams work are actually pretty good. They are just not well presented.
I don't know where you plan to go with your effort Harpit, but I would give it some serious thought as to who you are writing for and why. Then consider scope of concepts introduced and then work from there. I'm personally going to start at "has no assembly experience", and carry through solid, basic PASM programs, as I think that's probably the most useful. Really interested people will very likely have enough competency to jump in here and get at the good stuff like the rest of us do. (another book for advanced is totally needed, and something I hope to get at for Prop II, or see somebody get done for Prop II)
IMHO, the big problem people have with assembly language is the fundamental nature of it. Higher level language constructs can do lots of things for people, and one of the bigger ones is simply managing representations of things, the other being program flow and storage management. From there, one can easily have whole tasks abstracted to a simple command, and that is what makes the higher level languages work for people like they do.
In assembly land, it's all up to the programmer, and when one does not understand the very basics of how computers really do things, assembly language appears as this arcane wizardry, obtuse, cryptic. That's the challenge to be met, IMHO. Context is everything, and it's not just a matter of documenting favorable commands and workflows, like it can be for a cookbook, or higher level language introduction.
There is a third consideration too, and that is kinds of assembly language. For me, the PASM experience was favorable. It seemed to click easily enough, and it's beautiful really. I think some of that had to do with the kinds of assembly language experiences I had accumulated. There are some CPU instruction sets that are similar in concept to PASM, and there are a lot that are very different. For the "has assembly language" experience set of beginners to PASM, some relating of those concepts and establishing of common context is important, or differences in language, like "register" can really make a mess of things, doing more harm than good. I personally think this is challenging to do.
Harpit, I'm not putting this out here to compete, or discourage. My project got slowed by "that damn day job", but it is progressing, and it will get done.
I feel a fair amount of passion for PASM and the Propeller in general, and that's because the chip is cool, as are the people involved with it. Frankly, the whole scene has just been a lot of fun, and that counts for a lot.
Given that, it made perfect sense to put some lessons learned out there, with a gentle push to encourage you to take the time to, "do it right", or please don't do it, as it will do more harm than good. Really. I mean that, and I mean it in the very nicest of ways.
Note that the code listings in the PDF have the inline comments removed because this is material that goes to the magazine which prints in a two-column format; download the code for my inline comments if the article text is not enough.
you are taking the effort to learn PASM and writing a book for beginners. This is a big chance as you will encounter a lot of - of the same problems a beginner encounters.
The more somebody becomes an experts the more he/she is in danger to become blind for beginner-difficulties. Until he/she focuses again on these problems through practical teaching.
I would like to see before a book goes to printing that it is reviewed by beginners and by experts. By beginners to give it a last improvement about things the find still hard to understand.
By experts to catch bugs that beginners or advanced users (that you will be at this stage) do not see. After that it will be a book which is worth to make its way into the hall of fame,
because it is really easy to understand and has no bugs.
About debuggers: let's say - for a moment - the PASM-beginner is able to use the debugger. In this situation it will be a great help just singlestep through the code watching what is happening to any byte in the RAM and how the program flows
This is a great helpindeed.
Without a debugger the other possabilities of debugging is to switch on/off LEDs. Inserting code for printing some debug-output is way above the head of a beginner.
Know back to a real beginner that does not know how to use the debugger:
If you got a lot to learn about the debugger and have to do this learning through try and error because the manual about the debugger is just "three lines long"
I agree. It depends on how good and detailed the debugger manual is. Does the debugger-manual take the user by the hand and shows step by step screen-shot for screen-shot
how to use it and gives information about possible reasons why something might not work (forgot to insert debug-kernel or what ever) and how to solve it it will be easy to use
and the user will enjoy the extra-journey.
BMA is an advanced debugger with advanced possabilities and I want to emphasise: on beginners not that easy to use for beginners. IMHO PASD is easier for beginners.
The PASD-manual can be still improved. Now the question is who will do the work of the improvement?
I'm in temptation do do it. I enjoy this kind of work.very much. Writing such a manual takes much more time than writing some postings.
But I pull myself back as I know that other work that has a higher priority would suffer from that.
Maybe something inbetween. Harprit give PASD a short try and as soon as you encounter a problem using it - don't tinker around even if yiu would like to
tell me the problem and I will help. Maybe Ariba the author of PASD likes to help too.
About debuggers: I've programmed in assembler since the 6502 came along (AIM-65 in school, Apple II), 8080,Z80 (CP/M), and minicomputers (ND, VAX). I'm in camp with those who believe debuggers _are_ useful to complete beginner assembly coders. I remember when I learned my way around 8080 and Z80 assembly: I used the debugger to poke around and look at code, I wrote some code and stepped through it to see what it did. You learn very fast from that, the understanding comes much quicker than if you just code and try to run programs. Same thing when I was learning three different types of minicomputer assembly: Step through with debugger, see what every instruction does when it's doing it. And later, with 8088 and MS-DOS it was back to the debugger again.
After a very long hiatus I'm back to re-learn CP/M and 8080 assembly, and, this time as in the past, the way in is to start the debugger (SID in this case) and fiddle with code and single-stepping.
A couple of years back I began to write emulators for two different old minicomputer CPUs, and one of the very first things I did in both projects was to write a debugger that would let me single-step through actual code. I feel that you need to _see_ the code (and there is a one-to-one connection between assembly and code, unlike with Spin or any high level language) to get a feel for it.
Steve: Thanks to the link for that BMADebugger, I wasn't aware of it.
@Graham:
You have said this to me before and I accept your criticism.
My explanation of PID is intended for real beginners who will never understand the digital implementation of Kallman or any other filters.
If you read any of my books, you will see not a single equation. They are for beginners and beginners only. No complaints from beginners.
Yes there are mistakes in my books and I maintain errata on the internet. No one else seem to for their books. I handle customer support personally.
@Kuroneko:
As always thank you for you great help and comments.
@ PotatoHead:
I have read you notes for beginners. My stuff will be may times simpler than that.
I do not know enough the write the kind of stuff experience programmers can write
I will give it my best shot and will decide if I want to publish or not when I am done.
Its going to be a while
Thanks for your comments.
@JonnyMac:
Your article was helpful. Thanks
@Stephan:
I downloaded the debugger and am trying to get an understanding of how it works.
What is the short hand for changing one and a series of bits in DIRA and OUTA in PASM
Harprit
If you literally mean to change, as in to change 1s to 0s and vice versa, you would use XOR along with a mask value where a 1 bit in the mask would designate a bit that you wanted changed. If you're dealing with bits 8:0 only the mask could be a literal.
You may take offense at this, but my initial reaction when I started reading this thread was that it didn't seem like a particularly good idea to write a book about something that you're just learning about. I wouldn't want a brand new driver to write a book on driving. When I purchase a book, I tend to assume that the author knows his subject inside and out. I've been programming in PASM for about a year, and there are areas, major areas, that I haven't even touched. I visit these threads because I tend to learn new things whenever I do. And PASM is not my 1st assembly language by any means.
If you've never programmed in assembler before, it's hard for me to believe that you wil learn enough in a reasonable amount of time to do justice to your readers. Just my 10 cents worth.
MUX was hard to understand for me first, as I never seen this in other asms.
And it sounded to close to Multiplication.
What is does, it assume that you did a Test or Shift etc prior
and therefore there is an answer in Z or C now.
It will take this answer (can only be 0 or 1) and set the bits to this same stage of 0 or 1.
The Mask (source field) is so you can tell what bits you want this to apply to.
the mux.-commands (muxz, muxnz muxc muxnc) are the short way if the number of bits that should be changed can vary.
example with just 8 bits
Bit-Nr. 76543210
Bitstate 10000001
Bit-mask 00011000
after mux-command
Bitstate 10011001
now after some loops the mask might be
Bit-mask 00100111
then
Bit-Nr. 76543210
Bitstate 00000001
Bit-mask 00100111
after mux-command
Bitstate 00100111
Of course you could use operators like and andn or etc. but they would require more commands
copying actual state of f.e. outa to a temporal-used-long
manipulating the temporal-used-long with a command like "AND" with zeros to clear bits,
the command "OR" to set bits
another "OR"-command with the temporal-used-longand outa to set the bits in outa
With mux-commands you use one command to set or clear the Z-flag and then do the mux-command
mov _dummylong,#0 wz 'execute a command that sets the z-flag ((loading a zero will SET the z-flag if the wz-effect is specified)
muxz DirA,BitMask 'set IO-Pins as Output all bits that are set to "1" in BitMask will be set to one in DIRA
mov _dummylong,#1 wz 'execute a command that clears the z-flag (loading a value that is non-zero will clear the z-flag if the wz-effect is specified)
muxz DirA,BitMask 'set IO-Pins as Input all bits that are set to "1" in BitMask will be set to zero in DIRA
The PASD-Debug-Demo-code uses the ANDN + OR-command to set or clear bits.
''***************
''* PASD Test *
''***************
''
CON 'Use the following 2 lines if running on a Parallax PropDemo board
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
'Use the following 2 lines if running on a Hydra board
'_clkmode = xtal1 + pll8x
'_xinfreq = 10_000_000
VAR
long Cog, TestVar
OBJ
dbg : "PASDebug" '<---- Add for Debugger
PUB main
Cog := cognew(@entry, @TestVar) + 1
dbg.start(31,30,@entry) '<---- Add for Debugger
PUB stop
if Cog
cogstop(Cog~ - 1)
DAT
org 0
entry
' --------- Debugger Kernel add this at Entry (Addr 0) ---------
long $34FC1202,$6CE81201,$83C120B,$8BC0E0A,$E87C0E03,$8BC0E0A
long $EC7C0E05,$A0BC1207,$5C7C0003,$5C7C0003,$7FFC,$7FF8
' --------------------------------------------------------------
'
' Test code with modify, MainRAM access, jumps, subroutine and waitcnt.
'
:init mov dira,LEDS ' Configure LEDs as outputs (1)
andn outa,LEDS ' Set LEDs to the 'Off' state (0)
mov BlinkCounter,#0 ' Clear blink counter
:led_state_1 or outa,LED_0 ' Turn on LED 0 (Hydra)
or outa,LED_16 ' Turn on LED 16 (PropDemo)
andn outa,LED_17 ' Turn off LED 17 (PropDemo)
call #wait ' Delay
:led_state_2 andn outa,LED_0 ' Turn off LED 0 (Hydra)
andn outa,LED_16 ' Turn off LED 16 (PropDemo)
or outa,LED_17 ' Turn on LED 17 (PropDemo)
call #wait
add BlinkCounter,#1
cmp BlinkCounter,#5 wz
if_z jmp #:init
jmp #:led_state_1
wait mov WaitCounter,cnt
add WaitCounter,BlinkFreq
waitcnt WaitCounter,BlinkFreq
wait_ret ret
'
' VARIABLES
'
BlinkCounter long 0
LEDS long $00FF_0001 ' Bits 16-23 are PropDemo board leds. Bit 0 is Hydra LED.
LED_0 long $0000_0001 ' Hydra LED.
LED_16 long $0001_0000 ' PropDemo board LED.
LED_17 long $0002_0000 ' PropDemo board LED.
BlinkFreq long 40_000_000
WaitCounter res 1
fit
step through this code and then modify it with mov/mux-commands to see what the commands are doing
I also attach a file describing how to use PASD as an addition to the PASD-manual
This manual-add-on is a short test if you find it understandable this way
keep the questions coming
best regards
Stefan
oops forgotto attach the PDF-file ! corrected now.
Kinda following up on what Tor said, if you want to avoid the learning curve of a debugger right now, there is still value in studying the hex code from the PropTool (produced by pressing F8). daSilva recommended this, and used values that would be easy to find. I've answered many questions this way.
With mux-commands you use one command to set or clear the Z-flag and then do the mux-command
mov _dummylong,#0 wz 'execute a command that sets the z-flag ((loading a zero will SET the z-flag if the wz-effect is specified)
muxz DirA,BitMask 'set IO-Pins as Output all bits that are set to "1" in BitMask will be set to one in DIRA
mov _dummylong,#1 wz 'execute a command that clears the z-flag (loading a value that is non-zero will clear the z-flag if the wz-effect is specified)
muxz DirA,BitMask 'set IO-Pins as Input all bits that are set to "1" in BitMask will be set to zero in DIRA
Maybe it 's just me but I'd argue that these examples don't really get the mux message accross.
They way it stands now the first example is equivalent to or dira, BitMask and the second one boils down to andn dira, BitMask. So we did it in half the space (and twice the speed) and didn't have to worry about how to set flags.
Let's assume we don't have mux & Co. Then bit propagation could be done like this:
test mask, ina wc
if_c or outa, response
if_nc andn outa, response
Not exactly nice-looking but avoids jumping around the place. Now enter muxc and all we are left with is:
thank you very much for showing how it can be coded the shortest way.
I forgot to attach the additional PDF. Now you find it in posting #85 (two above)
How does this work for you?
I haven't tested it yet. But as you are an experienced programmer and there is only one type of propeller-chip
I expect that it will work for me too :-)
It took me a while to get this working but I learned a lot.
Thanks to all for the generous help provided.
This code is listed for absolute beginners, ABSOLUTE beginners.
You do not need to know anything about PASM or any other assembly languages. Just the desire to learn
I made it as simple as I could as an early program to look at and study.
I would like to know what you do not understand in this listing so I can fix it so that you can.
I tried to avoid every short hand so its a bit bulky but its for beginners
You need to look at the data sheet for the MCP 3208 to see what it requires.
Page 16 is most relevant, top diagram.
Programs runs on the development board
Wire the first 12 pins to the first 12 LEDs.
The 5K potentiometer goes on line 0 of the 3208 and across 5 volts.
Here we are learning about calling subroutines
and setting bits as we want them to be.
And using the PAR command to share variables
And using masks
And most of all how to interface to a chip like the 3208.
As always more experienced programmers are welcome to comment and criticise.
PUB null | P_Val
cognew(@generate, @P_Val) ' start new cog at "generate" and read variable at P_Val
dira[0 ..11]~~ ' all 12 lines are outputs. 12 lines needed for 1.5 bytes
repeat ' endless loop to display data
outa[0..11] := P_Val ' displays 1.5 bytes of data
DAT org 0 'sets the starting point in Cog
generate mov dira, set_dira 'sets direction of the prop pins
call #chip_sel_lo 'selects chip by pulling line low
call #Clk_lo 'START. Clock needs to be low to load data
call #Din_hi 'must start with Din high to set up 3208
call #Tog_clk 'clk hi to read data
call #Din_hi 'SINGLE DIFF Low to load
call #Tog_Clk 'toggle clock line hi then low to read in the data
call #Din_lo 'D2 Low to load input line selection sequence 000 for line 0
call #Tog_Clk 'toggle clock line hi then low to read in the data
call #Din_Lo 'D1 Low to load input line selection sequence 000 for line 0
call #Tog_Clk 'toggle clock line hi then low to read in the data
call #Din_Lo 'D0 Low to load input line selection sequence 000 for line 0
call #Tog_Clk 'toggle clock line hi then low to read in the data
call #Din_lo 'blank bit needs a clock cycle, next
call #Tog_Clk 'toggle clock line hi then low to read in the data
'next toggle is for the null bit, nothing read
call #Tog_Clk 'toggle clock line hi then low to read in the data
mov dat_red, #0 'Clear register we will read data into
mov count, #12 'Counter for number of bits we will read
do_again mov temp1, ina 'read in what is in all the input lines
andn temp1, inputmask wz 'mask off everything except Dout line. Set Z flag
if_nz add Dat_red, #1 'if value is still positive add 1 to data register
ror Dat_red, #1 'roll register right 1 bit to get ready for next bit
call #Tog_Clk 'toggle clock to get next bit ready in Dout
sub count, #1 wz 'decrement the "bits read" counter. Set Z flag
if_nz jmp #do_again 'go up and do it again if counter not 0
rol dat_red, #12 'roll back 12 bits to get data into 12 LSBits of register
mov temp, dat_red 'get data that as read
wrlong temp, par 'put it in PAR to share it as P.Val
call #Chip_Sel_Hi 'Put chip to sleep by delselecting it, for low power usage
jmp #generate 'go back to do it all again
'Subroutines
Clk_Hi mov temp, outa 'Get the OUTA register
or outa, clk_bit 'OR it with the Clock Bit
mov outa, temp 'put it back in OUTA register
Clk_Hi_ret ret
Clk_Lo mov temp, outa 'Get the OUTA register
andn temp, clk_bit 'ANDN it with the Clock Bit
mov outa, temp 'put it back in OUTA register
Clk_Lo_ret ret 'return from this subroutine
Tog_Clk call #Clk_hi 'make clokc bit high
call #clk_lo 'make clock bit low
Tog_Clk_ret ret 'return from this subroutine
Din_Hi mov temp, outa 'Get the OUTA register
or temp, din_Bit 'Make the Din high
mov outa, temp 'put it back in OUTA register
Din_Hi_ret ret 'return from this subroutine
Din_Lo mov temp, outa 'Get the OUTA register
andn temp, din_Bit 'make Din low
mov outa, temp 'put it back in OUTA register
Din_Lo_ret ret 'return from this subroutine
Chip_Sel_Hi mov temp, outa 'Get the OUTA register
or temp, chs_Bit 'Make Chip select high
mov outa, temp 'put it back in OUTA register
Chip_Sel_Hi_ret ret 'return from this subroutine
Chip_Sel_Lo mov temp, outa 'Get the OUTA register
andn temp, chs_Bit 'make chip select low
mov outa, temp 'put it back in OUTA register
Chip_Sel_Lo_ret ret 'return from this subroutine
Read_Dout mov temp, ina 'Get the INA register
Read_Dout_ret ret 'return from this subroutine
Read_Next_Bit mov temp1, ina 'Get the INA register
or temp1, inputmask 'mask all but Din bit
Read_Next_Bit_ret ret 'return from this subroutine
'Constants. This section is similar to the CON block in SPIN
Set_dira long %00001011_00000000_00000000_00000000 'Set dira byte
Chs_Bit long %00000001_00000000_00000000_00000000 'Chip select bit 24
Din_Bit long %00000010_00000000_00000000_00000000 'D in bit 25
Dout_Bit long %00000100_00000000_00000000_00000000 'D out bit 26
Clk_Bit long %00001000_00000000_00000000_00000000 'Clock bit 27
inputmask long %11111011_11111111_11111111_11111111 'mask for reading only the Dout bit
'Variables. This section is similar to the VAR block in SPIN
temp res 1 'temporary storage variable
temp1 res 1 'temporary storage variable
count res 1 'temporary storage variable
Dat_Red res 1 'temporary storage variable
'Subroutines
Clk_Hi mov temp, outa 'Get the OUTA register
or temp, clk_bit 'OR it with the Clock Bit
mov outa, temp 'put it back in OUTA register
Clk_Hi_ret ret
You should really work on your formatting. Anyway, why do you use a temporary when you work on outa, just do the bit operation (or/andn). outa is one of the safe SPRs.
Also, I think you want if_nz instead of f_nz. It still compiles because the latter is treated as a label but it's not doing what you intended. One last thing, why do you copy dat_red (a normal register) into temp (another normal register) before writing it to hub?
@Steve (Jazzed)
I did that because if I leave that line out it would not work!
Kuroneko left this line out in his earlier example and his example works!
I could not figure it out so I left it in.
@Kuroneko
I had it formatted perfect in the Prop Tool but when I post it got all screwed up.
Then I tried editing it but the edit does not stick.
I am doing something wrong but I have still to figure what it is.
Yes it was if_nz but the i got lost. I fixed it.
I thought I had to do it but I tried it like you suggested and now I know that it is not necessary.
I will edit it again after all the comments are in.
I'm learning but with me it goes very slowly.
Comments
Look, you said: "This is at least 50 times more difficult than writing in SPIN. I have to feel my way through the haze." It's not really that hard, but that is your perception because you have lots of work to do.
You are on a big learning curve. If you are not willing to dig in and CAREFULLY read the data-sheets, manuals, and tutorials discussed at the start of this thread regarding PASM, you will FAIL.
As for examples, there are literally hundreds of code examples out there to read. The OBEX and the Propeller Tool libraries offer wonderful examples. All you have to do is have a look.
Why don't you move the conversation forward by posting your broken code and let us help you learn from your mistakes? Don't spend all afternoon on something without reaching out. Hopefully your learning curve will get smaller with that. Everyone has broken code from time to time. Everyone finds ways around it or just gives up.
Regarding RES. You can use RES for uninitialized variables, but there are dangers in using it. I've already mentioned one of them below to try and save you from the grief that comes from it.
It truly amazes me that you have divined that I am planning to write a book on PASM for beginners without reading anything!
What a fantastic idea. I have read, scanned and searched more pages than you can possibly imagine.
The documentation provided by sophisticated code writers is so sparse and hard to decipher that I am left scratching my head.
Lines upon lines are left undocumented. Often comments don't explain anything to me. The posted stuff is not for beginners. No way.
My SPIN book has well over 120 pages of just SPIN code in it and each and ever line is carefully documented for beginners.
My PASM book will have over a hundred of pages of PASM code in it and every line will be understood by me and every line will
be followed by documentation that anyone can understand. There will be no short hand code that is hard to understand by beginners.
You gave me pages of hard to understand, complicated code on how to share a variable between PASM and SPIN and I
could not understand any of it. Hardly a way of explaining it to a beginner.
It was I, who after reading the manuals and data sheets, who wondered if one could not read and write the same register in the two languages.
Then...
Kuroneko showed us all how to do it in a few lines and I could understand every line. Even a dynamic demonstration of the code on the Demo board.
Fantastic. Crystal clear. No high flying confusing code.
Regards
Harprit.
Why don't you make kuroneko's code your first example of variable sharing. Then move on to a more advanced version. If you want to share more than a few variables, you'll have to store multiple pointers. How you do it is up to you.
Considering the volume of study you have claimed to have enjoyed, my example should have been easy.
code to read a pot and display the results on some LEDs.
Harprit
I think you are a little unfair on the available documentation, I think that DeSilva's tutorial is pretty helpful, there is also Potatoheads which is more digestible, I made my simple set of examples for the stuff I found the hardest at the start too: http://forums.parallax.com/showthread.php?94027-Assembly-step-by-step&p=647408 which has helped a lot of people get started. But I agree there is a space for a nice book on the subject.
Graham
As for usage, res covers uninitialised variables whereas long & Co are responsible for constants AND preset variables, e.g.
Your program will be writing a value first before it ever reads from it.
Using res will let your assembler calculate the address it will represent
but the data will not be included in the program itself, making it shorter.
Though you will not gain any cog ram, so in theory you could instead use
labelname long 0-0 , but you would make the code longer and it may also take longer time
to set up the new cog (I'm not sure if 496 longs is always transferred even if code is shorter?)
Using res, will force you to both iniate and reset the value for a loop etc, making for less buggy program.
If code it cramped I guess you could skip: mov cnt,#5
and have it set at start up of cog.
Yes! I think something like SPIN has some variance in what people might need to get it to "click" for them. Truth is, SPIN is pretty easy. Somebody can just jump in and do stuff and have some shot at success. It's pretty easy to poke around, change stuff, and watch what happens. That's what I did on the first day, and it was a total kick!
I don't think PASM shares that quality, though I personally think it's one of the most fun and easy to code assembly languages I've seen. Clean. Poking around requires some playground that's setup with strong expectations set so people know what to poke around on, and how to "see what it does". Honestly, that's a significant work right there.
I've had a work in progress for a while now, a follow on to the tutorial mentioned here. Over the few years that's been up, I've received e-mails from people saying, "I got it", or "thanks". Personally, I always thought the thing was too wordy and short on visuals. (I have found it challenging to change both, but I think I'm on a good path at present.)
That said, just look at the number of words to introduce the very basics, and I mean basics as it's really only a primer meant to kick somebody off into exploring more PASM. Given those things, it's very easy to see that boot-strapping newbies to assembly language requires a lot of context. Assembly language is basic, and very abstract in many ways.
And there are two kinds of people to write to, well maybe three, you tell me.
One is the person who has dealt with assembly before somewhat successfully. The other is the person who has no assembly language experience at all.
These are two very different user experience states to write for, which is exactly why DeSilva and I decided to break it where we did. At the time those were written, I was still coming up to speed on PASM. (Still am today, frankly --and it's a lotta fun) DeSilva had reached a nice level of mastery, and found it difficult to write for the newbie because of that. Made perfect sense for me to introduce the thing, in the hopes they could get far enough to jump into the other material out there. And the three things, including Grahams work are actually pretty good. They are just not well presented.
I don't know where you plan to go with your effort Harpit, but I would give it some serious thought as to who you are writing for and why. Then consider scope of concepts introduced and then work from there. I'm personally going to start at "has no assembly experience", and carry through solid, basic PASM programs, as I think that's probably the most useful. Really interested people will very likely have enough competency to jump in here and get at the good stuff like the rest of us do. (another book for advanced is totally needed, and something I hope to get at for Prop II, or see somebody get done for Prop II)
IMHO, the big problem people have with assembly language is the fundamental nature of it. Higher level language constructs can do lots of things for people, and one of the bigger ones is simply managing representations of things, the other being program flow and storage management. From there, one can easily have whole tasks abstracted to a simple command, and that is what makes the higher level languages work for people like they do.
In assembly land, it's all up to the programmer, and when one does not understand the very basics of how computers really do things, assembly language appears as this arcane wizardry, obtuse, cryptic. That's the challenge to be met, IMHO. Context is everything, and it's not just a matter of documenting favorable commands and workflows, like it can be for a cookbook, or higher level language introduction.
There is a third consideration too, and that is kinds of assembly language. For me, the PASM experience was favorable. It seemed to click easily enough, and it's beautiful really. I think some of that had to do with the kinds of assembly language experiences I had accumulated. There are some CPU instruction sets that are similar in concept to PASM, and there are a lot that are very different. For the "has assembly language" experience set of beginners to PASM, some relating of those concepts and establishing of common context is important, or differences in language, like "register" can really make a mess of things, doing more harm than good. I personally think this is challenging to do.
Harpit, I'm not putting this out here to compete, or discourage. My project got slowed by "that damn day job", but it is progressing, and it will get done.
I feel a fair amount of passion for PASM and the Propeller in general, and that's because the chip is cool, as are the people involved with it. Frankly, the whole scene has just been a lot of fun, and that counts for a lot.
Given that, it made perfect sense to put some lessons learned out there, with a gentle push to encourage you to take the time to, "do it right", or please don't do it, as it will do more harm than good. Really. I mean that, and I mean it in the very nicest of ways.
I wrote an article on this -- you might find it helpful as I tend to write very straightforward code.
-- http://www.parallax.com/Portals/0/Downloads/docs/cols/nv/prop/col/nvp10.pdf
Note that the code listings in the PDF have the inline comments removed because this is material that goes to the magazine which prints in a two-column format; download the code for my inline comments if the article text is not enough.
I second on what potatohead wrote.
you are taking the effort to learn PASM and writing a book for beginners. This is a big chance as you will encounter a lot of - of the same problems a beginner encounters.
The more somebody becomes an experts the more he/she is in danger to become blind for beginner-difficulties. Until he/she focuses again on these problems through practical teaching.
I would like to see before a book goes to printing that it is reviewed by beginners and by experts. By beginners to give it a last improvement about things the find still hard to understand.
By experts to catch bugs that beginners or advanced users (that you will be at this stage) do not see. After that it will be a book which is worth to make its way into the hall of fame,
because it is really easy to understand and has no bugs.
About debuggers: let's say - for a moment - the PASM-beginner is able to use the debugger. In this situation it will be a great help just singlestep through the code watching what is happening to any byte in the RAM and how the program flows
This is a great helpindeed.
Without a debugger the other possabilities of debugging is to switch on/off LEDs. Inserting code for printing some debug-output is way above the head of a beginner.
Know back to a real beginner that does not know how to use the debugger:
If you got a lot to learn about the debugger and have to do this learning through try and error because the manual about the debugger is just "three lines long"
I agree. It depends on how good and detailed the debugger manual is. Does the debugger-manual take the user by the hand and shows step by step screen-shot for screen-shot
how to use it and gives information about possible reasons why something might not work (forgot to insert debug-kernel or what ever) and how to solve it it will be easy to use
and the user will enjoy the extra-journey.
BMA is an advanced debugger with advanced possabilities and I want to emphasise: on beginners not that easy to use for beginners. IMHO PASD is easier for beginners.
The PASD-manual can be still improved. Now the question is who will do the work of the improvement?
I'm in temptation do do it. I enjoy this kind of work.very much. Writing such a manual takes much more time than writing some postings.
But I pull myself back as I know that other work that has a higher priority would suffer from that.
Maybe something inbetween. Harprit give PASD a short try and as soon as you encounter a problem using it - don't tinker around even if yiu would like to
tell me the problem and I will help. Maybe Ariba the author of PASD likes to help too.
keep the questions coming
best regards
Stefan
After a very long hiatus I'm back to re-learn CP/M and 8080 assembly, and, this time as in the past, the way in is to start the debugger (SID in this case) and fiddle with code and single-stepping.
A couple of years back I began to write emulators for two different old minicomputer CPUs, and one of the very first things I did in both projects was to write a debugger that would let me single-step through actual code. I feel that you need to _see_ the code (and there is a one-to-one connection between assembly and code, unlike with Spin or any high level language) to get a feel for it.
Steve: Thanks to the link for that BMADebugger, I wasn't aware of it.
-Tor
You have said this to me before and I accept your criticism.
My explanation of PID is intended for real beginners who will never understand the digital implementation of Kallman or any other filters.
If you read any of my books, you will see not a single equation. They are for beginners and beginners only. No complaints from beginners.
Yes there are mistakes in my books and I maintain errata on the internet. No one else seem to for their books. I handle customer support personally.
@Kuroneko:
As always thank you for you great help and comments.
@ PotatoHead:
I have read you notes for beginners. My stuff will be may times simpler than that.
I do not know enough the write the kind of stuff experience programmers can write
I will give it my best shot and will decide if I want to publish or not when I am done.
Its going to be a while
Thanks for your comments.
@JonnyMac:
Your article was helpful. Thanks
@Stephan:
I downloaded the debugger and am trying to get an understanding of how it works.
Harprit
What is the short hand for changing one and a series of bits in DIRA and OUTA in PASM
Harprit
Read about MUXC, MUXNC, MUXZ, MUXNZ, OR, ANDN, XOR etc... in the manual.
If you literally mean to change, as in to change 1s to 0s and vice versa, you would use XOR along with a mask value where a 1 bit in the mask would designate a bit that you wanted changed. If you're dealing with bits 8:0 only the mask could be a literal.
You may take offense at this, but my initial reaction when I started reading this thread was that it didn't seem like a particularly good idea to write a book about something that you're just learning about. I wouldn't want a brand new driver to write a book on driving. When I purchase a book, I tend to assume that the author knows his subject inside and out. I've been programming in PASM for about a year, and there are areas, major areas, that I haven't even touched. I visit these threads because I tend to learn new things whenever I do. And PASM is not my 1st assembly language by any means.
If you've never programmed in assembler before, it's hard for me to believe that you wil learn enough in a reasonable amount of time to do justice to your readers. Just my 10 cents worth.
And it sounded to close to Multiplication.
What is does, it assume that you did a Test or Shift etc prior
and therefore there is an answer in Z or C now.
It will take this answer (can only be 0 or 1) and set the bits to this same stage of 0 or 1.
The Mask (source field) is so you can tell what bits you want this to apply to.
The Mask can be the pin# you want to set in Outa.
MUXN, it will use a bit reversed answer of Z or C
the mux.-commands (muxz, muxnz muxc muxnc) are the short way if the number of bits that should be changed can vary.
example with just 8 bits Of course you could use operators like and andn or etc. but they would require more commands
copying actual state of f.e. outa to a temporal-used-long
manipulating the temporal-used-long with a command like "AND" with zeros to clear bits,
the command "OR" to set bits
another "OR"-command with the temporal-used-longand outa to set the bits in outa
With mux-commands you use one command to set or clear the Z-flag and then do the mux-command
The PASD-Debug-Demo-code uses the ANDN + OR-command to set or clear bits. step through this code and then modify it with mov/mux-commands to see what the commands are doing
I also attach a file describing how to use PASD as an addition to the PASD-manual
This manual-add-on is a short test if you find it understandable this way
keep the questions coming
best regards
Stefan
oops forgotto attach the PDF-file ! corrected now.
Kinda following up on what Tor said, if you want to avoid the learning curve of a debugger right now, there is still value in studying the hex code from the PropTool (produced by pressing F8). daSilva recommended this, and used values that would be easy to find. I've answered many questions this way.
They way it stands now the first example is equivalent to or dira, BitMask and the second one boils down to andn dira, BitMask. So we did it in half the space (and twice the speed) and didn't have to worry about how to set flags.
Let's assume we don't have mux & Co. Then bit propagation could be done like this: Not exactly nice-looking but avoids jumping around the place. Now enter muxc and all we are left with is: How does this work for you?
thank you very much for showing how it can be coded the shortest way.
I forgot to attach the additional PDF. Now you find it in posting #85 (two above)
I haven't tested it yet. But as you are an experienced programmer and there is only one type of propeller-chip
I expect that it will work for me too :-)
keep the improving comments coming
best regards
Stefan
Thanks to all for the generous help provided.
This code is listed for absolute beginners, ABSOLUTE beginners.
You do not need to know anything about PASM or any other assembly languages. Just the desire to learn
I made it as simple as I could as an early program to look at and study.
I would like to know what you do not understand in this listing so I can fix it so that you can.
I tried to avoid every short hand so its a bit bulky but its for beginners
You need to look at the data sheet for the MCP 3208 to see what it requires.
Page 16 is most relevant, top diagram.
Programs runs on the development board
Wire the first 12 pins to the first 12 LEDs.
The 5K potentiometer goes on line 0 of the 3208 and across 5 volts.
Here we are learning about calling subroutines
and setting bits as we want them to be.
And using the PAR command to share variables
And using masks
And most of all how to interface to a chip like the 3208.
As always more experienced programmers are welcome to comment and criticise.
Do you really need to set bits 0..11 set in Set_dira?
In this example it doesn't matter, but it is confusing.
Also, I think you want if_nz instead of f_nz. It still compiles because the latter is treated as a label but it's not doing what you intended. One last thing, why do you copy dat_red (a normal register) into temp (another normal register) before writing it to hub?
I did that because if I leave that line out it would not work!
Kuroneko left this line out in his earlier example and his example works!
I could not figure it out so I left it in.
@Kuroneko
I had it formatted perfect in the Prop Tool but when I post it got all screwed up.
Then I tried editing it but the edit does not stick.
I am doing something wrong but I have still to figure what it is.
Yes it was if_nz but the i got lost. I fixed it.
I thought I had to do it but I tried it like you suggested and now I know that it is not necessary.
I will edit it again after all the comments are in.
I'm learning but with me it goes very slowly.
Thanks all
Harprit
Odd, never had problems with this. Then again I never use those funny editor icons. I simply type the code tags and paste in between.