Browse Source

iot.characterlcd. Initial Import.

woollybah 5 years ago
parent
commit
0bbd3536a5
1 changed files with 789 additions and 0 deletions
  1. 789 0
      characterlcd.mod/characterlcd.bmx

+ 789 - 0
characterlcd.mod/characterlcd.bmx

@@ -0,0 +1,789 @@
+' Copyright (c) .NET Foundation and Contributors
+' Copyright (c) 2019 Bruce A Henderson
+' 
+' All rights reserved.
+' 
+' Permission is hereby granted, free of charge, to any person obtaining a copy
+' of this software and associated documentation files (the "Software"), to deal
+' in the Software without restriction, including without limitation the rights
+' to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+' copies of the Software, and to permit persons to whom the Software is
+' furnished to do so, subject to the following conditions:
+' 
+' The above copyright notice and this permission notice shall be included in all
+' copies or substantial portions of the Software.
+' 
+' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+' SOFTWARE.
+' 
+SuperStrict
+
+Rem
+bbdoc: Character LCDs.
+End Rem
+Module iot.CharacterLCD
+
+Import iot.core
+Import brl.color
+
+
+Rem
+bbdoc: Abstraction layer for accessing the lcd IC.
+End Rem
+Type TLCDInterface Implements IDisposable Abstract
+
+	Field waitMultiplier:Double = 1.0
+	Field backlightOn:Int
+	Field eightBitMode:Int
+
+	Method SendData(value:Byte) Abstract
+	Method SendCommand(command:Byte) Abstract
+	Method SendData(buffer:Byte Ptr, size:Size_T) Abstract
+	Method SendCommands(buffer:Byte Ptr, size:Size_T) Abstract
+
+	Method GetWaitMultiplier:Double()
+		Return waitMultiplier
+	End Method
+	
+	Method SetWaitMultiplier(value:Double)
+		waitMultiplier = value
+	End Method
+	
+	Method IsBacklightOn:Int()
+		Return backlightOn
+	End Method
+	
+	Method SetBacklightOn(value:Int)
+		backlightOn = value
+	End Method
+	
+	Method GetEightBitMode:Int()
+		Return eightBitMode
+	End Method
+
+	Method WaitForNotBusy(microseconds:Int)
+		' TODO
+	End Method
+	
+	
+	
+End Type
+
+Rem
+bbdoc: Standard direct pin access to the HD44780 controller.
+End Rem
+Type TLCDGpio Extends TLCDInterface
+
+	Field ReadOnly rsPin:Int
+	Field ReadOnly rwPin:Int
+	Field ReadOnly enablePin:Int
+	Field ReadOnly backlight:Int
+
+	Field backlightBrightness:Int
+	Field lastByte:Byte
+	Field useLastByte:Int
+	
+	Field ReadOnly dataPins:Int[]
+	Field controller:TGpioController
+	Field pinBuffer:SPinValuePair[8]
+	
+	Method New(registerSelectPin:Int, enablePin:Int, dataPins:Int[], backlightPin:Int = -1, backlightBrightness:Float = 1.0, readWritePin:Int = -1, controller:TGpioController = Null)
+		rsPin = registerSelectPin
+		rwPin = enablePin
+		Self.dataPins = dataPins
+		backlight = backlightPin
+		Self.backlightBrightness = backlightBrightness
+		
+		If dataPins.length = 8 Then
+			eightBitMode = True
+		Else If dataPins.length <> 4 Then
+			Throw New TArgumentException("")
+		End If
+		
+		If controller Then
+			Self.controller = controller
+		Else
+			Self.controller = New TGpioController
+		End If
+		
+		Initialize()
+	End Method
+	
+	Method Initialize()
+		' prep the pin
+		controller.OpenPin(rsPin, EPinMode.Output)
+		
+		If rwPin <> -1 Then
+			controller.OpenPin(rwPin, EPinMode.Output)
+		
+			' Set to write. Once we enable reading have reading pull high and reset
+			' after reading to give maximum performance to write (i.e. assume that
+			' the pin is low when writing).
+			controller.Write(rwPin, EPinValue.Low)
+		End If
+		
+		If backlight <> -1 Then
+			controller.OpenPin(backlight, EPinMode.Output)
+			If backlightBrightness > 0 Then
+				' Turn on the backlight
+				controller.Write(backlight, EPinValue.High)
+			End If
+		End If
+		
+		controller.OpenPin(enablePin, EPinMode.Output)
+		
+		For Local i:Int = 0 Until dataPins.length
+			controller.OpenPin(dataPins[i], EPinMode.Output)
+		Next
+		
+		' The HD44780 self-initializes when power is turned on to the following settings:
+		' 
+		'  - 8 bit, 1 line, 5x7 font
+		'  - Display, cursor, and blink off
+		'  - Increment with no shift
+		'
+		' It is possible that the initialization will fail if the power is not provided
+		' within specific tolerances. As such, we'll always perform the software based
+		' initialization as described on pages 45/46 of the HD44780 data sheet. We give
+		' a little extra time to the required waits as described.
+
+		If dataPins.length = 8 Then
+			' Init to 8 bit mode (this is the default, but other drivers may set the controller to 4 bit mode, so reset to be safe.)
+			Delay(50)
+			WriteBits($30, 8)
+			Delay(5)
+			WriteBits($30, 8)
+			Delay(100)
+			WriteBits($30, 8)
+		Else
+			' Init to 4 bit mode, setting rspin to low as we're writing 4 bits directly.
+			' (Send writes the whole byte in two 4bit/nibble chunks)
+			controller.Write(rsPin, EPinValue.Low)
+			Delay(50)
+			WriteBits($3, 4)
+			Delay(5)
+			WriteBits($3, 4)
+			Delay(100)
+			WriteBits($3, 4)
+			WriteBits($2, 4)			
+		End If
+		
+		' The busy flag can NOT be checked until this point.
+	End Method
+	
+	Method IsBacklightOn:Int()
+		Return backlight <> -1 And controller.Read(backlight) = EPinValue.High
+	End Method
+	
+	Method SetBackLigntOn(value:Int)
+		If backlight <> -1 Then
+			If value Then
+				controller.Write(backlight, EPinValue.High)
+			Else
+				controller.Write(backlight, EPinValue.Low)
+			End If
+		End If
+	End Method
+	
+	Method SendData(value:Byte)
+		controller.Write(rsPin, EPinValue.High)
+		SendByte(value)
+	End Method
+	
+	Method SendCommand(command:Byte)
+		controller.Write(rsPin, EPinValue.Low)
+		SendByte(command)
+	End Method
+	
+	Method SendData(buffer:Byte Ptr, size:Size_T)
+		controller.Write(rsPin, EPinValue.High)
+		For Local i:Int = 0 Until size
+			SendByte(buffer[i])
+		Next
+	End Method
+	
+	Method SendCommands(buffer:Byte Ptr, size:Size_T)
+		controller.Write(rsPin, EPinValue.Low)
+		For Local i:Int = 0 Until size
+			SendByte(buffer[i])
+		Next		
+	End Method
+	
+	Method SendByte(value:Byte)
+		If dataPins.Length = 8 Then
+			WriteBits(value, 8)
+		Else
+			WriteBits(Byte(value Shr 4), 4)
+			WriteBits(value, 4)
+		End If
+		
+		WaitForNotBusy(37)
+	End Method
+	
+	Method WriteBits(bits:Byte, count:Int)
+		Local changedCount:Int
+		For Local i:Int = 0 Until count
+			Local newBit:Int = (bits Shr i) & 1
+			If useLastByte Then
+				' Each bit change takes ~23μs, so only change what we have to
+				' This is particularly impactful when using all 8 data lines.
+				Local oldBit:Int = (lastByte Shr i) & 1
+				If oldBit <> newBit Then
+					pinBuffer[changedCount] = New SPinValuePair(dataPins[i], newBit)
+				End If
+				changedCount:+ 1
+			Else
+				pinBuffer[changedCount] = New SPinValuePair(dataPins[i], newBit)
+				changedCount:+ 1
+			End If
+		Next
+		
+		If changedCount > 0 Then
+			controller.Write(pinBuffer, changedCount)
+		End If
+		
+		useLastByte = True
+		lastByte = bits
+		
+		' Enable pin needs to be high for at least 450ns when running on 3V
+		' and 230ns on 5V. (PWeh on page 49/52 and Figure 25 on page 58)
+		controller.Write(enablePin, EPinValue.High)
+		UDelay(1)
+		controller.Write(enablePin, EPinValue.Low)
+	End Method
+	
+	Method Dispose()
+		If controller Then
+			controller.Dispose()
+		End If
+	End Method
+	
+End Type
+
+Rem
+bbdoc: 
+End Rem
+Type TLCDI2c Extends TLCDInterface
+
+	Field ReadOnly device:TI2cDevice
+	
+	Method New(device:TI2cDevice)
+		Self.device = device
+	End Method
+
+	Method GetEightBitMode:Int() Override
+		Return True
+	End Method
+	
+	Method IsBacklightOn:Int() Override
+		Throw New TNotImplementedException
+	End Method
+	
+	Method SetBacklightOn(value:Int) Override
+		Throw New TNotImplementedException
+	End Method
+	
+	Method SendCommand(command:Byte) Override
+		Local buffer:Byte Ptr = StackAlloc(2)
+		buffer[0] = 0
+		buffer[1] = command
+		device.Write(buffer, 2)
+	End Method
+	
+	Method SendCommands(commands:Byte Ptr, size:Size_T) Override
+		If size > 20 Then
+			Throw New TArgumentOutOfRangeException("Too many commands in one request.")
+		End If
+		
+		Local buffer:Byte Ptr = StackAlloc(size + 1)
+		buffer[0] = 0
+		MemCopy(buffer + 1, commands, size)
+		device.Write(buffer, size + 1)
+	End Method
+
+	Method SendData(value:Byte) Override
+		Local buffer:Byte Ptr = StackAlloc(2)
+		buffer[0] = EControlByteFlags.RegisterSelect.Ordinal()
+		buffer[1] = value
+		device.Write(buffer, 2)
+	End Method
+
+	Method SendData(data:Byte Ptr, size:Size_T) Override
+		' limit sending to 20 byte chunks
+		Local buffer:Byte Ptr = StackAlloc(21)
+		buffer[0] = EControlByteFlags.RegisterSelect.Ordinal()
+		Local offset:Int
+		
+		While size > 0
+			Local toCopy:Size_T = Min(size, 20)
+			MemCopy(buffer + 1, data + offset, toCopy)
+
+			device.Write(buffer, toCopy + 1)
+			
+			offset :+ toCopy
+			size :- toCopy
+		Wend
+		
+	End Method
+
+	Method Dispose()
+	End Method
+	
+End Type
+
+Enum EControlByteFlags:Byte Flags
+	ControlByteFollows = $80
+	RegisterSelect = $40
+End Enum
+
+Rem
+bbdoc: Supports LCD character displays compatible with the HD44780 LCD controller/driver.
+about: Also supports serial interface adapters such as the MCP23008.
+End Rem
+Type THd44780 Implements IDisposable
+
+	Const CLEAR_DISPLAY_COMMAND:Int = $0001
+	Const RETURN_HOME_COMMAND:Int = $0002
+	Const SET_CG_RAM_ADDRESS_COMMAND:Int = $0040
+	Const SET_DD_RAM_ADDRESS_COMMAND:Int = $0080
+
+	Field displayFunction:EDisplayFunction = EDisplayFunction.Command
+	Field displayControl:EDisplayControl = EDisplayControl.Command
+	Field displayMode:EDisplayEntryMode = EDisplayEntryMode.Command
+
+	Field rowOffsets:Byte[]
+	
+	Field lcdInterface:TLCDInterface
+	Field size:SSize
+	
+	Method GetSize:SSize()
+		Return size
+	End Method
+	
+	Method New(size:SSize, lcdInterface:TLCDInterface)
+		Self.size = size
+		Self.lcdInterface = lcdInterface
+		
+		If lcdInterface.eightBitMode Then
+			displayFunction :| EDisplayFunction.EightBit
+		End If
+		
+		Initialize(size.height)
+		rowOffsets = InitializeRowOffsets(size.height)
+	End Method
+	
+	Method Initialize(rows:Int)
+		' While the chip supports 5x10 pixel characters for one line displays they
+		' don't seem to be generally available. Supporting 5x10 would require extra
+		' support for CreateCustomCharacter
+		
+		If GetTwoLineMode(rows) Then
+			displayFunction :| EDisplayFunction.TwoLine
+		End If
+
+		displayControl :| EDisplayControl.DisplayOn
+		displayMode :| EDisplayEntryMode.Increment
+	
+		Local commands:Byte Ptr = StackAlloc(4)
+		commands[0] = displayFunction.Ordinal()
+		commands[1] = displayControl.Ordinal()
+		commands[2] = displayMode.Ordinal()
+		commands[3] = CLEAR_DISPLAY_COMMAND
+		
+		SendCommands(commands, 4)
+	End Method
+	
+	Method SendData(value:Byte)
+		lcdInterface.SendData(value)
+	End Method
+	
+	Method SendCommand(command:Byte)
+		lcdInterface.SendCommand(command)
+	End Method
+	
+	Method SendData(buffer:Byte Ptr, size:Size_T)
+		lcdInterface.SendData(buffer, size)
+	End Method
+	
+	Method SendCommands(buffer:Byte Ptr, size:Size_T)
+		lcdInterface.SendCommands(buffer, size)
+	End Method
+	
+	Method GetTwoLineMode:Int(rows:Int)
+		Return rows > 1
+	End Method
+	
+	Method InitializeRowOffsets:Byte[](rows:Int)
+		Local rowOffsets:Byte[]
+	
+		Select rows
+			Case 1
+				rowOffsets = New Byte[1]
+			Case 2
+				rowOffsets = [0:Byte, 64:Byte]
+			Case 4
+				rowOffsets = [0:Byte, 64:Byte, 20:Byte, 84:Byte]
+			Default
+				Throw New TArgumentOutOfRangeException("rows")
+		End Select
+	
+		Return rowOffsets
+	End Method
+	
+	Method WaitForNotBusy(microseconds:Int)
+		lcdInterface.WaitForNotBusy(microseconds)
+	End Method
+	
+	Rem
+	bbdoc: Clears the LCD, returning the cursor to home and unshifting if shifted.
+	about: Will also set to Increment.
+	End Rem
+	Method Clear()
+		SendCommand(CLEAR_DISPLAY_COMMAND)
+		WaitForNotBusy(2000)
+	End Method
+	
+	Rem
+	bbdoc: Moves the cursor to the first line and first column, unshifting if shifted.
+	End Rem
+	Method Home()
+		SendCommand(RETURN_HOME_COMMAND)
+		WaitForNotBusy(1520)
+	End Method
+	
+	Rem
+	bbdoc: Moves the cursor to an explicit column and row position.
+	End Rem
+	Method SetCursorPosition(Left:Int, top:Int)
+		Local rows:Int = rowOffsets.length
+		
+		If top < 0 Or top >= rows Then
+			Throw New TArgumentOutOfRangeException("rows")
+		End If
+		
+		Local newAddress:Int = Left + rowOffsets[top]
+		If Left < 0 Or (rows = 1 And newAddress >= 80) Or (rows > 1 And newAddress >= 104) Then
+			Throw New TArgumentOutOfRangeException("left")
+		End If
+		
+		SendCommand(Byte(SET_DD_RAM_ADDRESS_COMMAND | newAddress))
+	End Method
+	
+	Rem
+	bbdoc: Determines whether the display is on or not.
+	returns: #True if the display is on, #False otherwise.
+	End Rem
+	Method IsDisplayOn:Int()
+		Return (displayControl & EDisplayControl.DisplayOn).Ordinal()
+	End Method
+	
+	Rem
+	bbdoc: Enable/disable the display.
+	End Rem
+	Method SetDisplayOn(value:Int)
+		If value Then
+			displayControl :| EDisplayControl.CursorOn
+		Else
+			displayControl :& ~EDisplayControl.CursorOn
+		End If
+		SendCommand(displayControl.Ordinal())
+	End Method
+	
+	Rem
+	bbdoc: Determines whether the underlins cursor is visible or not.
+	returns: #True if the underline cursor is visible, #False otherwise.
+	End Rem
+	Method IsUnderlineCursorVisible:Int()
+		Return (displayControl & EDisplayControl.CursorOn).Ordinal()
+	End Method
+	
+	Rem
+	bbdoc: Enable/disable the underline cursor.
+	End Rem
+	Method SetUnderlineCursorVisible(value:Int)
+		If value Then
+			displayControl :| EDisplayControl.CursorOn
+		Else
+			displayControl :& ~EDisplayControl.CursorOn
+		End If
+		SendCommand(displayControl.Ordinal())
+	End Method
+	
+	Rem
+	bbdoc: Determines whether the blinking cursor is visible or not.
+	returns: #True if the blinking cursor is visible, #False otherwise.
+	End Rem
+	Method IsBlinkingCursorVisible:Int()
+		Return (displayControl & EDisplayControl.BlinkOn).Ordinal()
+	End Method
+	
+	Rem
+	bbdoc: Enable/disable the blinking cursor.
+	End Rem
+	Method SetBlinkingCursorVisible(value:Int)
+		If value Then
+			displayControl :| EDisplayControl.BlinkOn
+		Else
+			displayControl :& ~EDisplayControl.BlinkOn
+		End If
+		SendCommand(displayControl.Ordinal())
+	End Method
+	
+	Rem
+	bbdoc: 
+	End Rem
+	Method GetAutoShift:Int()
+		Return (displayMode & EDisplayEntryMode.DisplayShift).Ordinal()
+	End Method
+	
+	Rem
+	bbdoc: 
+	End Rem
+	Method SetAutoShift(value:Int)
+		If value Then
+			displayMode :| EDisplayEntryMode.DisplayShift
+		Else
+			displayMode :& ~EDisplayEntryMode.DisplayShift
+		End If
+		SendCommand(displayControl.Ordinal())
+	End Method
+	
+	Rem
+	bbdoc: 
+	End Rem
+	Method GetIncrement:Int()
+		Return (displayMode & EDisplayEntryMode.Increment).Ordinal()
+	End Method
+	
+	Rem
+	bbdoc: 
+	End Rem
+	Method SetIncrement(value:Int)
+		If value Then
+			displayMode :| EDisplayEntryMode.Increment
+		Else
+			displayMode :& ~EDisplayEntryMode.Increment
+		End If
+		SendCommand(displayControl.Ordinal())
+	End Method
+	
+	Rem
+	bbdoc: 
+	End Rem
+	Method ShiftDisplayLeft()
+		SendCommand((EDisplayShift.Command | EDisplayShift.Display).Ordinal())
+	End Method
+	
+	Rem
+	bbdoc: 
+	End Rem
+	Method ShiftDisplayRight()
+		SendCommand((EDisplayShift.Command | EDisplayShift.Display | EDisplayShift.Right).Ordinal())
+	End Method
+
+	Rem
+	bbdoc: 
+	End Rem
+	Method ShiftCursorLeft()
+		SendCommand((EDisplayShift.Command | EDisplayShift.Display).Ordinal())
+	End Method
+	
+	Rem
+	bbdoc: 
+	End Rem
+	Method ShiftCursorRight()
+		SendCommand((EDisplayShift.Command | EDisplayShift.Display | EDisplayShift.Right).Ordinal())
+	End Method
+	
+	Rem
+	bbdoc: Writes text to the display.
+	End Rem
+	Method Write(value:String)
+		Local buf:Byte Ptr = value.ToCString()
+		SendData(buf, Size_T(value.Length))
+		MemFree(buf)
+	End Method
+	
+	Method Dispose()
+		If lcdInterface Then
+			lcdInterface.Dispose()
+			lcdInterface = Null
+		End If
+	End Method
+	
+End Type
+
+Rem
+bbdoc: 16x2 HD44780 compatible character LCD display.
+End Rem
+Type TLcd1602 Extends THd44780
+
+	Rem
+	bbdoc: Constructs a new HD44780 based 16x2 LCD controller, using GPIO pins.
+	End Rem
+	Method New(registerSelectPin:Int, enablePin:Int, dataPins:Int[] , backlightPin:Int = -1, backlightBrightness:Float = 1.0, readWritePin:Int = -1, controller:TGpioController = Null)
+		Super.New(New SSize(16, 2), New TLCDGpio(registerSelectPin, enablePin, dataPins, backlightPin, backlightBrightness, readWritePin, controller))
+	End Method
+	
+	Rem
+	bbdoc: Constructs a new HD44780 based 16x2 LCD controller with integrated I2c support.
+
+	End Rem
+	Method New(device:TI2cDevice)
+		Super.New(New SSize(16, 2), New TLCDI2c(device))
+	End Method
+
+End Type
+
+Rem
+bbdoc: Supports I2c LCDs with I2c RGB backlight, such as the Grove - LCD RGB Backlight (16x2 LCD character display with RGB backlight).
+End Rem
+Type TLcdRgb1602 Extends TLcd1602
+
+	Field rgbDevice:TI2cDevice
+	
+	Field currentColor:SColor8
+	Field backlightOn:Int = True
+
+	Method New(lcdDevice:TI2cDevice, rgbDevice:TI2cDevice)
+		Super.New(lcdDevice)
+		Self.rgbDevice = rgbDevice
+		
+		InitRgb()
+	End Method
+
+	Rem
+	bbdoc: Enables or disables the backlight.
+	End Rem
+	Method SetBacklightOn(value:Int)
+		If value Then
+			ForceSetBacklightColor(currentColor)
+		Else
+			ForceSetBacklightColor(SCOlor8.Black)
+		End If
+		backlightOn = value
+	End Method
+	
+	Rem
+	bbdoc: Returns #True if the backlight is on, #False otherwise.
+	End Rem
+	Method IsBacklightOn:Int()
+		Return backlightOn
+	End Method
+
+	Rem
+	bbdoc: Sets the backlight color.
+	End Rem
+	Method SetBacklightColor(color:SColor8)
+		If Not backlightOn Then
+			Return 
+		End If
+		
+		ForceSetBacklightColor(color)
+		currentColor = color
+	End Method
+
+Private
+	Method InitRgb()
+		' backlight init
+		SetRgbRegister(ERgbRegisters.REG_MODE1, 0)
+		
+		' set LEDs controllable by both PWM and GRPPWM registers
+		SetRgbRegister(ERgbRegisters.REG_LEDOUT, $FF)
+		
+		' set MODE2 values
+		SetRgbRegister(ERgbRegisters.REG_MODE2, $20)
+		
+		SetBacklightColor(SColor8.White)
+	End Method
+	
+	Method SetRgbRegister(addr:ERgbRegisters, value:Byte)
+		Local buffer:Byte Ptr = StackAlloc(2)
+		buffer[0] = addr.Ordinal()
+		buffer[1] = value
+		rgbDevice.Write(buffer, 2)
+	End Method
+
+	Method ForceSetBacklightColor(color:SColor8)
+		SetRgbRegister(ERgbRegisters.REG_RED, color.r)
+		SetRgbRegister(ERgbRegisters.REG_GREEN, color.g)
+		SetRgbRegister(ERgbRegisters.REG_BLUE, color.b)
+	End Method
+Public
+	
+	Method Dispose()
+		If rgbDevice Then
+			rgbDevice.Dispose()
+		End If
+	End Method
+	
+End Type
+
+
+Rem
+bbdoc: 20x4 HD44780 compatible character LCD display.
+End Rem
+Type TLcd2004 Extends THd44780
+
+	Rem
+	bbdoc: Constructs a new HD44780 based 20x4 LCD controller.
+	End Rem
+	Method New(registerSelectPin:Int, enablePin:Int, dataPins:Int[] , backlightPin:Int = -1, backlightBrightness:Float = 1.0, readWritePin:Int = -1, controller:TGpioController = Null)
+		Super.New(New SSize(20, 4), New TLCDGpio(registerSelectPin, enablePin, dataPins, backlightPin, backlightBrightness, readWritePin, controller))
+	End Method
+
+End Type
+
+
+Struct SSize
+	Field width:Int
+	Field height:Int
+	
+	Method New(width:Int, height:Int)
+		Self.width = width
+		Self.height = height
+	End Method
+	
+End Struct
+
+
+Enum ERgbRegisters:Byte
+	REG_MODE1 = $00
+	REG_MODE2 = $01
+	REG_LEDOUT = $08
+	REG_RED = $04
+	REG_GREEN = $03
+	REG_BLUE = $02
+End Enum
+
+Enum EDisplayEntryMode:Byte Flags
+	DisplayShift = $1
+	Increment = $2
+	Command = $4
+End Enum
+
+Enum EDisplayControl:Byte Flags
+	BlinkOn = $1
+	CursorOn = $2
+	DisplayOn = $4
+	Command = $8
+End Enum
+
+Enum EDisplayShift:Byte Flags
+	Right = $04
+	Display = $08
+	Command = $10
+End Enum
+
+Enum EDisplayFunction:Byte Flags
+	ExtendedInstructionSet = $01
+	Font5x10 = $04
+	TwoLine = $08
+	EightBit = $10
+	Command = $20
+End Enum