your code has longs and res not only behind the last PASM-command but also right inbetween the code
I don't remember the why but I surely know that all longs and all res HAVE TO BE behind the last PASM-command.
Maybe braking this rule is causing the problems.
If I would like to analyse the problem I would singlestep through the PASM-code with PASD.
keep the coding rules in mind and follow them
best regards
You have data in the middle of your code. That rarely works with any assembler unless the value at :timer just happens to be a valid instruction. You might be able to get away with moving :timer down below the ret instruction but I think putting everything at the end might be the best bet.
When you come out of the WAITCNT, the program counter is incremented and points to the memory location at :timer and fetches it and tried to execute it. At that point, your program has lost all meaning and is no longer doing what you intened the code to do.
'I would add "under no circumstances should a res command be used in the middle of a PASM program" .... blah res N must be at the end of code because it does not allocate space for the variable and will cause any longs or instructions that might come after it to have the wrong register addresses.'
A long can be anywhere in a PASM program if you follow the rules.
Everyone learns different ways, but reading is fundamental.
'I would add "under no circumstances should a res command be used in the middle of a PASM program" .... blah res N must be at the end of code because it does not allocate space for the variable and will cause any longs or instructions that might come after it to have the wrong register addresses.'
A long can be anywhere in a PASM program if you follow the rules.
Everyone learns different ways, but reading is fundamental.
...and once again, this is why you want expert commenting on the code and not beginners and near-beginners. I was close but incorrect and misleading, which is as good as WRONG at the machine code level!!
Well there is one thing wrong I learned from a posting. I used to put all my longs and res statements at the end of the code, then someone posted code that put them in the middle of methods so I started doing it. The old learn by seeing trick. What a mess. Back to the beginning. We need rules as to when you can put where.
I used to put all my longs and res statements at the end of the code, then someone posted code that put them in the middle of methods so I started doing it.
Before this gets more confusing, can you show us the code in question? There may be a perfectly valid reason for doing it like that in the posted code.
FWIW, data can be anywhere within a cog image (even in the code path as long as you make sure it doesn't affect the code flow, e.g. nop).
mov ctra, $+1 ' fetch from current +1
long mode << 23 | pin
res should be placed at the end of the cog image (there are exceptions but you don't want to go there right now). Note that if you have several cog images in the same source file it may appear as if res ends up somewhere in the middle.
Longs can be in the middle of the code but for better overview put them behind the last PASM-command.
All "res" have to be behind all PASM-commands and behind all longs that belong to a certain cog.
If you have PASM-code for more than one cog in one file - the code for each cog has to be in its own DAT-section
inside each DAT-section the rules above apply.
If you were just looking at the backround-color - in case of PASM-code for multiple cogs - this looks like longs and res are in the middle of code.
But that is not true. longs and "res" are always at the end of the belonging code-block.
Besides why do you feel so strongly that a good primary education is a prescription for NOT being able ever to discuss nuclear physics. I personally am amazed by that conclusion but there may be aspects to learning a language that are beyond me.
Harprit
I do not feel that way at all, rather that is the conclusion you have somehow arrived at. However have you noticed that nearly all primary school teachers must posess or be working towards a masters degree? That being said, I do believe that your idea of having a beginner involved in the authoring of a tutorial work has merit; however I also believe that the author should posess significant experience in both the device and underlying programming principles in order to not propagate erroneous methods and bad habits that will likely hinder the growth of the reading audience. Further there should also be significant experience in the hardware used in the presentation and examples to avoid unexpected frustrations. I am new to the prop, and you asked....
All "res" have to be behind all PASM-commands and behind all longs that belong to a certain cog.
True 99.9% of the time (so make that usually should be). There are scenarios where it's perfectly valid/reasonable to use res in the middle of the file (example VGA 1280x1024 Tile Driver). As for long placement, I'd argue that placing certain variables belonging to a specific sub-routine directly before or after said sub-routine is acceptable. Just keep them out of the way.
If you have PASM-code for more than one cog in one file - the code for each cog has to be in its own DAT-section inside each DAT-section the rules above apply.
Separate DAT sections are not necessary. Important is a valid org directive in front of the new image. Using a new DAT section obviously helps in terms of visual appearance.
I have an beginner question.
I have to split 1 byte in two nibble and send them to lcd ( 4 bit bus , 16x2 )
Can you give me your opinion about this piece of code ?I'am not sure this works
' MSB LSB
'7 6 5 4 3 2 1 0 SET
'-----------------------------------------------------------
'0 0 1 1 0 0 0 0 8 bit mode
'0 0 1 0 0 0 0 0 4 bit
'0 0 1 0 1 0 0 0 4-bits, 2-lines, 5x7
'0 0 0 0 1 0 0 0 display off, cursor off, blink off
'0 0 0 0 1 1 0 0 display on
'0 0 0 0 0 0 0 1 Clear display
'0 0 0 0 0 1 1 0 increment, no display shift
'P32........P24..........P14 P13 P12 P11 P10 P0
' En RS DB7 DB6 DB5 DB4
'0 0000000 X 000000000 X X X X X 0000000000 0 <--------- Port's map
Lcd_init
andn outa,RS
mov cmd,#$28 ' 4-bit mode - 2 line - 5x7 font.
Call #LcdDat
mov cmd,#$0C ' Display no cursor - no blink.
Call #LcdDat
mov cmd,#$06 'Automatic Increment - No Display shift.
Call #LcdDat
mov cmd,#$80 'Address DDRAM with 0 offset 80h.
Call #LcdDat
Lcd_init_ret ret
LcdDat
'MSB Data
mov t2,outa 'copy porta to temp var
mov msb,cmd 'copy cmd to msb var
ror msb,#4 'shift msb >> 4
and msb,#$F0 'msb & 0xF0
or t2,msb 'Add new bits to t2
mov outa,t2 'Set port
or outa,EN 'EN high
nop
nop
nop
nop
nop
nop
nop '-------------------> 250ns
andn outa,EN 'EN low -> Send Msb to LCD
'LSB Data
mov t2,outa 'copy portA to temp var
mov lsb,cmd 'copy cmd to msb var
and lsb,#$F0 'msb & 0xF0
or t2,lsb 'Add new bits to t2
mov outa,t2 'Set port
or outa,EN 'EN high
nop
nop
nop
nop
nop
nop
nop '-------------------> 250ns
andn outa,EN 'EN low -> Send Lsb to LCD
rdlong delay200us, #0
mov t1, cnt ' setup
add t1, delay ' first add
waitcnt t1,delay '200us
LcdDat_ret ret
msb byte
lsb byte
cmd byte
this is a thread where a tutorial about learning PASM and code-examples for this tutorial are discussed.
Anyway to get onto your question:
is this working code that you found somewhere and you ant to know how it works in detail?
or is the code above something that you have written on your own and want to know why it is working (or maybe not working)
I'm not superfamiliar with bitoperations. So if I would have to check it in detail I would use the PASD_ebugger and singelstep through the code to check if my thoughts
what the code should do is matching 100% what the code is in fact really doing.
Or if you don't want to use PASD doing the same operations in SPIN or in a excel-sheet (especially the bit-manipulations) and then compare the results with each other.
to get the 4 upper bits down a bitshift to the right (instead of bitrotating should do it)
to delete the upper 4 bits (to extract the lower 4 bit an and #$0F operation should be enough.
As all commands in PASM are 32bits rotating bits rotates the lowest 4 bits (bits 3,2,1,0 to bits 31,30,29,28)
You are "OR"-ing the bitvalues t2 and lsb/msb so the bits 31,30,29,28 get changed too and that wasn't intended.
If I understand right you are using prop-IO-pins P10-P13 as databit-bus 4 bits wide.
Then the upper and lower nibble has to be shifted to the right position in a variable so "OR"-ing with a variable holding the state of each bit from outa and then write it to outa
As a first hint do the bitmanipulations in the propellertool to get feedback on what happens
30 20 10
10987654321098765432109876543210
cmd %00000000000000000000000011010111
get rid of lower nibble
30 20 10
10987654321098765432109876543210
cmd %00000000000000000000000011010111
shift 4 bits right
30 20 10
10987654321098765432109876543210
cmd %00000000000000000000000000001101
to get it to IO-pin P10-P13
shift 10 bits left
30 20 10
XXXX
10987654321098765432109876543210
cmd %00000000000000000011010000000000
upper nibble
set all bits to zero except upper nibble
30 20 10
10987654321098765432109876543210
cmd %00000000000000000000000011010111
and %00000000000000000000000011110000
result%00000000000000000000000011010000
shift 6 bits left
30 20 10
10987654321098765432109876543210
XXXX
result%00000000000000000011010000000000
Mazzini,
Here is what it is doing. (personally, I have just mastered the MUXes and they are powerful!!!)
The init is pretty straightforward, as the init routine simply sets the pin designated as RS to command mode. After that it repeats the same call to DAT with the values passed in the command variable. The LcdDat routine has two halves where the same thing also is repeated twice, once for each nibble.
Anyway, the outa register is preserved for manipulation. The command is then copied to a working variable and shifted right 4 places to get the high nibble into position for bits 0-3. The mask I am not so sure is correct. I would not of habit do the mask this way because the immediate bits leave the upper bits of msb unchanged and you could introduce problems later in more complex situations. Better to create a long of $00_00_00_0F for bits 0-3 being command / data lines to the lcd device, same for the dira register if needed when you set your I/O direction. The zeros will be used to make sure there are no inadvertent 1s left in bits 31-4 that could cause mis-setting of outa bits when the msb is or'd with the saved outa prior to clocking with EN. En is raised high and then after a delay, low to clock the value into the LCD. Rinse and repeat for the LSB. You could use this method to shift any number to get the msb/lsb to the pins you have chosen to tie the device to. It looks like the author was expecting to use bits 4-7 from the use of the $F0 mask, though I am not so sure of the match up of the right shift and the original mask used. as to the listed delay times, that would depend entirely on the clock frequency used. I would guess that the clock frequency here was about 16Mhz based on 250ns/NOP. Simply clone this same routine with R/S set to 1 for the data to be displayed.
To use the pin out shown, set the mask $00_00_1E_00 (easier if on 4 bit boundaries for hex) and you will need to create this mask variable. The immediate instructions will not help you as the 1E00 to mask the bits will be out of range (max $1ff, 9bits) unless you took the rather circuitous route of shifting cmd/data nibbles to bits 0-3, masking them and then carefully shifting to the appropriate pins prior to or'ing with outa. ick.... There is a downside to rip and strip, and that is being able to see what the authors hardware setup was when the code was written. As mentioned above I suspect he was using either bits 0-3 from the right shift used or 4-7 from the mask
Hope this helps,
Frank
Sorry if it seems verbose, to many years as a technical instructor. Enjoy your time on the forum. Some seriously good people share here.
@Stephen, great post on using the editor to work through bit ops.
Edit: Prop tool is good for this because it's got real overwrite mode, and it formats in ways favorable to these kinds of activities. I use it all the time for basic ASCII art too, which has similar feature requirements.
I have been writing some assembly lately and also following this thread with great interest.
Assembly is still full of many mysteries to me. For instance, the difference between 'mylabel' and ':mylabel'. I wasn't even sure there was a difference until I added a new label in some code and it stopped compiling. A search for ":" in the instruction manual revealed a one line entry. However, that was the manual from a few years ago, and the same manual from the latest version has a full page explaining what ":" labels are and has "New" next to this page.
I read through this new manual and there are a lot more "New" sections and so I'd suggest that anyone trying to learn assembly look at getting the latest download.
I've then gone off on a tangent thinking about why assembly is confusing. To me, it is things like : and # and what special meanings these have. It is also the structure of assembly, and I find myself using certain constructs over and over. For instance
cmp myvariable,othervariable wz
if_nz jmp #label
some instructions
label ' jump to here if not true
If "some instructions" extends to a page of instructions, the overall structure tends to get lost.
I was thinking that maybe that could be simplified into a higher language construct - eg in a Basic syntax,
if myvariable = othervariable then
some code
endif
and in a C type of syntax
if (myvariable == othervariable)
{
some code
}
and there is a spin type of syntax too.
I am thinking of some sort of pre-compiler that takes a hybrid higher level language and turns it into pasm before running it through the pasm compiler.
One can think of some other constructs that come up over and over in assembly and which can be reverse translated into a higher level language.
In the case of "if", there are the four combinations of if_z, if_nz, if_c and if_nc.
Then there are simple loops. There are loops where you set a variable to zero and count up until it equals something. These are loops with jmp instructions. And there are loops where you set a variable to a value and then count down to zero, and these are djnz loops.
Each of these can be reverse translated into a higher level basic/c/spin type syntax that to my eyes looks easier to read.
Such a higher level language is not going to be C or Basic or Spin though. Scattered through the code will be assembly instructions that make sense to leave them as they are. But maybe it might look more familiar to write "a = b" or "a :=b" than mov a,b.
I've got a few more ideas, but in general the aim would be to have a hybrid pasm/high level language where it compiles into the most efficient pasm code one can write.
Yeah, I have noticed some new (good) things in the manual as well. I keep it open on another desktop (inveterate, nah.... incorrigible Xnix user) What I wish it had following instructions would be more examples of usage. Kinda a rip-off of the unix man pages. Truth tables are helpful, but an example of usage goes a long way too.
C and higher level languages can simplify some things through abstraction at a price. Also there is the issue of portability between platforms, but how often will anyone be porting prop to pic? Would love a good loaded macro assembler. Wonder if anyone has done a cross compiler w/ GCC yet for the prop?
Frank. There is a gcc cross compiler being written as we speak. It already generates PASM for in COG execution and will also target LMM PASM. Have a look for threads about it on the Parallax Semiconductor forum.
Thanks so much to all for long answers
Sry if this is the wrong place, I will create a new one in 15 min.
from this link I tried to translate the code in pasm http://www.8051projects.net/lcd-interfacing/lcd-4-bit-programming.php
My goal was work on byte data afterward or'in the prop port so that I don't overwrite the whole port
Here is my code for a 2x16 display from my book on Spin for beginners. I am in the process of converting it to PASM and will post that as soon as I am done. This is in 8 bit mode.
{{Spin code for 2 x 16 LCD. Harprit Sandhu)}}
CON
_CLKMODE=XTAL1 + PLL16X 'The system clock spec
_XINFREQ = 5_000_000 'the crystal frequency
RegSelect = 18
ReadWrite = 17
Enable = 16
DataBit0 = 15
DataBit7 = 8
high =1 'define the High state
low =0 'define the Low state
{{
Defining high and low states will allow us to invert these when we use
buffers to amplify the output from the prop chip. We will then make
low=1 and high=0 thus inverting all the values throughout the program.
I am NOT using a buffer.
}}
PUB Go
DIRA[DataBit7..DataBit0]:=%11111111 'the lines for the LCD are outputs
DIRA[RegSelect] := High 'the lines for the LCD are outputs
DIRA[ReadWrite] := High 'the lines for the LCD are outputs
DIRA[Enable] := High 'the lines for the LCD are outputs
INITIALIZE_LCD 'initialize the LCD
waitcnt(clkfreq/2+cnt) 'wait for LCD to start up
repeat 'this is a parking loop to keep the system
repeat 4 'print 4 'A's
SEND_CHAR ("A")
repeat 4 'print 4 'b's
SEND_CHAR ("b")
POSITION (1,2) 'move to POSITION: line 2, space 1
repeat 4 'print 4 'C's
SEND_CHAR ("C")
repeat 4 'print 4 'd's
SEND_CHAR ("d")
waitcnt(clkfreq/20+cnt) 'wait for LCD to start up
CLEAR 'clear the LCD
PRI INITIALIZE_LCD 'The addresses and data used here are
waitcnt(clkfreq/2+cnt) 'specified in the Hitachi data sheet for
'display. YOU MUST CHECK THIS FOR YOURSELF
OUTA[RegSelect] := Low 'these three lines are specified to write
OUTA[ReadWrite] := Low 'the initial set up bits for the LCD
OUTA[Enable] := Low 'See Hitachi HD44780 data sheet
'display. YOU MUST CHECK THIS FOR YOURSELF.
SEND_INSTRUCTION (%0011_0000) 'Send 1st
waitcnt(394_000+cnt) 'wait
SEND_INSTRUCTION (%0011_0000) 'Send 2nd
waitcnt(9600+cnt) 'wait
SEND_INSTRUCTION (%0011_0000) 'Send 3rd
waitcnt(96_000+cnt) 'wait
SEND_INSTRUCTION (%0011_1000) 'Sets DL=8 bits, N=2 lines, F=5x7 font
SEND_INSTRUCTION (%0000_1111) 'Display on, Cursor on, Blink on
SEND_INSTRUCTION (%0000_0001) 'clear LCD
SEND_INSTRUCTION (%0000_0110) 'Move Cursor, Do not shift display
PUB CLEAR 'Clear the LCD display and go home
SEND_INSTRUCTION (%0000_0001)
PUB POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION 'Pos crsr
'HOR_POSITION : Horizontal Position : 1 to 16
'LINE_NUMBER : Line Number : 1 or 2
CHAR_LOCATION := (HOR_POSITION-1) * 64 'figure location
CHAR_LOCATION += (LINE_NUMBER-1) + 128 'figure location
SEND_INSTRUCTION (CHAR_LOCATION) 'send the instr to position cursor
PUB SEND_CHAR (DISPLAY_DATA) 'set up for writing to the display
CHECK_BUSY 'wait for busy bit to clear before sending
OUTA[ReadWrite] := Low 'Set up to read busy bit
OUTA[RegSelect] := High 'Set up to read busy bit
OUTA[Enable] := High 'Set up to toggle bit H>L
OUTA[DataBit7..DataBit0] := DISPLAY_DATA 'Ready to SEND data in
OUTA[Enable] := Low 'Toggle the bit H>L
PUB CHECK_BUSY | BUSY_BIT 'routine to check busy bit
OUTA[ReadWrite] := High 'Set to read the busy bit
OUTA[RegSelect] := Low 'Set to read the busy bit
DIRA[DataBit7..DataBit0] := %0000_0000 'Set the entire port to input
REPEAT 'Keep doing it till clear
OUTA[Enable] := High 'set to 1 to get ready to toggle H>L bit
BUSY_BIT := INA[DataBit7] 'the busy bit is bit 7 of the byte read
OUTA[Enable] := Low 'make the enable bit go low for H>L toggle
WHILE (BUSY_BIT == 1) 'do it as long as the busy bit is 1
DIRA[DataBit7..DataBit0] := %1111_1111 'set the port back to outputs
PUB SEND_INSTRUCTION (DISPLAY_DATA) 'set up for writing instructions
CHECK_BUSY 'wait for busy bit to clear before sending
OUTA[ReadWrite] := Low 'Set up to read busy bit
OUTA[RegSelect] := Low 'Set up to read busy bit
OUTA[Enable] := High 'Set up to toggle bit H>L
OUTA[DataBit7..DataBit0] := DISPLAY_DATA 'Ready to READ data in
OUTA[Enable] := Low 'Toggle the bit H>L
First place to look if you don't just want to start from scratch...
OBEX OBEX OBEX.
There are at least 20 LCD drivers of various types and levels of skill and documentation. There are 8 bit and 4 bit parallel drivers, as well as reduced pin count serial drivers. Also a good spot for just about anything else you may need.
MIT license, a beautiful thing!!!!!
Frank
I have placed a 3 pin serial spin driver there as well. (an early learning project, so it could probably be tightened up a bit)
First place to look if you don't just want to start from scratch...
OBEX OBEX OBEX.
There are at least 20 LCD drivers of various types and levels of skill and documentation. There are 8 bit and 4 bit parallel drivers, as well as reduced pin count serial drivers. Also a good spot for just about anything else you may need.
MIT license, a beautiful thing!!!!!
Frank
I have placed a 3 pin serial spin driver there as well. (an early learning project, so it could probably be tightened up a bit)
Yes you are right , obex are great work and need time to build them and it is free
I will search one in pasm
I think the best examples for beginners to learn from are the spin/pasm programs that come with the Propeller tool. They are all written by proffesionals so as a beginner you know they are garaunteed to work so you learn spin/pasm by figuring out how to use them.
Last thing for the night....
A debug/devel trick beginners can use until they master a debugger:
Instrument the heck out of your code. Echo out significant results to the terminal or add "I am here" messages into the flow of your code. Sort of like where is Waldo except Waldo is saying "here I am". Write out input values and results as you go along. Test as you proceed and then comment them out as they are no longer needed. You could recycle the monitoring variables for further testing or leave commented in place in case you want to do some regression testing if/when something breaks. May not be best for time critical paths, but so far has served me well in shared memory and clock gen for my curve tracer project. Must.........master...............counters.........next
Most children, all over the world, learn a language, even unwritten languages, without meeting any one with a BA and MA or a PhD. Linguists tell us that by the time they are conversant they know about 500 words. In these words they can express most everything they need to, for day to day living. At most total immersion language schools, they try to teach you these 500 words under pressure. Its hell but I understand that you learn the language fast. The US Army once used to boast that they could teach you Russian in a week at their Monterrey total immersion school.
Beginners in PASM don't need any revelations from experts. They need a gentle introduction to what the language is all about. Leave off all the stuff they can pick up on their own later. Just the basics. Without all the scare tactics and know it all bravado.
My personal take on it is that some of the posters on this forum are bent out of shape because I have the nerve to write a book on something I know absolutely nothing about. As I have admitted, I knew absolutely nothing about all this 6 weeks ago and not much now. Others have been most gracious and kind in providing both help and encouragement.
The only thing we can go by is the record. My book on SPIN is panned by the experts and loved by novices. It has a few mistakes in it (panned and how by some) that I have corrected on my web site. So lets concentrate on the job and hand and see what I come up with. If nothing it will be a sincere effort. Lots and lots of explaining and commented code. Example code for most PASM instructions that beginners need to be familiar with. Its about those 500 words after all.
Rather more than what all the critics have come up with in a book for beginners.
To be a good pasm programmer, it's not about patching others peoples obex code.
It's to learn to think in a binary way, to really understand what is going on.
1st thing that got me a little confused when I looked at sample code was.
The underscores in large numbers, example %11_0000_11
Why are they there, and sometimes they are not evenly spaced.
Answer: They are just for your eyes, the assembler skips the underscores.
2nd, the |<
Answer, its single bit version of <<
for example: |<6 (= %1<<6) the assembler will create a number that is %1000000
3rd, the use of shadow registers as a trick to save on memory.
example: mov CNT,CNT
Why would you need to copy CNT to itself?
It turns out that right field (source) and left field(destination) have two different memory locations.
That some special registers are called Write or Read Only registers,
when it's actually more about right (source) and left (destination) versions.
I don't think anyone is calling your sincerity or motivation into question.
To use your language analogy, true that a 4 year old can generally speak their native language well enough for day to day functioning but if I want to learn their language, I won't seek that 4 year old to teach me, I will teach a more experienced with more exposure to the language and the world of speech. While the 4 year old may teach me the word "way" in their context, that 4 year old is going to (hopefully) learn the difference between way, weigh and whey at some point in the future as their education progresses....and break any bad habits associated with misuse. I don't want to for the bad habits in the beginning and then relearn the correct way as my PASM experience grows. I'd rather learn the correct way from the start.
I don't see scare tactics or bravado in any of the "expert contributions. Possible some frustration with repeating themselves, possibly some lack of teaching skills and patience (I'm guilty of this - I would NEVER want myself as a teacher in any subject I have significant knowledge in!). Tutorial writing and teaching in general are great arts that many people do not possess (guilty as charged). It is hard to remember the things you did when learning, the things that didn't click and the things that you no longer see because you are deeply immersed in the subject. The secret is for some intermediary to be able to come along and take that expert wisdom, break it down and present it in learn-able pieces (often presenting it in different, multiple ways) so the reader/learner can understand and figure out how to synthesize the new information. This is not an easy task and I commend you in taking it on.
The other hard part is for the writer to avoid teaching bad habits or "not quite correct" things that will need to be relearned later. For a child learning a language, hopefully these good habits and expanded skills are taught in school. For someone that is trying to learn PASM to enjoy or be quickly productive, any bad or misleading information is a disservice.
I sincerely don't believe the "critics" as you have labeled some are being critical to be mean, spiteful or to express jealously at your writing a book. I think they are trying to be helpful so you can create the best work possible and teach people PASM (often a difficult subject for even an experienced programmer without assembler exposure) so those people can avoid any traps or frustration or well-intended but incorrect information.
Since you have placed yourself into this role as the intermediary or translator between those knowing PASM and those wanting to learn PASM, you need to understand your reader, where they are coming from and what knowledge you expect them to have (and fill any missing gaps via appendices or introductory chapters) and you also need to be at a level in your PASM knowledge where you can interpret and synthesize the information and tips provided by experts into learn-able lessons and examples.
"People learn differently" can also be applied to "people teach differently".....based on your background and experience, you know both sides of the coin well!
I don't expect my 3rd grader's teacher to be able to teach the theory and proof behind division and multiplication but I do expect the kid to come home an know that 1/10 is smaller than 1/5 and 0 times anything is 0 and not leave me a not that she's playing at a "frends" house! To me, those are basics and can't be put off until later when she has more experience.
Keep up your admirable work, be ready for many rewrites and reorganizations and try to remember that the critics are really trying to help.....they hang around here to help people and don't want to correct any bad habits you may publish!
Sorry folks but I had more problems than I expected with the 2 x 16 display. Converting to PASM can get tricky. I got it working now but I'm still getting some garbage on the screen. Should sort it out soon and then I will post.
Comments
your code has longs and res not only behind the last PASM-command but also right inbetween the code
I don't remember the why but I surely know that all longs and all res HAVE TO BE behind the last PASM-command.
Maybe braking this rule is causing the problems.
If I would like to analyse the problem I would singlestep through the PASM-code with PASD.
keep the coding rules in mind and follow them
best regards
Stefan
When you come out of the WAITCNT, the program counter is incremented and points to the memory location at :timer and fetches it and tried to execute it. At that point, your program has lost all meaning and is no longer doing what you intened the code to do.
'I would add "under no circumstances should a res command be used in the middle of a PASM program" .... blah res N must be at the end of code because it does not allocate space for the variable and will cause any longs or instructions that might come after it to have the wrong register addresses.'
A long can be anywhere in a PASM program if you follow the rules.
Everyone learns different ways, but reading is fundamental.
...and once again, this is why you want expert commenting on the code and not beginners and near-beginners. I was close but incorrect and misleading, which is as good as WRONG at the machine code level!!
Harprit.
FWIW, data can be anywhere within a cog image (even in the code path as long as you make sure it doesn't affect the code flow, e.g. nop). res should be placed at the end of the cog image (there are exceptions but you don't want to go there right now). Note that if you have several cog images in the same source file it may appear as if res ends up somewhere in the middle.
Can the expert please re-check this:
Longs can be in the middle of the code but for better overview put them behind the last PASM-command.
All "res" have to be behind all PASM-commands and behind all longs that belong to a certain cog.
If you have PASM-code for more than one cog in one file - the code for each cog has to be in its own DAT-section
inside each DAT-section the rules above apply.
If you were just looking at the backround-color - in case of PASM-code for multiple cogs - this looks like longs and res are in the middle of code.
But that is not true. longs and "res" are always at the end of the belonging code-block.
keep the questions coming
best regards
Stefan
I do not feel that way at all, rather that is the conclusion you have somehow arrived at. However have you noticed that nearly all primary school teachers must posess or be working towards a masters degree? That being said, I do believe that your idea of having a beginner involved in the authoring of a tutorial work has merit; however I also believe that the author should posess significant experience in both the device and underlying programming principles in order to not propagate erroneous methods and bad habits that will likely hinder the growth of the reading audience. Further there should also be significant experience in the hardware used in the presentation and examples to avoid unexpected frustrations. I am new to the prop, and you asked....
Frank
Separate DAT sections are not necessary. Important is a valid org directive in front of the new image. Using a new DAT section obviously helps in terms of visual appearance.
I have an beginner question.
I have to split 1 byte in two nibble and send them to lcd ( 4 bit bus , 16x2 )
Can you give me your opinion about this piece of code ?I'am not sure this works
Thanks in advance
this is a thread where a tutorial about learning PASM and code-examples for this tutorial are discussed.
Anyway to get onto your question:
is this working code that you found somewhere and you ant to know how it works in detail?
or is the code above something that you have written on your own and want to know why it is working (or maybe not working)
I'm not superfamiliar with bitoperations. So if I would have to check it in detail I would use the PASD_ebugger and singelstep through the code to check if my thoughts
what the code should do is matching 100% what the code is in fact really doing.
Or if you don't want to use PASD doing the same operations in SPIN or in a excel-sheet (especially the bit-manipulations) and then compare the results with each other.
to get the 4 upper bits down a bitshift to the right (instead of bitrotating should do it)
to delete the upper 4 bits (to extract the lower 4 bit an and #$0F operation should be enough.
As all commands in PASM are 32bits rotating bits rotates the lowest 4 bits (bits 3,2,1,0 to bits 31,30,29,28)
You are "OR"-ing the bitvalues t2 and lsb/msb so the bits 31,30,29,28 get changed too and that wasn't intended.
If I understand right you are using prop-IO-pins P10-P13 as databit-bus 4 bits wide.
Then the upper and lower nibble has to be shifted to the right position in a variable so "OR"-ing with a variable holding the state of each bit from outa and then write it to outa
As a first hint do the bitmanipulations in the propellertool to get feedback on what happens
keep the questions coming
best regards
Stefan
Here is what it is doing. (personally, I have just mastered the MUXes and they are powerful!!!)
The init is pretty straightforward, as the init routine simply sets the pin designated as RS to command mode. After that it repeats the same call to DAT with the values passed in the command variable. The LcdDat routine has two halves where the same thing also is repeated twice, once for each nibble.
Anyway, the outa register is preserved for manipulation. The command is then copied to a working variable and shifted right 4 places to get the high nibble into position for bits 0-3. The mask I am not so sure is correct. I would not of habit do the mask this way because the immediate bits leave the upper bits of msb unchanged and you could introduce problems later in more complex situations. Better to create a long of $00_00_00_0F for bits 0-3 being command / data lines to the lcd device, same for the dira register if needed when you set your I/O direction. The zeros will be used to make sure there are no inadvertent 1s left in bits 31-4 that could cause mis-setting of outa bits when the msb is or'd with the saved outa prior to clocking with EN. En is raised high and then after a delay, low to clock the value into the LCD. Rinse and repeat for the LSB. You could use this method to shift any number to get the msb/lsb to the pins you have chosen to tie the device to. It looks like the author was expecting to use bits 4-7 from the use of the $F0 mask, though I am not so sure of the match up of the right shift and the original mask used. as to the listed delay times, that would depend entirely on the clock frequency used. I would guess that the clock frequency here was about 16Mhz based on 250ns/NOP. Simply clone this same routine with R/S set to 1 for the data to be displayed.
To use the pin out shown, set the mask $00_00_1E_00 (easier if on 4 bit boundaries for hex) and you will need to create this mask variable. The immediate instructions will not help you as the 1E00 to mask the bits will be out of range (max $1ff, 9bits) unless you took the rather circuitous route of shifting cmd/data nibbles to bits 0-3, masking them and then carefully shifting to the appropriate pins prior to or'ing with outa. ick.... There is a downside to rip and strip, and that is being able to see what the authors hardware setup was when the code was written. As mentioned above I suspect he was using either bits 0-3 from the right shift used or 4-7 from the mask
Hope this helps,
Frank
Sorry if it seems verbose, to many years as a technical instructor. Enjoy your time on the forum. Some seriously good people share here.
Edit: Prop tool is good for this because it's got real overwrite mode, and it formats in ways favorable to these kinds of activities. I use it all the time for basic ASCII art too, which has similar feature requirements.
I'm adding that to my beginner stuff.
Assembly is still full of many mysteries to me. For instance, the difference between 'mylabel' and ':mylabel'. I wasn't even sure there was a difference until I added a new label in some code and it stopped compiling. A search for ":" in the instruction manual revealed a one line entry. However, that was the manual from a few years ago, and the same manual from the latest version has a full page explaining what ":" labels are and has "New" next to this page.
I read through this new manual and there are a lot more "New" sections and so I'd suggest that anyone trying to learn assembly look at getting the latest download.
I've then gone off on a tangent thinking about why assembly is confusing. To me, it is things like : and # and what special meanings these have. It is also the structure of assembly, and I find myself using certain constructs over and over. For instance
If "some instructions" extends to a page of instructions, the overall structure tends to get lost.
I was thinking that maybe that could be simplified into a higher language construct - eg in a Basic syntax,
and in a C type of syntax
and there is a spin type of syntax too.
I am thinking of some sort of pre-compiler that takes a hybrid higher level language and turns it into pasm before running it through the pasm compiler.
One can think of some other constructs that come up over and over in assembly and which can be reverse translated into a higher level language.
In the case of "if", there are the four combinations of if_z, if_nz, if_c and if_nc.
Then there are simple loops. There are loops where you set a variable to zero and count up until it equals something. These are loops with jmp instructions. And there are loops where you set a variable to a value and then count down to zero, and these are djnz loops.
Each of these can be reverse translated into a higher level basic/c/spin type syntax that to my eyes looks easier to read.
Such a higher level language is not going to be C or Basic or Spin though. Scattered through the code will be assembly instructions that make sense to leave them as they are. But maybe it might look more familiar to write "a = b" or "a :=b" than mov a,b.
I've got a few more ideas, but in general the aim would be to have a hybrid pasm/high level language where it compiles into the most efficient pasm code one can write.
I shall ponder this some more...
Yeah, I have noticed some new (good) things in the manual as well. I keep it open on another desktop (inveterate, nah.... incorrigible Xnix user) What I wish it had following instructions would be more examples of usage. Kinda a rip-off of the unix man pages. Truth tables are helpful, but an example of usage goes a long way too.
C and higher level languages can simplify some things through abstraction at a price. Also there is the issue of portability between platforms, but how often will anyone be porting prop to pic? Would love a good loaded macro assembler. Wonder if anyone has done a cross compiler w/ GCC yet for the prop?
Frank
Thanks so much to all for long answers
Sry if this is the wrong place, I will create a new one in 15 min.
from this link I tried to translate the code in pasm http://www.8051projects.net/lcd-interfacing/lcd-4-bit-programming.php
My goal was work on byte data afterward or'in the prop port so that I don't overwrite the whole port
see you next topic if you agree
Here is my code for a 2x16 display from my book on Spin for beginners. I am in the process of converting it to PASM and will post that as soon as I am done. This is in 8 bit mode. Harprit
First place to look if you don't just want to start from scratch...
OBEX OBEX OBEX.
There are at least 20 LCD drivers of various types and levels of skill and documentation. There are 8 bit and 4 bit parallel drivers, as well as reduced pin count serial drivers. Also a good spot for just about anything else you may need.
MIT license, a beautiful thing!!!!!
Frank
I have placed a 3 pin serial spin driver there as well. (an early learning project, so it could probably be tightened up a bit)
Good idea I will compare it to my code in order to learning some stuff of Pasm Thanks so much:D
Congratulation for your book
Yes you are right , obex are great work and need time to build them and it is free
I will search one in pasm
A debug/devel trick beginners can use until they master a debugger:
Instrument the heck out of your code. Echo out significant results to the terminal or add "I am here" messages into the flow of your code. Sort of like where is Waldo except Waldo is saying "here I am". Write out input values and results as you go along. Test as you proceed and then comment them out as they are no longer needed. You could recycle the monitoring variables for further testing or leave commented in place in case you want to do some regression testing if/when something breaks. May not be best for time critical paths, but so far has served me well in shared memory and clock gen for my curve tracer project. Must.........master...............counters.........next
Frank
Most children, all over the world, learn a language, even unwritten languages, without meeting any one with a BA and MA or a PhD. Linguists tell us that by the time they are conversant they know about 500 words. In these words they can express most everything they need to, for day to day living. At most total immersion language schools, they try to teach you these 500 words under pressure. Its hell but I understand that you learn the language fast. The US Army once used to boast that they could teach you Russian in a week at their Monterrey total immersion school.
Beginners in PASM don't need any revelations from experts. They need a gentle introduction to what the language is all about. Leave off all the stuff they can pick up on their own later. Just the basics. Without all the scare tactics and know it all bravado.
My personal take on it is that some of the posters on this forum are bent out of shape because I have the nerve to write a book on something I know absolutely nothing about. As I have admitted, I knew absolutely nothing about all this 6 weeks ago and not much now. Others have been most gracious and kind in providing both help and encouragement.
The only thing we can go by is the record. My book on SPIN is panned by the experts and loved by novices. It has a few mistakes in it (panned and how by some) that I have corrected on my web site. So lets concentrate on the job and hand and see what I come up with. If nothing it will be a sincere effort. Lots and lots of explaining and commented code. Example code for most PASM instructions that beginners need to be familiar with. Its about those 500 words after all.
Rather more than what all the critics have come up with in a book for beginners.
Regards
H
It's to learn to think in a binary way, to really understand what is going on.
1st thing that got me a little confused when I looked at sample code was.
The underscores in large numbers, example %11_0000_11
Why are they there, and sometimes they are not evenly spaced.
Answer: They are just for your eyes, the assembler skips the underscores.
2nd, the |<
Answer, its single bit version of <<
for example: |<6 (= %1<<6) the assembler will create a number that is %1000000
3rd, the use of shadow registers as a trick to save on memory.
example: mov CNT,CNT
Why would you need to copy CNT to itself?
It turns out that right field (source) and left field(destination) have two different memory locations.
That some special registers are called Write or Read Only registers,
when it's actually more about right (source) and left (destination) versions.
I don't think anyone is calling your sincerity or motivation into question.
To use your language analogy, true that a 4 year old can generally speak their native language well enough for day to day functioning but if I want to learn their language, I won't seek that 4 year old to teach me, I will teach a more experienced with more exposure to the language and the world of speech. While the 4 year old may teach me the word "way" in their context, that 4 year old is going to (hopefully) learn the difference between way, weigh and whey at some point in the future as their education progresses....and break any bad habits associated with misuse. I don't want to for the bad habits in the beginning and then relearn the correct way as my PASM experience grows. I'd rather learn the correct way from the start.
I don't see scare tactics or bravado in any of the "expert contributions. Possible some frustration with repeating themselves, possibly some lack of teaching skills and patience (I'm guilty of this - I would NEVER want myself as a teacher in any subject I have significant knowledge in!). Tutorial writing and teaching in general are great arts that many people do not possess (guilty as charged). It is hard to remember the things you did when learning, the things that didn't click and the things that you no longer see because you are deeply immersed in the subject. The secret is for some intermediary to be able to come along and take that expert wisdom, break it down and present it in learn-able pieces (often presenting it in different, multiple ways) so the reader/learner can understand and figure out how to synthesize the new information. This is not an easy task and I commend you in taking it on.
The other hard part is for the writer to avoid teaching bad habits or "not quite correct" things that will need to be relearned later. For a child learning a language, hopefully these good habits and expanded skills are taught in school. For someone that is trying to learn PASM to enjoy or be quickly productive, any bad or misleading information is a disservice.
I sincerely don't believe the "critics" as you have labeled some are being critical to be mean, spiteful or to express jealously at your writing a book. I think they are trying to be helpful so you can create the best work possible and teach people PASM (often a difficult subject for even an experienced programmer without assembler exposure) so those people can avoid any traps or frustration or well-intended but incorrect information.
Since you have placed yourself into this role as the intermediary or translator between those knowing PASM and those wanting to learn PASM, you need to understand your reader, where they are coming from and what knowledge you expect them to have (and fill any missing gaps via appendices or introductory chapters) and you also need to be at a level in your PASM knowledge where you can interpret and synthesize the information and tips provided by experts into learn-able lessons and examples.
"People learn differently" can also be applied to "people teach differently".....based on your background and experience, you know both sides of the coin well!
I don't expect my 3rd grader's teacher to be able to teach the theory and proof behind division and multiplication but I do expect the kid to come home an know that 1/10 is smaller than 1/5 and 0 times anything is 0 and not leave me a not that she's playing at a "frends" house! To me, those are basics and can't be put off until later when she has more experience.
Keep up your admirable work, be ready for many rewrites and reorganizations and try to remember that the critics are really trying to help.....they hang around here to help people and don't want to correct any bad habits you may publish!
I'll ditto Jazzed
H
Thanks for your patience.
Harprit
Assume the pin is pulled high
Is it enough to debounce it with
Wait for pin to go low
wait for pin to go high
It seems to work OK but I'm bit unsure if this is foolproof
H