Hippy's sendDataByte explanation?

marcos.placona

Senior Member
Hi, I'm working with some LCD displays and so far everything works. I'm just a bit puzzled because I can't really understand how part of the code works, although it works fine :)

This is the part I don't really understand:

Code:
SendDataByte:
     {
        pins = byte & %11110000 | rsbit ; Put MSB out first
        PULSOUT E,1                     ; Give a 10uS pulse on E
        pins = byte * %00010000 | rsbit ; Put LSB out second
        PULSOUT E,1                     ; Give a 10uS pulse on E

        rsbit = RSDATmask               ; Send to Data register next

        RETURN
     }
I don't really understand what "pins" does here, and what are they used for. Also, I don't know why it uses "&" in one line, and on the other "*". I understand that the "|" is used as OR qualified, but still don't really know why they are there.

Then there's the values: %11110000, which I believe have something to do with DB4-DB7 (pure guess) and the pins they are connected.

I have DB4-DB7 connected respectively with output 4 - 7. To save my i2c scl pin, I tried to move DB4 from output 4 to output 0, thus changing the value %11110000 to %11100001 . It really messed up the results on the screen.

I know it'd working, and I should be happy with that, but I realy wanna understand more about what I'm doing. So far I was able to understand everything the code does apart from that.

If anybody can give me a light in here, that'd be highly appreciated.
 

hippy

Ex-Staff (retired)
I think there's an explanation on the Frum somewhere but coudn't point to it.

The basic premis is as you've determined to split the byte into two nibbles and send as two separate chunks. For the first, the data to send And'ed(&) with %11110000 to just leave the msb in the top 4-bits then the RS bit which is in the 'rsbit' variable is Or'd in (|). For the second the 4-lsb's are needed and need to be moved to the top 4-bits, the easiest way to do that is multiply by 16 ( * %0001000 ), then the RS bit is Or'd in again. Using 'pins=' is just a quick way of getting all the output bits set from the byte.

How to use I2C never made it through to my live web page, but here's what should be there. It's for an 18X but the same would apply for others ...

Using I2C on a PICAXE-18X

Please note that this configuration has not been tested while using I2C, only in a configuration with no I2C devices connected.

Because the LCD interface only uses six I/O lines leaving two unused, it would be possible to use an 18X to interface to an LCD and use I2C. This is not chievable without changing the hardware configuration described earlier because Output Pin 4, used to drive the LCD is required for I2C interfacing. Output Pin 1 which is also used for I2C interfacing has not been used by the LCD interface.

To use an 18X with an LCD interface and I2C, DB4 ( pin 11 ) of the LCD must be connected to Output Pin 0 ( leg 6 ) of the 18X rather than to Output Pin 4 as previously shown ...

Code:
+5V --------.--------------------.------.------.
           .|.     PICAXE-18X    |      |      |
           | |    .----.----.    |      |      |
       4K7 |_|    | 1    18 |    |      |      |
            |     | 2    17 |    |      |      |                 LCD
      ......|....>| 3    16 |    |      |      |             .---------.
      :     `---->| 4    15 |    |      |      |             |         |
      }-----------| 5    14 |----'      |      |           .-^--.      |
      |  .--------| 6    13 |-----------|------|---------->| 14 | DB7  |
      |  |        | 7    12 |-----------|------|---------->| 13 | DB6  |
      |  |  .-----| 8    11 |-----------|------|---------->| 12 | DB5  |
      |  |  |  .--| 9    10 |--//  .----|------|---------->| 11 | DB4  |
      |  |  |  |  `---------'      |    |      |           | 10 | DB3  |
      |  |  |  `-------------------|----|------|------.    |  9 | DB2  |
      |  |  `----------------------|----|------|---.  |    |  8 | DB1  |
      |  |                         |    |      |   |  |    |  7 | DB0  |
      |  `-------------------------'    |      |   |  `--->|  6 | E    |
      |                                .|.     |   |  .--->|  5 | /WR  |
      |                           10K  | |<-.  |   `--|--->|  4 | RS   |
      |                           Pot  |_|  `--|------|--->|  3 | Vo   |
      |                                 |      `------|--->|  2 | Vcc  |
0v ---^---------------------------------^-------------^--->|  1 | Vss  |
                                                           `-.--'      |
               100nF Power Supply                            |         |
              decoupling not shown                           `---------'
The following change should be made to reflect the new pin usage definitions in your software ...

Code:
        SYMBOL  RS        = 2         ; 0 = Command   1 = Data
        SYMBOL  E         = 3         ; 0 = Idle      1 = Active
        SYMBOL  DB4       = 0         ; LCD Data Line 4
        SYMBOL  DB5       = 5         ; LCD Data Line 5
        SYMBOL  DB6       = 6         ; LCD Data Line 6
        SYMBOL  DB7       = 7         ; LCD Data Line 7
The definition of DB4 is not actually used within the LCD interfacing routines so this is a cosmetic change to maintain accurate documentation, however, the following changes must be made to the interface routines for the hardware change to be effective ...

Code:
    SendInitCmdByte:

        PAUSE 15                        ; Delay 15mS at 4MHz

    SendCmdByte:

        rsbit = RSCMDmask               ; Send to Command register

    SendDataByte:

        rsbit = byte / 16 & 1 | rsbit   ; Move MSB DB4 to bit 0
        pins = byte & %11110000 | rsbit ; Put MSB out first
        PULSOUT E,1                     ; Give a 10uS pulse on E
        rsbit = rsbit & %00001100       ; Clear bits 0 and 1
        rsbit = byte & 1 | rsbit        ; Move LSB DB4 to bit 0
        pins = byte * %00010000 | rsbit ; Put LSB out second
        PULSOUT E,1                     ; Give a 10uS pulse on E

        rsbit = RSDATmask               ; Send to Data register next

        RETURN
Note that this code will also work with an 18X wired as originally described ( with DB4 to Output Pin 4 ) although Output Pin 0 will no longer be available for general purpose use.

Added : This would need changing if your RS and E are on different pins than 2 and 3 respectively.

Your last code showed ...

Code:
       SYMBOL  RS        = 0         ; 0 = Command   1 = Data
        SYMBOL  E         = 2         ; 0 = Idle      1 = Active
        SYMBOL  DB4       = 4         ; LCD Data Line 4
        SYMBOL  DB5       = 5         ; LCD Data Line 5
        SYMBOL  DB6       = 6         ; LCD Data Line 6
        SYMBOL  DB7       = 7         ; LCD Data Line 7
Let me know what wiring you're using and I can give you the changes needed, or simply move RS to 2, E to 3, DB4 to 0 and use the above code after changing RSDATmask to %00000100.
 
Last edited:

marcos.placona

Senior Member
Hi Hippy, thanks for the code, and sorry for not posting before.

Changing my senddatabyte to

Code:
SendDataByte:

        rsbit = byte / 16 & 1 | rsbit   ; Move MSB DB4 to bit 0
        pins = byte & %11110000 | rsbit ; Put MSB out first
        PULSOUT E,1                     ; Give a 10uS pulse on E
        rsbit = rsbit & %00001100       ; Clear bits 0 and 1
        rsbit = byte & 1 | rsbit        ; Move LSB DB4 to bit 0
        pins = byte * %00010000 | rsbit ; Put LSB out second
        PULSOUT E,1                     ; Give a 10uS pulse on E

        rsbit = RSDATmask               ; Send to Data register next

        RETURN
Did work, and also, it still works even if I have my DB4 connected to output 4 (that's weird) I'm not sure I understand why we use the DB's for, as the RS is responsible for writing stuff to the LCD I suppose.

But thanks ever so much, now I can use the i2c pins.
 

hippy

Ex-Staff (retired)
It still works with DB4 because the bit masking in the code copies bit 4 to bit 0 but still leaves te original bit 4 intact. Only once an I2CSLAVE is issued does what was DB4 become an I2C line and override what 'pins=' puts out.
 
Top