News:

;) This forum is the property of Proton software developers

Main Menu

Print command, some idea

Started by keytapper, Jan 24, 2023, 08:20 AM

Previous topic - Next topic

keytapper

Well I stumbled on the fact of pin count lack. So usually there's a chance to get the print over a serialized line with the help of some hardware module, which are pretty cheap.
I could discover that the I2C printing is rather efficient, so I hope that will go into the language as well as the current print has.

I'd invite to a review (as there may be a set of paid option) and include that piece of code with an optimized solution so the compiler may accomodate the proper variables with the system ones already in use.
I just thought that it may go under the same print umbrella, just adding the below mentioned declarations.

Some Declare to assign the printing method
Declare_Bus = I2C, [1]Serial
Declare_Type = Soft, [1]Hard
[1]Declare_Model = HD44780, KS0108, Alpha, T5963, Nextion, Serial,other
[1]Additionally

Then at compiling the subsequent checks would perform ;D that the MCU has the necessary requirements to accomplish the user intents.

Please just put a LIKE if you are interested of it.
Ignorance comes with a cost

top204

What you are asking for is a re-write of the whole of the compiler's LCD code! This would take a couple of months to complete for all the LCD types and cost quite a bit of money per daily rate. :-) Have you any idea what is involved in re-writing the code for all the different types of LCD, not to mention the I2C slave firmwares required for each of them with their different interface methods and in raw, optimised, assembler code?

I created an include file a couple of years ago for an LCD05 interface that attaches to an alphanumeric LCD. It uses I2C for the interface, and the include file replaces the compiler's Print, Print At, Cls and Cursor commands so they interface via I2C to the LCD. The "LCD05.inc" include file is listed below. The same principles can be used to interface with any LCD type, and the procedure mechanism makes things so much easier to create unique libraries without having them built into the compiler itself:

$ifndef __LCD05_INC_
$define __LCD05_INC_
'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' LCD05 I2C LCD library that replaces the compiler's library routines, so the commands Print, Print At, Cls, and Cursor can be used
' Written for the Positron8 BASIC compiler by Les Johnson
'
    #Disable Print, Cls, Cursor                 ' Disable the compiler's library routines for Cls, Cursor, and Print
'
' LCD pinouts
'
'                 |                  Link
'    Vcc (5V)O----|                  O--O <----Open = I2C
'    SDA/TX  O----|                            Closed = Serial
'    SCL/RX  O----|       Keypad Connections
'    GND     O----|_____________________________
'                        | | | | | | |
'                        | | | | | | |
'                        O O O O O O O
'                        | | | | | | |
'                        | | | | | | -------- Row 2 Input
'                        | | | | | ---------- Row 3 Input
'                        | | | | ------------ Column 3 Output
'                        | | | -------------- Row 4 Input
'                        | | ---------------- Column 1 Output
'                        | ------------------ Row 1 Input
'                        -------------------- Column 2 Output
'
$define cLCD_Address $C6                        ' The I2C display is located on the I2C bus at an address of $C6
'
' Create LCD I2C registers
'
$define cFIFO_Free_Bytes   0                    ' Number of free bytes in FIFO buffer (read)
$define cCommand_Reg       0                    ' Command register
$define cKeypad_State_Low  1                    ' Keypad state Low byte
$define cKeypad_State_High 2                    ' Keypad state High byte
$define cVersion           3                    ' Read the firmware version
'
' The LCD05 has four registers, three being read only information registers.
' Register 0 is a dual purpose register, when written, it is the command register where all of the instructions from the commands section should be sent.
' When read it returns the number of free bytes in the FIFO buffer.
'
' Create the LCD commands for the I2C interface controller
'
$define cNull                    0              ' Ignored as a no operation
$define cCursor_Home             1              ' Sets the cursor to the home position (top left)
$define cSet_CursorXY            2              ' (1-80 or 32) Cursor to a position specified by the next byte, where 1 is the top left and 80/32 is the bottom right
$define cSet_Cursor              3              ' (Line, Column) Sets cursor using two bytes, where first byte is the line and the second byte is the column
$define cHide_Cursor             4              ' Stops the position cursor from appearing on the display
$define cShow_Underline_Curs     5              ' Changes the cursor to the underline type
$define cShow_Blinking_Curs      6              ' Changes the cursor to the blinking type
$define cBackspace               8              ' Deletes the preceding character from the current position on the display
$define cHor_Tab                 9              ' Moves the current position across by the tab space set by command 18 (default tab space 4)
$define cSmart_Ln_Fd             10             ' Moves the cursor down one line to the position beneath in the same column
$define cVert_Tab                11             ' Moves the cursor up one line to the position above in the same column
$define cClear_Screen            12             ' Clears the screen and sets cursor to the home position
$define cClear_Column            17             ' Clears the contents of the current column and moves cursor right by one column
$define cTab_Set                 18             ' Sets the required tab size, the following byte can be a size of between 1 and 10
$define cBacklight_On            19             ' Turns the backlight of the LCD05 on
$define cBacklight_Off           20             ' Turns the backlight of the LCD05 off (default)
$define cDisable_Start_Mess      21             ' Disables the display of setup information at power up
$define cEnable_Start_Mess       22             ' Enables the display of setup information at power up
$define cSave_As_StartUp_Screen  23             ' Saves current screen and displays it on power up
$define cSet_Display_Type        24             ' Sets which display is connected to the LCD05 (see changing display type below)
$define cChange_Address          25             ' First byte of sequence to change LCD05 address (see changing address)
$define cCustom_UDG              27             ' Allows 8 custom chars to be built. See custom char generator below
$define cDble_Key_Scan_Rate      28             ' Increases the frequency of the keypad scan to 20Hz
$define cNorm_Key_Scan_Rate      29             ' Returns to the default keypad scan frequency of 10Hz
$define cContrast_Set            30             ' The value following this command will be the contrast level (0-255)
$define cBrightness_Set          31             ' The value following this command will be the brightness level (0-255)
'
' 32-255 ASCII_Chars Writes ASCII chars straight to the display
'
' Changing address:
'
' The LCD05 software has the facility to easily change the module's address on the I2C bus system in the range of 0xC6 - 0xCE ( even numbers only ).
' This is achieved by sending the following sequence:
'
'   $19       (1st byte of change address command)
'   $A0       (2nd byte of change address command)
'   $AA       (3rd byte of change address command)
'   $A5       (4th byte of change address command)
'   $C6, $C8, $CA, $CC or $CE ( New address to map LCD05 at)
'
' The Current address is displayed every time the module is first powered as a default, this may be changed to no display or custom display by user command.
'
' Changing display type .
' Because there are four variations of the LCD display that the LCD05 connects too, a software command can be used to switch between them.
' Firstly a command of 24 must be issued, this is then followed by the display type attached:
' LCD style  Value
' 20x4 Green  3
' 20x4 Blue   4
' 16x2 Green  5
' 16x2 Blue   6
'
$define cGreen_20x4 3
$define cBlue_20x4  4
$define cGreen_16x2 5
$define cBlue_16x2  6
'
' Create a compiler system variable
'
    Dim GEN As Byte System
'
' Create user variables
'
    Dim LCD05_bCharOut As Byte Access                               ' Holds the byte to send to the LCD
    Dim LCD05_bXpos    As Byte Access                               ' Holds the X position on the LCD
    Dim LCD05_bYpos    As Byte Access                               ' Holds the Y position (line) on the LCD

'---------------------------------------------------------------------------
    GoTo _I2C_LCD_Main_                                             ' Jump over the compiler's replacement library routines to _I2C_LCD_Main_

'---------------------------------------------------------------------------
' Send a single Command to the I2C controller
' Input     : pCommand holds the command to send
' Output    : None
' Notes     : None
'
$define LCD_Command(pCommand)  I2COut LCD_SDA_Pin, LCD_SCL_Pin, cLCD_Address, cCommand_Reg, [pCommand]

'---------------------------------------------------------------------------
' Send a multiple Command to the I2C controller
' Input     : pCommand holds the command to send
'           : pParam holds the parameter to send
' Output    : None
' Notes     : None
'
$define LCD_SendCommand(pCommand, pParam)  I2COut LCD_SDA_Pin, LCD_SCL_Pin, cLCD_Address, cCommand_Reg, [pCommand, pParam]

'---------------------------------------------------------------------------
' Alter the contrast of the LCD's display
' Input     : pContrast holds the contrast value (0 = low, 255 = high)
' Output    : None
' Notes     : None
'
$define LCD_Contrast(pContrast)  I2COut LCD_SDA_Pin, LCD_SCL_Pin, cLCD_Address, cCommand_Reg, [cContrast_Set, pContrast]

'---------------------------------------------------------------------------
' Alter the brightness of the LCD's backlight
' Input     : pBrightness holds the contrast value (0 = Low, 255 = High)
'           : pParam holds the parameter to send
' Output    : None
' Notes     : None
'
$define LCD_Brightness(pBrightness)  I2COut LCD_SDA_Pin, LCD_SCL_Pin, cLCD_Address, cCommand_Reg, [cBrightness_Set, pBrightness]

'---------------------------------------------------------------------------
' Extinguish the back light
' Input     : None
' Output    : None
' Notes     : None
'
$define LCD_Backlight_Off() LCD_Brightness(0)

'---------------------------------------------------------------------------
' Illuminate the back light
' Input     : None
' Output    : None
' Notes     : None
'
$define LCD_Backlight_On() LCD_Brightness(255)

'---------------------------------------------------------------------------
' Create a custom character for the LCD
' Input     : pCharNum holds the character to alter (128 to 135)
'           : pByte1 to pByte7 hold the bytes to place in the custom character
' Output    : None
' Notes     : None
'
$define LCD_UDG(pCharNum, pByte0, pByte1, pByte2, pByte3, pByte4, pByte5, pByte6, pByte7) '
    I2COut LCD_SDA_Pin, LCD_SCL_Pin, cLCD_Address, cCommand_Reg, [cCustom_UDG, pCharNum, pByte0, pByte1, pByte2, pByte3, pByte4, pByte5, pByte6, pByte7]

'---------------------------------------------------------------------------
' Send a byte to the Hitachi LCD
' Input     : WREG holds the byte to send
' Output    : WREG is still holding the original byte sent
' Notes     : None
'
__Print_:
#ifSym __Syscom_ALCD_Print_Req_                                     ' Has the Print command been used in the program?
    LCD05_bCharOut = WREG                                           ' Yes. So save WREG
    I2COut LCD_SDA_Pin, LCD_SCL_Pin, cLCD_Address, 0, [LCD05_bCharOut]
    WREG = LCD05_bCharOut                                           ' Restore WREG
    Return
#endIfSym

'---------------------------------------------------------------------------
' Move the cursor on the LCD
' Input     : GEN = Line
'           : WREG = Xpos
' Output    : None
' Notes     : None
'
__Cursor_:
#ifSym __Syscom_ALCD_Cursor_Req_            ' Has the Cursor command been used in the program?
    LCD05_bXpos = WREG                      ' Yes. So transfer the Xpos into LCD05_bXpos
    LCD05_bYpos = GEN                       ' Transfer the Ypos into GEN
    I2COut LCD_SDA_Pin, LCD_SCL_Pin, cLCD_Address, cCommand_Reg, [cSet_Cursor, LCD05_bYpos, LCD05_bXpos]
    Return
#endIfSym

'---------------------------------------------------------------------------
' Clear the LCD
' Input     : None
' Output    : None
' Notes     : Also disables the cursor and turns on the backlight
'
__LCD_Cls_:
#ifSym __Syscom_ALCD_Cls_Req_               ' Has the Cls command been used in the program?
    LCD05_bXpos = 0                         ' Yes. So Clear the X position
    LCD05_bYpos = 0                         ' Clear the Y position
    I2COut LCD_SDA_Pin, LCD_SCL_Pin, cLCD_Address, cCommand_Reg, [cClear_Screen]
    Return
#endIfSym

'---------------------------------------------------------------------------
' Setup the I2C interface and the LCD
' Input     : None
' Output    : None
' Notes     : Disables the cursor and turns on the backlight
'
Proc I2C_LCD_Setup()
    DelayMS 100
    LCD05_bXpos = 0
    LCD05_bYpos = 0
    I2COut LCD_SDA_Pin, LCD_SCL_Pin, cLCD_Address, cCommand_Reg, [cClear_Screen, cHide_Cursor, cBacklight_On]
EndProc

'---------------------------------------------------------------------------
'
_I2C_LCD_Main_:

$endif      ' __LCD05_INC_

A demo program for the above library listing is listed below:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' I2C LCD library that re-creates the compiler's commands for an LCD05 interface.
' Written for the Positron8 BASIC compiler by Les Johnson.
'
    Device = 18F25K22                           ' Choose the device, can be 18F or Enhanced 14-bit core types
    Declare Xtal = 16                           ' Tell the compiler what frequency the device is operating at (in MHz)

    Include "LCD05.inc"                         ' Load the LCD05 I2C routines into the program
'
' Set the pins used by the LCD's I2C interface
'
    Symbol LCD_SCL_Pin = PORTC.3                ' Set the pin to use for SCL to the LCD controller
    Symbol LCD_SDA_Pin = PORTC.4                ' Set the pin to use for SDA to the LCD controller

    Dim MyDword As Dword
    Dim X_bPosition As Byte
    Dim Y_bPosition As Byte

'---------------------------------------------------------------------------
Main:
    I2C_LCD_Setup()
'
' Draw a frame around the LCD
'
    Cls
    For X_bPosition = 1 To 20
        Print At 1, X_bPosition, "*"
        DelayMS 10
    Next
    For Y_bPosition = 1 To 4
        Print At Y_bPosition, 20, "*"
        DelayMS 10
    Next
    For X_bPosition = 20 DownTo 1
        Print At 4, X_bPosition, "*"
        DelayMS 10
    Next
    For Y_bPosition = 4 DownTo 1
        Print At Y_bPosition, 1, "*"
        DelayMS 10
    Next
    DelayMS 500
'
' Display some texts and values
'
    Cls
    Print At 1,1, "Decimal Test"

    For MyDword = 0 To $FFFFFF
        Print At 2,2, "Byte  = ", Dec MyDword.Byte0, "    "
        Print At 3,2, "Word  = ", Dec MyDword.Word0, "    "
        Print At 4,2, "Dword = ", Dec MyDword, "    "
        DelayMS 10
    Next

See_Mos

Would it not be easier to use a spare PIC device to drive an LCD display?

I know low cost modules are available but apart from the Nextion Les has already provided the software required. Just using the available serial commands only needs one pin.

keytapper

Quote from: top204 on Jan 24, 2023, 10:28 AMWhat you are asking for is a re-write of the whole of the compiler's LCD code! This would take a couple of months to complete for all the LCD types
OK Sir, my greatest respect for your masterpiece, my apologies for such ambitious idea. Probably there are option that need to bring rewards to the author.
There are publishers that offer different versions according what is included in the package.

I admit that in my spare time I should read more on what is given in the package. Mostly I'm jumping at the keyboard and try to get some experiment running, then the good information still set apart.

From the example you provided,Sir, I got to learn more cheat-code. Hope that whose using frequently the language will bring good examples.
Ignorance comes with a cost

keytapper

#4
Quote from: See_Mos on Jan 24, 2023, 12:03 PMWould it not be easier to use a spare PIC device to drive an LCD display?
Yeah, one IC may be similar to another, but programmable would cost efforts to make it functional.
I assembled a prototype, on a veroboard, with a 74xx595 and it's like the PCF8574. The connection to the LCD (HD44780) is like many modules available with PCF8574. For my prototype I put the backlight at pin 3. This makes little effort to switch between HBusOut, BusOut, ShiftOut or SPI as making an alias to the library.
As you say, perhaps a MCU will allow to use several protocol with just a matter of module jumpers or EEPROM setting.
Ignorance comes with a cost

trastikata

In my opinion with the new procedure capable Positron there's little benefit to include commands for particular hardware.

Best is to keep the library with include files for various hardware and make our own procedures to reuse in future programs.

keytapper

I do share the idea for procedures which broaden the flexibility of the code and introduce modularity on the programming.
I drop the proposal, I will try to add my experience in this case and share that here.
Ignorance comes with a cost

HAL

Hello everyone,
Has anyone tried to compile the code for LCD05?

It looks like a really great tool to have if an I2C LCD is needed. ;)

However, using Positron 4.0.3.0  I can't get it to compile.
Compiled as is gives an error:  Error at Line [23]    *** Duplicate Declaration 'PORTC' ! ***ERROR
results as below:

Warning!  *** No $define LCD_SDA_Pin in the main program, so using a default pin of PORTC.1! ***
Warning!  *** No $define LCD_SCL_Pin in the main program, so using a default pin of PORTC.0! ***
Error at Line [23]    *** Duplicate Declaration 'PORTC' ! ***

After commenting out the two statements in the demo code:

'Symbol LCD_SCL_Pin = PORTC.3
'Symbol LCD_SDA_Pin = PORTC.4

Compilation after the change almost gets all the way through (to the Re-Assembling part) but at the end gives 28 ASSEMBLER ERRORS

some but not all shown below....

ASSEMBLER ERRORS
Error[113]  C:\USERS\USER\PDS\A.S 677 : Symbol not previously defined (__PRINT_)
Error[113]  C:\USERS\USER\PDS\A.S 683 : Symbol not previously defined (__PRINT_)
Error[113]  C:\USERS\USER\PDS\A.S 988 : Symbol not previously defined (__LCD_CLS_)
Error[113]  C:\USERS\USER\PDS\A.S 1002 : Symbol not previously defined (__CURSOR_)
Error[113]  C:\USERS\USER\PDS\A.S 1004 : Symbol not previously defined (__PRINT_)

ASSEMBLER ERRORS. HEX file not Created

Does anyone have any insight as to what the problem may be?

Thanks
Hal

HAL

Let me answer my own post....

Regarding the LCD05.Inc file there were two instances of the @ being used but no @Print.

Changed both to the format that Les described in his post  #8 on Apr 30, 2022, 08:48 PM : 
  Change the: @Print  to  __Print_:

Asm-
LCD@Cur
__Cursor_:
EndAsm

Asm-
LCD@Cls
__LCD_cls_:
EndAsm

The Assembler errors vanished.

Then tried to make changes to eliminate the errors / warnings in the main program but was not successful
however a hex file did finally get generated....

    Symbol LCD_SCL_Pin = PORTC.3  <<<< original
    $define LCD_SDA_Pin PORTC.3    <<<< mimicked the include file     
    Dim SCL_Pin As PORTC.3        <<<< as per the manual 

  Warning! Line [44]    In file [C:\Users\User\PDS\Includes\LCD05.INC]    *** No $define LCD_SDA_Pin in the      main program, so using a default pin of PORTC.1! ***
  Warning! Line [53]    In file [C:\Users\User\PDS\Includes\LCD05.INC]    *** No $define LCD_SCL_Pin in the main program, so using a default pin of PORTC.0! ***
    Program Compiled with Warnings. 1090 Bytes used from a possible 32768
    44 Variables used in the 18F25K22 from a possible 1536
    There are Warnings!
 
Well it's gone 0400 time for us old codgers to call it a night....
  An interesting learning experience.....  @whatever = __whatever_: