Shop OBEX P1 Docs P2 Docs Learn Events
Whats the best way to send 2, 4 bit values to a parallax parallel LCD in SX/B — Parallax Forums

Whats the best way to send 2, 4 bit values to a parallax parallel LCD in SX/B

Capt. QuirkCapt. Quirk Posts: 872
edited 2006-12-25 09:09 in General Discussion
I am trying to find a way to send 4 bit MSB & LSB data to my parallel LCD module·and do it more efficient then the code I found by "Basme". He did it with each bit sent on an individual pin. Most of the examples available were 4 bit, BS2 code. The BS2 code used the HIGHNIB & LOWNIB and produced shorter code. I found several recent examples using the new SX\B __PARAM1 and related functions, but none of those examples worked with the parallel LCD.
·
·I am trying to do all my projects with an SX now, instead of a BS2 or BS2SX. And so I trying to learn SX\B and learn how to program it as efficient as possible and then move on to assembly. But for right now I only have an SX Blitz and so SX\B is a must.

Comments

  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2006-12-20 19:20
    Bill,

    It is not clear to me (and perhaps to others) what you are using as your measure of efficiency. Possibilities include clock cycles, the number of instructions, the amount of memory used or even the number of SX/B statements required.

    You will need to think of SX/B efficiency differently than how you may tend to think of it in relation to the Basic Stamps. SX/B instructions might translate into anywhere from one to many assembly statements. With the Basic Stamps, each instruction basically translates into one 'token' with its associated variables.

    Until you become familiar with SX assembly I would urge you not to worry too much about efficiency. (It sounds strange, I know. Perhaps others will disagree with me.) When you write an SX/B program, take at look at its assembly source listing (CTRL-L). This will help you the most. You will soon learn where the greatest improvements in efficiency can be made. Some functions, such as SERIN and SEROUT, generate large blocks of assembly code each time they are encountered in your program. So it is a more efficient use of code space to include such functions only once in your program. Just call them as a subroutine each time you need them. Other functions perform initialization steps which might only be needed once. If you split those instructions into two separate assembly sections you might gain some efficiency in terms of clock cycles for your program. You will have to decide if it is worth the effort.

    Honestly, the SX operates so fast that unless you are critically short on your timing in a certain section of code or you find yourself running out of memory, you really will not need to focus on efficiency as much as you might think.



    Comments on Your Code:

    Basme's code outputs the high nibble first. Your code sections do not. Try changing your second code segment to look like this:
    Send_Inst:
      LOW RS                
      RB = Inst             ' Sends High nibble first  
      PULSOUT E, 3          '         
      TEMP1 = Inst << 4     ' Creates an 8 bit "LOWNIBBLE" variable by 
                            ' sending 0000 zeros on pins 0 to 3
      RB = Temp1            ' Outputs the LSB low nibble and LSB values 
      'RB = Inst            ' are sent to ground                        
      PULSOUT E,3                           
      GOSUB Wait_Busyflag
      HIGH RS                                      
      RETURN
    



    With everything else being equal, it does appear that your second code section uses four fewer assembly code primitives and thus runs four clock cycles faster than the section of Basme's code you reference. Does that help?

    - Sparks
  • JonnyMacJonnyMac Posts: 9,444
    edited 2006-12-20 19:30
    To get the low nib from a byte you need to mask the byte with $0F to strip off the upper bits. To get the high nib (into the low nib position), use SWAP, then mask the value.

    If all of your LCD connctions are on the same port, RB for example, then you need to put the current state of the control lines (E, RS, RW) into the byte that you'll write to the port -- all of this stuff takes place "behind" the scenes in the BASIC Stamp when writing to NIB ports (e.g., OUTA, OUTB, etc.) because the hardware underneath only supports 8-bit ports.

    This is off the top of my head, but may be helpful. It shows, though, that copying the four bits -- one at a time -- may actually be the most efficient.

    LCD_OUT:
      lcdCtrl = char & $F0
      lcdCtrl.1 = E
      lcdCtrl.2 = RW
      lcdCtrl.3 = RS
      RB = lcdCtrl
      BLIP_E
      lcdCtrl = char & $0F
      SWAP lcdCtrl
      lcdCtrl.1 = E
      lcdCtrl.2 = RW
      lcdCtrl.3 = RS
      RB = lcdCtrl
      BLIP_E
      RETURN
    
  • BamseBamse Posts: 561
    edited 2006-12-20 20:32
    Just a quick thought, haven't tried this...
    Use RA for the data part, on a SX 28, this is port is four bits but I think all 8 bits are available internally...

    Change,
    Send_Text:
      LCD.4 = Char.4                        ' Send High Nibble
      LCD.5 = Char.5                        ' Send High Nibble
      LCD.6 = Char.6                        ' Send High Nibble
      LCD.7 = Char.7                        ' Send High Nibble
      PULSOUT E,3
      GOSUB Wait_Busyflag
      LCD.4 = Char.0                        ' Send Low Nibble
      LCD.5 = Char.1                        ' Send Low Nibble
      LCD.6 = Char.2                        ' Send Low Nibble
      LCD.7 = Char.3                        ' Send Low Nibble
      PULSOUT E,3
      GOSUB Wait_Busyflag
      RETURN
    
    



    To:

    Send_Text:
      RA = Char
      SWAP RA          'High Nibble first
      PULSOUT E,3
      GOSUB Wait_Busyflag
      SWAP RA           'Then low nibble...
      PULSOUT E,3
      GOSUB Wait_Busyflag
      RETURN
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Living on the planet Earth might be expensive but it includes a free trip around the sun every year...

    Experience level:
    [noparse][[/noparse] ] Let's connect the motor to pin 1, it's a 6V motor so it should be fine.
    [noparse][[/noparse] ] OK, I got my resistors hooked up with the LEDs.
    [noparse][[/noparse]X] I got the Motor hooked up with the H-bridge and the 555 is supplying the PWM.
    [noparse][[/noparse] ] Now, if I can only program the BOE-BOT to interface with he Flux Capacitor.
    [noparse][[/noparse] ] I dream in SX28 assembler...

    /Bamse
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2006-12-20 20:58
    I simply didn't know how to program a nibble from a byte. Many of the key words and descriptions in Pbasic are so different from SXB, that I couldn't tell what would do the job. I tried the information in J. W.'s Nuts n Volts artical, but I knew they were byte and word variables. I thought "SHL" (<<) would do the job, but it would only partially initialize.

    Basme, thanks for posting your code!!. It was the only SXB code I found that intialized the parallax parallel LCD. I found SXB & Assby code in the Parallax Google & SX Downloads section, but only the 4-bit assembly version worked and I couldn't reverse engineer the code back to SXB.

    Thanks for all your help
    Bill
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2006-12-21 00:12
    Sparks,
    on the piece of code you posted, I knew it was supposed to be the 4 MSB's first. But the LCD wouldn't initialize and so I reversed it and then LCD initialized, but displayed 4 zeros instead of my text. That lead me to think the "<<" was producing values that I hadn't calculated on. Based off the experience with putting 4 LSB first, I tried the __PARAM1 code both ways also and thats why it was incorrectly formatted. Also, I followed a link to your web site and spent at least an hour browsing all your pages, WOW.

    Johnny Mac,
    The code you presnted used $F0 & $0F, I have had problems finding out the most basic information about using these. The stamp Works manual uses them in some of it's most basic LED experiments, It's not enough for me to just do the exercises, I need to know all the basics so I know why they used variables like that.

    Do you have any recomended reading?
  • JonnyMacJonnyMac Posts: 9,444
    edited 2006-12-21 02:00
    Bill,

    Masking is a pretty common in programming, especially embedded programming. I'm working on a book called "Practical SX/B" right now and make sure that the topic gets good coverage. What's important to understand how the basic operators | (or), & (and) and ~ (not) behave. With & (and), anything "anded" with zero is zero, so you can clear bits by putting zeros into the positions you want cleared, hence:

    someValue = someValue & $0F
    



    will cause the the upper bits of 'someValue' to be cleared, while the lower bits will remain intact (1 stays 1, 0 stays 0). Using masking and SWAP generates less assembly code in SX/B that shifting by four bits.

    Since I wrote StampWorks (yes, I am the artist formerly known as Jon Williams) I think it's a great book, but it is focused on the BS2 and a lot of very cool tricks that are built into the BASIC Stamp that don't exist in other languages, even SX/B. My new book points out those differences when appropriate to help BS2 programmers make the move to SX/B without stress or pain.
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2006-12-21 06:30
    Now I'm a bit embarrassed, LOL. (46yrs old, but I can keep up with my kids)

    I have read about numbering systems in nearly every book, on the subject. I think there were 2 things that·confused me; (1) was that your example and many other programming examples·were an 8 bit hex, and I am more used to seeing 12 or 16 bit hex #'s used in computers and in the BS syntax & reference manual.

    (2) Most books seem to deal with how to understand Hex and convert Hex to Decimal·or Binary, but I don't recall seeing anything about converting hex to binary for the purpose of modifying binary code. Needless to say, I'll be looking at the "operators" more often.
    ·
    Thanks for the help

    ·
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2006-12-21 06:35
    Finally fixed my display name to what it was supposed to be
  • JonnyMacJonnyMac Posts: 9,444
    edited 2006-12-21 16:30
    Hexadecimal is simply a programmer's shortcut, each hex digit replacing four binary digits. In PBASIC and SX/B, the prefix designates the number system so $F, $0F, $00F, $000F are all valid and denote the same value. Even if you use the latter two variants with an 8-bit value in SX/B, only the lower eight bits of the mask are used.

    If you've got an SX-Key you can see for yourself by stepping through this little program in the Debugger:

    Main:
      RB = %11111010
      RB = RB & $000F
      END
    



    When you hit the END statement RB will equal %00001010.
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2006-12-21 18:25
    Capt. Quirk,

    (Cool name. I wish I had thought of it!)

    Most standard LCDs (and certainly if you got one from Parallax) are going to be expecting the high nibble first, then the low nibble. So, although you are seeing something displayed by sending your data the other way around, it is not your text. So I do not think the display has been properly initialized.

    Question: Can you initialize your LCD and have it properly display text using anyone else's SX/B code?

    In my response I simply took the second code snippet you provided and examined it mainly from the standpoint of “efficiency.” In so doing I was compelled to point out what looked like an error to me in regard your presentation of the low nibble first.

    Obviously there are other factors that must be considered for making the LCD function properly. Basme's code segment does not alter the low nibble of the RB port of the SX. Your code does. If there is nothing connected to RB pins 0-3 this should not cause any problems. It might be more “code space efficient” to do operate this way. If, however, you do have things connected to RB pins 0-3, you quite likely will not want to have their states altered by your LCD code. If you happen to have your LCD control lines connected to any of these lower RB pins, then you will definitely need to heed JonnyMac's advise to use a mask so the the lower nibble (and thus the lower pins) of RB are not altered inadvertently. Keep in mind that if you do this you will need to apply the appropriate masking function with fewer than four assembly language primitives or faster than four clock cycles if you wish to improve upon Basme's code in terms of code space or speed.

    The bottom line is... once it has been compiled (which is what really counts on the SX), the code segment you have referenced by Basme is hard to improve upon in terms of either code space or speed!

    I must make one final comment. Although I am glad that you found some web pages that were quite helpful to you, I can not accept any credit for them. I am quite certain they are the effort of someone else. Perhaps you will be kind enough to share the link so that we may all benefit and the proper author may receive due credit. smile.gif

    - Sparks
  • PJMontyPJMonty Posts: 983
    edited 2006-12-21 19:09
    Capt. Quirk,

    With regards to numbering systems, are you familiar with how to count in binary? Below I have a list that shows the equivalent value from 0 to 15 in binary, decimal, and hex. There are a few things you need to understand. The first is that binary works like decimal works like hex in that all of them have the least significant digit on the right, and the most significant on the left. The examples below are for a 4 bit (a nibble) numbering system. In an 8 bit system, there would be two hex digits starting at $00 and ending at $FF.

    Take a look at the column of binary values. Note how the right most (least significant) is simply an alternating string of ones and zeros. The next most significant digit does the same thing, but it alternates every two numbers. The next alternates very four numbers, and the most significant alternates every eight. See the pattern here? Each new significant digit alternates twice as slowly as the previous digit.

    Binary numbers have a range of 0 to 1 for each digit, hence they alternate. Decimal digits have a range of 0 to 9, hence we can count to 9 before needing to add another digit and starting over. If you wrote a column of decimal numbers, you would see the least significant (leftmost) digit would continuously count from 0 to 9 over and over. The next digit (the 10's column) would do the same thing, except it would be happening 10 times slower. In other words, the 120's column would have ten zeros, then ten ones, then twos, etc, etc. The 100's column would do the same thing except you would have 100 zeros, 100 one, etc.

    Hex is not different except that after we hit the number 9, we use the letters A to F to represent the numbers 10 to 15. However, just like all numbering schemes, once you have used all the values for the least significant column, you have to add another digit and start the least significant digit over again. Thus, after you hit $F (which equals 15 decimal), the next number is $10, which equals 16 decimal.

    Binary  Decimal  Hex
    0000 = 0 = $0
    0001 = 1 = $1
    0010 = 2 = $2
    0011 = 3 = $3
    0100 = 4 = $4
    0101 = 5 = $5
    0110 = 6 = $6
    0111 = 7 = $7
    1000 = 8 = $8
    1001 = 9 = $9
    1010 = 10 = $A
    1011 = 11 = $B
    1100 = 12 = $C
    1101 = 13 = $D
    1110 = 14 = $E
    1111 = 15 = $F
    



    Remember that in decimal we talk about the 1's column, the 10's column, the 100's column, etc. In binary, it's the 1's column, the 2's column, the 4's column, the 8's column, etc. In hex it's the 1's column, the 16's column, the 256's column, etc.

    Note that the binary values for 1, 2, 4, and 8 all have a one in the respective column, and zeros in all the rest. This is how you create masks for turning bits on and off. If you want to isolate the least significant bit and most significant bit, you would have 1001, which equals 9. That's a one in the 8's column and a one in the 1's column. 1 + 8 = 9.

    I can't speak for anyone else, but I don't "think" in binary or hex really. When I want to create a mask, I write out the binary value I need and use it directly in my code. If I see %00001111 in my code, I know I'm isolating the bottom nibble from the top. If I see %00000010, I know I'm isolating bit one (the rightmost bit is bit number zero).

    I hope some of this helps.

    Thanks,
    PeterM
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2006-12-21 23:18
    Sparks,

    I thought you were "Sparks Fun Electronics". As for your question "Question: Can you initialize your LCD and have it properly display text using anyone else's SX/B code?" the answer is no. There·is the SXB example in the sx-key v3.2.3 ide, another by John J Couture, Al Williams version that was converted from his·assembly code and sereral·Pbasic examples. Also Jon recently wrote a Serial SXB example. Even Basme's code had errors,·But it was the only one that I knew for sure was initializing. So I converted it to·8 bit, since it was simpler and sending in 4 bit seemed to be the problem with the other codes. Then I found the bugs, just a simple spacing error and it worked just fine.

    Originally I bought the Blitz instead of the key, mainly because·I never needed the inline debugger for a BS2, so why should I need it for the SX. I had no idea there was no "Debug" window in the SX IDE.

    So I had the parallel LCD and I already had it working on the BS2. So I planned to use it as my debug window. But since I didn't have the SX Key, I couldn't debug the·SX LCD examples and I embarrased to say, I spent an entire week to just get it to say "Basme was here".·I'm sure I wasted that week unnecessarily, you guys have already been a big help, I just didn't want ask until I knew I was really stuck and durring that week I had fun trying all kinds of things to trouble shoot the code.

    My plans up to this point and beyond were:

    (1) Get the LCD to work in 8 bit mode
    (2) then make it work in 4 bit mode
    (3) then get the BS2 LCD demo program to work
    (4) Finally, get the LCD to show real-time values (like Ken's mill example)

    So yesterday I bought the SX-Key and Gunther's updated book and after responses I 'll be working on code again.
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2006-12-21 23:52
    JonnyMac & PJMonty,

    I bet you guys can convert Decimal to Hex and/or Binary in your head like I do with inches to millimeters or meters. I've already started to go back over the basics, so that someday I'll get to that point too.

    After your suggestions and help, I googled them and found more information·online.·My digital·and programming books had nothing on masking. Online I found information on using the "OR" and "XOR" for masking too. At the same time I realized that the boring sections in books about "Booleans" and how they pertain to making digital chips,·function the way they do. Was the exact same thing, but your·minipulating code instead. I never thought I needed to no more about Booleans, than how there used in algebra and basic code.

    Friday I should receive my SX-Key and I'll try your code snippet out

    Thanks

    Bill
  • JonnyMacJonnyMac Posts: 9,444
    edited 2006-12-22 01:46
    I tend to agree, Peter, and generally only use hex masks when I want to isolate one nibble or the other from a byte.
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2006-12-25 09:09
    I tried those ideas and the one that worked the best was "SWAP", it did exactly what I needed. The "MASK" versions with or without the "swap", didn't work.· The masking always changes the data by adding "0000" to·one side or the other and by the last instruction you end up with %0000_0000 and no data.

    Swap did it very neatly, if I started with %0010_1000 the high nibble (%0010)·would go out rb.4 - 7 and then after "swap" the low nibble (%1000) would go out.

    The problem with·"swap" is when you need the other 4 RB pins connected too some other device, can I·declare those 4 data bus pins (RB.4 -.7) as an array? and if so can somebody post an example?

    Also Basme said he thought the 4 RA pins were actually 8 bit, but in the SX 28 data sheet it talks about the SX as an 8 bit processor that uses 12 bit words, so does that mean RA is only 4 bit. And what does it's·pins 0 thru 3,· pass the LSB or MSB?

    Thanks





    Note: in the attachment, the BS2 code calls the sub "busy_flag" and it wasn't necessary

    Post Edited (Capt. Quirk) : 12/25/2006 9:15:52 AM GMT
Sign In or Register to comment.