You are not logged in or registered. Please login or register to use the full functionality of this board...
The QB64 Edition
Waltersmind's - Single Color LED sign with scrolling letters - Printable Version

+- The QB64 Edition (http://www.thejoyfulprogrammer.com/qb64/forum)
+ Thread: Waltersmind's - Single Color LED sign with scrolling letters (/showthread.php?tid=7)



Waltersmind's - Single Color LED sign with scrolling letters - Waltersmind - 06-11-2014 01:55 AM

Here is the code to my really cool LED scrolling sign.

Code Snippet: [Select]
' *************************************************************************************************
' *                                                                                               *
' *  Walter's LED sign  - By member Waltersmind.                                                  *
' *                                                                                               *
' *  Created: May 04, 2014                                                                        *
' *                                                                                               *
' *************************************************************************************************

TYPE LEDCharacter
   Image AS _UNSIGNED LONG
   ImageWidth AS _UNSIGNED INTEGER
   ImageHeight AS _UNSIGNED INTEGER
END TYPE

DIM SHARED ScreenWidth AS _UNSIGNED LONG
DIM SHARED ScreenHeight AS _UNSIGNED LONG
DIM SHARED MainScreen AS _UNSIGNED LONG
DIM SHARED BackBuffer AS _UNSIGNED LONG
DIM SHARED SaveBuffer AS _UNSIGNED LONG

DIM SHARED ScrollSpeed AS INTEGER
DIM SHARED Character(126) AS LEDCharacter
DIM SHARED LEDPixelSize AS _UNSIGNED INTEGER
DIM SHARED LEDBulbSize AS _UNSIGNED INTEGER
DIM SHARED LEDScreenWidth AS _UNSIGNED INTEGER
DIM SHARED LEDScreenHeight AS _UNSIGNED INTEGER
DIM SHARED LEDPanelWidth AS _UNSIGNED INTEGER
DIM SHARED LEDPanelHeight AS _UNSIGNED INTEGER
DIM SHARED LEDImageOn AS _UNSIGNED LONG
DIM SHARED LEDImageOff AS _UNSIGNED INTEGER

DIM SHARED CurrentLine AS _UNSIGNED INTEGER
DIM SHARED CurrentCharacter AS _UNSIGNED INTEGER
DIM SHARED CurrentPixelDelay AS _UNSIGNED INTEGER
DIM SHARED CurrentPixelCounter AS _UNSIGNED INTEGER
DIM SHARED CurrentCharacterPixel AS _UNSIGNED INTEGER
DIM SHARED PixelSpeed AS _FLOAT
DIM SHARED CurrentPixelState AS _UNSIGNED LONG

REDIM SHARED Message(-1) AS STRING

LEDPixelSize = 6 '12 'The LED pixel unit that contains the LED bulb
LEDBulbSize = 4 '8  ' The size of the LED bulb
LEDPanelWidth = 200 ' The width is in LED pixels (a space that contains one LED bulb), not monitor pixels.
LEDPanelHeight = 16 ' This is the actual height the current font uses.
CurrentPixelDelay = LEDPanelWidth + 10 ' The delay in LED units before the next line is displayed.
PixelSpeed = 1 ' Change this to speed up the scrolling.

ScreenWidth = LEDPanelWidth * LEDPixelSize
ScreenHeight = LEDPanelHeight * LEDPixelSize

MainScreen = _NEWIMAGE(ScreenWidth, ScreenHeight, 32)
BackBuffer = _NEWIMAGE(ScreenWidth, ScreenHeight, 32)
SaveBuffer = _NEWIMAGE(ScreenWidth, ScreenHeight, 32)
LEDImageOn = _NEWIMAGE(LEDPixelSize, LEDPixelSize, 32)
LEDImageOff = _NEWIMAGE(LEDPixelSize, LEDPixelSize, 32)

SCREEN MainScreen

' *** Get read to draw the turned-off LED bulb
_DEST LEDImageOff

' *** Draw LED background
LINE (0, 0)-(LEDPixelSize, LEDPixelSize), _RGB(32, 0, 0), BF

' *** Draw grey-filled gradient circle that represents the turned-off LED bulb
FOR CircleSize% = LEDBulbSize TO 1 STEP -1
   Red% = 64 - CircleSize% * 6
   Green% = 0 ' Red%
   Blue% = 0 'Red%
   Colr& = _RGB(Red%, Green%, Blue%)
   CIRCLE (LEDPixelSize / 2 - 1, LEDPixelSize / 2 - 1), CircleSize% / 2 + 0.05, Colr&
   PAINT (LEDPixelSize / 2 - 1, LEDPixelSize / 2 - 1), Colr&, Colr&
NEXT


' *** Get ready to draw the turned-on LED bulb
_DEST LEDImageOn

' *** Draw LED Background
LINE (0, 0)-(LEDPixelSize, LEDPixelSize), _RGB(64, 0, 0), BF

' *** Draw filled gradient circles that represents the turned-on LED bulb
FOR CircleSize% = LEDBulbSize TO 1 STEP -1
   Red% = (LEDBulbSize - CircleSize%) * 35 + 140
   Green% = 0 'Red%
   Blue% = 0
   Colr& = _RGB(Red%, Green%, Blue%)
   CIRCLE (LEDPixelSize / 2 - 1, LEDPixelSize / 2 - 1), CircleSize% / 2 + 0.05, Colr&
   PAINT (LEDPixelSize / 2 - 1, LEDPixelSize / 2 - 1), Colr&, Colr&
NEXT

' Due to some strange thing with printing a text character to an exact text character size image,
' we can not print text straight to the characters image. So here we draw it to the backbuffer.
_DEST BackBuffer

' *** Create images for each character
FOR C = 32 TO 126

   CharLength% = _PRINTWIDTH(CHR$(C))
   Character(C).Image = _NEWIMAGE(CharLength%, 16, 32)
   Character(C).ImageWidth = CharLength%
   Character(C).ImageHeight = 16

   ' If you change this color value, you must change it below in the testing part. Please note, the
   ' color value cannot be &HFFFFFFFF. When we use POINT below, if there is an error reading the pixel
   ' color, it returns &HFFFFFFFF or -1. This is a single-color LED sample, so the color used is not
   ' at all important.
   COLOR &HFFFF0000
   LOCATE 1, 1
   PRINT CHR$(C)

   ' Now we copy the text image over to the character image.
   _PUTIMAGE (0, 0), BackBuffer, Character(C).Image

NEXT


' *** Draw blank LED panel to the backbuffer.
FOR PanelHeight~% = 0 TO LEDPanelHeight - 1
   FOR PanelWidth~% = 0 TO LEDPanelWidth - 1
       _PUTIMAGE (PanelWidth~% * LEDPixelSize, PanelHeight~% * LEDPixelSize), LEDImageOff, BackBuffer
   NEXT
NEXT

' Copy the back buffer over to the main screen image.
_PUTIMAGE (0, 0), BackBuffer, MainScreen



' *************************************************************************************************
' *                   MODIFIED VERSION OF FORUM MEMBER'S artmaker43 MODIFICATION                  *
' *************************************************************************************************


' *** Predefine the LED Message text file. No need to ask the user for it, and it speeds things up.
File$ = "LED_Messages.txt"

' *** See if the file exists before we try to open it.
IF _FILEEXISTS(File$) THEN

   ' *** The file exists, so get the next file handle to use.
   FileHandle% = FREEFILE

   ' *** Open the file for reading.
   OPEN "I", FileHandle%, File$

   ' *** Check to see if there are any messages in the file.
   IF LOF(FileHandle%) > 0 THEN

       ' *** If there is, then read all the message lines in the file, if there are any.
       DO UNTIL EOF(FileHandle%)

           ' *** Enlarge the Message ARRAY to accommodate the next line.
           REDIM _PRESERVE SHARED Message(UBOUND(Message) + 1) AS STRING

           ' *** Read the new line.
           LINE INPUT #FileHandle%, Message(UBOUND(Message))

           ' *** If the message line is of zero length, then make it have a space character
           ' *** to create a time delay until the next message is show.
           IF Message(UBOUND(Message)) = "" THEN Message(UBOUND(Message)) = " "

       LOOP

   END IF

   ' *** Close all open files.
   CLOSE

END IF

' *** Check to see if there are any messages in our array, and if not, create a message
' *** to let the user know there are no messages available at this time.
IF UBOUND(message) < 0 THEN

   ' *** Since there are no messages in the file, then let the user know on screen.
   REDIM _PRESERVE SHARED Message(0) AS STRING
   Message(0) = "---=== NO MESSAGES AVAILABLE AT THIS TIME ===---"

END IF


' *************************************************************************************************
' *                                   BACK TO WALTERSMIND CODE                                    *
' *************************************************************************************************



CurrentLine = 0 ' We will start off with the zero-index of the message$ array.
CurrentCharacter = 1 ' Set to the first character of the line. It cannot be zero.
CurrentPixelCounter = 30 ' This is the first LED-pixel delay value. It is lower than the default value.
CurrentCharacterPixel = 0 ' Always start with zero here.

' *** Now the setup part is done, let's now animate our happy little LED sign.
DO

   _LIMIT 25

   ' Get the current character in the line
   MIDCharacter% = ASC(MID$(Message(CurrentLine), CurrentCharacter, 1))

   ' Change the source to the current characters image
   _SOURCE Character(MIDCharacter%).Image

   ' Check to see if we are still in the display delay.
   IF CurrentPixelCounter > 0 THEN

       ' If we are here than scroll everything left by pixel amount until we are no longer in the delay.

       CurrentPixelCounter = CurrentPixelCounter - PixelSpeed

       ' Since the source and destination image cannot be the same, we have to copy part of the LED image
       ' we know will still be on screen when scrolled, to the save buffer.
       _PUTIMAGE (0, 0), BackBuffer, SaveBuffer, (LEDPixelSize * PixelSpeed, 0)-(ScreenWidth, ScreenHeight)

       ' Copy the save buffer image back into the back buffer at the far left of the image. This simulates scrolling.
       _PUTIMAGE (0, 0), SaveBuffer, BackBuffer

   ELSE

       ' Since the source and destination image cannot be the same, we have to copy part of the LED image
       ' we know will still be on screen when scrolled, to the save buffer.
       _PUTIMAGE (0, 0), BackBuffer, SaveBuffer, (LEDPixelSize * PixelSpeed, 0)-(ScreenWidth, ScreenHeight)

       ' Copy the save buffer image back into the back buffer at the far left of the image. This simulates scrolling.
       _PUTIMAGE (0, 0), SaveBuffer, BackBuffer

       ' X% is basically 0 to PixelSpeed-1.
       FOR PixelX% = (LEDPanelWidth - PixelSpeed) TO (LEDPanelWidth - 1)

           ' *** Let's draw the vertical slice of the character defined by "PixelSpeed" first.
           FOR PixelY% = 0 TO LEDPanelHeight - 1

               ' Get the current character pixel X position.
               CharX% = CurrentCharacterPixel + (PixelX% - (LEDPanelWidth - PixelSpeed))

               ' Get the color of the current pixel in the characters image.
               CurrentPixelState = POINT(CharX%, PixelY%)

               ' Check to see if it contains the previously defined color value.
               IF CurrentPixelState = &HFFFF0000 THEN

                   ' If it does, draw the LED ON image.
                   _PUTIMAGE (PixelX% * LEDPixelSize, PixelY% * LEDPixelSize), LEDImageOn, BackBuffer

               ELSE

                   ' If it doesn't, then draw the LED OFF image.
                   _PUTIMAGE (PixelX% * LEDPixelSize, PixelY% * LEDPixelSize), LEDImageOff, BackBuffer

               END IF
           NEXT
       NEXT

       ' Get the next character pixel X-offset.
       CurrentCharacterPixel = CurrentCharacterPixel + PixelSpeed

       ' See if it is outside the current characters width.
       IF CurrentCharacterPixel >= (Character(MIDCharacter%).ImageWidth) THEN

           ' If it is, reset the X-position back to 0.
           CurrentCharacterPixel = 0

           ' Go to the next character in the current line.
           CurrentCharacter = CurrentCharacter + 1

           ' See if exuasted the characters in this line.
           IF CurrentCharacter > LEN(Message(CurrentLine)) THEN

               ' We have, so go to the next line.
               CurrentLine = CurrentLine + 1

               ' Reset the character position to the first position.
               CurrentCharacter = 1

               ' Here we setup the delay to show the next line
               CurrentPixelCounter = CurrentPixelDelay

               ' Check to see if we ran out of lines.
               IF CurrentLine > UBOUND(Message) THEN

                   ' We have so reset the current line to the first one in our array.
                   CurrentLine = 0

               END IF
           END IF
       END IF
   END IF

   ' Copy the complete back buffer on to the main screen.
   _PUTIMAGE (0, 0), BackBuffer, MainScreen

   ' Show it.
   _DISPLAY

LOOP UNTIL _KEYHIT
SYSTEM

[attachment=152]


Here is the YouTube video of the demo.





Download the "LED_Messages.txt" file for the user defined message, and to see how to create your own messages.


Walter Whitman
The Joyful Programmer