I was searching the internet, and a colour TFT display caught my eye that was circular. Apparently, they have been available for some time, but it was the very first time I had seen one, and it triggered an idea for an emulator of one of my favourite display valves (tubes), from yester-year. The EM34 'Magic Eye" valve that indicates a voltage to it by a circular green phosphorus display that opens and closes, and with my love of old electronic valve equipment, I started work on it.
Below is an image of the CG9A01 circular TFT I used for the emulator. It uses an SPI interface, that can operate extremely fast, and is very simple to control.
Below are two images of the EM34 valve, one showing the whole component,and one showing it illuminated:
As can be seen from the above illuminated image, the circular colour TFT display is ideal for an emulation of a circular phosphorus green valve, and the code listing for the emulator written in the Positron8 BASIC Compiler, for a PIC18F26K40 device is listed below:
'
' /\\\\\\\\\
' /\\\///////\\\
' \/\\\ \/\\\ /\\\ /\\\
' \/\\\\\\\\\\\/ /\\\\\ /\\\\\\\\\\ /\\\\\\\\ /\\\\\\\\\\\ /\\\\\\\\\\\ /\\\\\\\\\
' \/\\\//////\\\ /\\\///\\\ \/\\\////// /\\\/////\\\ \////\\\//// \////\\\//// \////////\\\
' \/\\\ \//\\\ /\\\ \//\\\ \/\\\\\\\\\\ /\\\\\\\\\\\ \/\\\ \/\\\ /\\\\\\\\\\
' \/\\\ \//\\\ \//\\\ /\\\ \////////\\\ \//\\/////// \/\\\ /\\ \/\\\ /\\ /\\\/////\\\
' \/\\\ \//\\\ \///\\\\\/ /\\\\\\\\\\ \//\\\\\\\\\\ \//\\\\\ \//\\\\\ \//\\\\\\\\/\\
' \/// \/// \///// \////////// \////////// \///// \///// \////////\//
' Let's find out together what makes a PIC Tick!
'
' An EM34 (6U5) 'Magic Eye' valve, digital emulator, using a circular CG9A01 Graphic LCD on a PIC18FxxK40 device.
' An ADC input can be used to move the EM34 image on the LCD, or a simulation that creates a random value,
' that moves the EM34 image.
'
' Written by Les Johnson for the Positron8 BASIC compiler.
' https://sites.google.com/view/rosetta-tech/home
'
Device = 18F26K40 ' Tell the compiler what device to compile for
Declare Xtal = 64 ' Tell the compiler what frequency the device is operating at (in MHz)
Declare Float_Display_Type = Fast ' Tell the compiler to use the faster Floating Point to ASCII library sub
Declare Auto_Heap_Strings = On ' Make Strings "Heap" types, so they are placed after standard variables
Declare Auto_Variable_Bank_Cross = On ' Make sure all multi-byte variables remain within a single RAM bank
'
' Setup USART1 for debugging
'
Declare Hserial1_Baud = 9600
Declare HRSOut1_Pin = PORTC.6
'
' Define the pins used for the CG9A01 LCD display
'
$define CG9A01_CLK_Pin PORTC.3 ' Connects to the CG9A01 CLK pin (named SCL on some displays)
$define CG9A01_CLK_PPS_Pin Pin_C3 ' Define the CLK Pin to use for PPS
$define CG9A01_DTA_Pin PORTC.5 ' Connects to the CG9A01 DTA pin (named SDI on some displays)
$define CG9A01_DTA_PPS_Pin Pin_C5 ' Define the DTA Pin to use for PPS
$define CG9A01_CS_Pin PORTC.2 ' Connects to the CG9A01 CS pin
$define CG9A01_DC_Pin PORTC.1 ' Connects to the CG9A01 DC pin (named RS on some displays)
$define CG9A01_RST_Pin PORTC.0 ' Connects to the CG9A01 Reset pin
$define CG9A01_BLK_Pin PORTB.0 ' Connects to the CG9A01 BLK (Backlight) pin
'
' Setup the ADC input pin and SFR
'
$define ADC_Pin PORTA.0 ' The pin to use for the ADC input
$define ADC_SFR ANSELA.0 ' The ADC analogue SFR and bit, for the Port and Pin used
$define ADC_Pin_Analogue() ADC_SFR = 1 ' A meta-macro to set the ADC channel pin as analogue
$define ADC_Pin_Digital() ADC_SFR = 0 ' A meta-macro to set the ADC channel pin as digital
$define GLCD_Backlight_On() PinHigh CG9A01_BLK_Pin ' A meta-macro to illuminate the LCD's backlight
$define GLCD_Backlight_Off() PinLow CG9A01_BLK_Pin ' A meta-macro to extinguish the LCD's backlight
Include "CG9A01.inc" ' Load the CG9A01 library into the program
Include "HSPI_K40.inc" ' Load the SPI peripheral library into the program
'
' Convert a 24-bit RGB888 constant value into a 16-bit RGB565 constant value
'
$define RGB565(r,g,b) $eval ((((r) >> 3) & 0x1F) << 11) | ((((g) >> 2) & 0x3F) << 5) | (((b) >> 3) & 0x1F)
$define cBRIGHT_GREEN RGB565(0, 255, 100) ' Holds the RGB565 value for bright green
$define cMEDIUM_GREEN RGB565(0, 220, 60) ' Holds the RGB565 value for medium green
$define cDARK_GREEN RGB565(0, 80, 35) ' Holds the RGB565 value for dark green
$define cEM34_CENTER_X $eval (cCG9A_Width / 2) ' Holds the centre X position of the EM34 image
$define cEM34_CENTER_Y $eval (cCG9A_Height / 2) ' Holds the centre Y position of the EM34 image
$define cEM34_OUTER_RADIUS 100 ' Holds the outer radius of the EM34 image
$define cEM34_INNER_RADIUS 42 ' Holds the inner radius of the EM34 image
'
' Create global variables here
'
Dim EM34_wColour As Word ' Holds the colours of the EM34 display
Dim wADC_Raw As Word = 0 ' Holds the 10-bit ADC value
'-------------------------------------------------------------------------------------------------------
' The main program starts here
' Read the ADC on PORTA.0, and display the value on the Graphic LCD as an EM34 image.
' Or Simulate an ADC value moving with a random value, and display the value on the Graphic LCD as an EM34 image.
'
Main:
Setup() ' Setup the program and peripherals
Do ' Create a loop
'wADC_Raw = ADC_Read10(0) ' Read the ADC (Comment out if not using the ADC for the input)
'
' Use this code if not using the ADC input. It will create a slower random value between 0 and 1023
'
wADC_Raw = ((Random) // 1024): DelayMS 40
EM34_Display(wADC_Raw) ' Display the ADC value on the LCD as an EM34 valve
Loop ' Do it forever
'-------------------------------------------------------------------------------------------------------
' Setup the program and peripherals
' Input : None
' Output : None
' Notes : None
'
Proc Setup()
Clear ' Clear all user RAM before the program starts
'
' Setup the SPI1 peripheral (if used)
'
$ifndef _cSOFTWARE_SPI_ ' Is the CG9A01 library using bit-bashed SPI routines?
PPS_Unlock() ' No. So Unlock the PPS for the SPI peripheral
Set_PPSForSCK1(CG9A01_CLK_PPS_Pin) ' Setup the SPI1 peripheral's PPS, CLK for the LCD's SCK pin
Set_PPSForSDO1(CG9A01_DTA_PPS_Pin) ' Setup the SPI1 peripheral's PPS, SDO pin for the LCD's DTA pin
Set_PPSForSDI1(Pin_C4) ' Setup the SPI1 peripheral's PPS, SDI pin
HSPI1_Init_Mode0_MaxMHz() ' Setup the SPI1 peripheral to operate in Mode 0 at fastest speed
$endif
GLCD_Init() ' Initialise the CG9A01 LCD
GLCD_Rotate(0) ' Rotate the display
ADC_Pin_Analogue() ' Set the ADC channel pin as analogue
GLCD_Cls(clBlack) ' Clear the LCD with a black background
ADC_Setup() ' Setup the ADC peripheral
EM34_Init() ' Draw the initial EM34 image before moving it
EndProc
'-------------------------------------------------------------------------------------------------------
' Draw the initial EM34 image before moving it
' Input : None
' Output : None
' Notes : None
'
Proc EM34_Init()
Dim wAngle As Word
GLCD_Backlight_Off() ' Extinguish the LCD's backlight.
' So that it does not show the initial circle being drawn
For wAngle = 46 To 314 ' \
Draw_AngleLine(wAngle, cMEDIUM_GREEN) ' | Draw the top curve of the glowing display
Next ' /
For wAngle = 316 To 403 ' \
Draw_AngleLine(wAngle, cDARK_GREEN) ' | Draw the background curve of the glowing display
Next ' /
Draw_AngleLine(315, cBRIGHT_GREEN) ' \ Draw the bright lines at the ends of the moving display
Draw_AngleLine(45, cBRIGHT_GREEN) ' /
GLCD_Backlight_On() ' Illuminate the LCD's backlight
EndProc
'-------------------------------------------------------------------------------------------------------
' Draw the display image of the EM34 on the Graphic LCD
' Input : pADC_Value holds the 10-bit ADC value
' Output : None
' Notes : None
'
Proc EM34_Display(pADC_Value As Word)
Dim bPrevMoveAngle As Byte
Dim bNewMoveAngle As Byte
Dim fADC_Filtered As Float
Dim fLogValue As Float
Dim fTemp1 As Float
Dim fTemp2 As Float
Dim bLineAngle As fLogValue.Byte0
fADC_Filtered = (fADC_Filtered * 9.0) + pADC_Value ' \
fADC_Filtered = fADC_Filtered / 10.0 ' | ADC value filtering and mapping to display angle
fLogValue = Log10(fADC_Filtered + 1) ' /
fTemp1 = fADC_Filtered / 11 ' \
fTemp2 = fLogValue * 15.0 ' |
bNewMoveAngle = (fTemp1 + fTemp2) / 3 ' /
If bNewMoveAngle > 45 Then ' \
bNewMoveAngle = 45 ' | Make sure the value remains between 0 to 45
EndIf ' /
'
' Update the Display
'
If bNewMoveAngle > 0 Then ' Is there a value to display?
If bNewMoveAngle > bPrevMoveAngle Then ' Yes. So is bNewMoveAngle greater than bPrevMoveAngle?
For bLineAngle = bPrevMoveAngle To bNewMoveAngle - 1 ' \
Draw_AngleLine(315 + bLineAngle, cMEDIUM_GREEN) ' | Yes. So display the moving light
Draw_AngleLine(405 - bLineAngle, cMEDIUM_GREEN) ' /
Next
Else ' Otherwise...
For bLineAngle = bPrevMoveAngle DownTo bNewMoveAngle + 1' \
Draw_AngleLine(315 + bLineAngle, cDARK_GREEN) ' | Erase the moving light
Draw_AngleLine(405 - bLineAngle, cDARK_GREEN) ' /
Next
EndIf
Draw_AngleLine(315 + bNewMoveAngle, cBRIGHT_GREEN) ' \ Draw the brighter lines on the two moving lights
Draw_AngleLine(405 - bNewMoveAngle, cBRIGHT_GREEN) ' /
EndIf
bPrevMoveAngle = bNewMoveAngle
EndProc
'-------------------------------------------------------------------------------------------------------
' Draw a line at an angle
' Input : pAngle holds the angle of the line in degrees
' : pColour holds the colour of the line to draw
' : Constant: cEM34_INNER_RADIUS holds the starting position of the line
' : Constant: cEM34_OUTER_RADIUS holds the ending position of the line
' : Constants: cEM34_CENTER_X and cEM34_CENTER_Y holds the X and Y positions for the inner start of a line
' Output : None
' Notes : Uses a faster implementation of a line draw code
' : And uses flash memory tables for Sine and Cosine values for extra speed
'
Proc Draw_AngleLine(pAngle As Word, pColour As EM34_wColour)
Dim fSinVal As Float ' Holds the Sine value read from the flash memory table
Dim fCosVal As Float ' Holds the Cosine value read from the flash memory table
Dim wXpos As fSinVal.Word0
Dim wYpos As fSinVal.Word1
Dim wErr As fCosVal.Word0
Dim wYstep As fCosVal.SWord1
Dim tBwrd As Bit = 0
Dim wStartXpos As Word
Dim wStartYpos As Word
Dim wEndXpos As Word
Dim wEndYpos As Word
Dim wTemp1 As SWord
Dim wTemp2 As SWord
fSinVal = CRead32 fAngleSine_Table[pAngle] ' Read the Sine value from the flash memory table
fCosVal = CRead32 fAngleCos_Table[pAngle] ' Read the Cosine value from the flash memory table
wStartXpos = cEM34_CENTER_X + (fSinVal * cEM34_INNER_RADIUS) ' Find the X start position of the line
wStartYpos = cEM34_CENTER_Y + (fCosVal * cEM34_INNER_RADIUS) ' Find the Y start position of the line
wEndXpos = cEM34_CENTER_X + (fSinVal * cEM34_OUTER_RADIUS) ' Find the X end position of the line
wEndYpos = cEM34_CENTER_Y + (fCosVal * cEM34_OUTER_RADIUS) ' Find the Y end position of the line
wTemp1 = wEndYpos - wStartYpos
wTemp2 = wEndXpos - wStartXpos
wTemp1 = Abs(wTemp1)
wTemp2 = Abs(wTemp2)
If wTemp1 > wTemp2 Then
tBwrd = 1
Swap(wStartXpos, wStartYpos)
Swap(wEndXpos, wEndYpos)
EndIf
If wStartXpos > wEndXpos Then
Swap(wStartXpos, wEndXpos)
Swap(wStartYpos, wEndYpos)
EndIf
wXpos = wEndXpos - wStartXpos
wYpos = Abs(wEndYpos - wStartYpos)
wErr = wXpos / 2
wYstep = -1
If wStartYpos < wEndYpos Then
wYstep = 1
EndIf
Repeat
If tBwrd = 1 Then
GLCD_Pixel(wStartYpos, wStartXpos, pColour)
Else
GLCD_Pixel(wStartXpos, wStartYpos, pColour)
EndIf
wErr = wErr - wYpos
If wErr < 0 Then
wStartYpos = wStartYpos + wYstep
wErr = wErr + wXpos
EndIf
Inc wStartXpos
Until wStartXpos > wEndXpos
'
' A Flash memory table of floating point Sine values used for the angle calculation
'
Dim fAngleSine_Table As FlashF = {-0.00000,0.01745,0.03489,0.05233,0.06975,0.08715,0.10452,0.12186,0.13917,0.15643,
0.17364,0.19080,0.20791,0.22495,0.24192,0.25881,0.27563,0.29237,0.30901,0.32556,
0.34202,0.35836,0.37460,0.39073,0.40673,0.42261,0.43837,0.45399,0.46947,0.48480,
0.50000,0.51503,0.52991,0.54463,0.55919,0.57357,0.58778,0.60181,0.61566,0.62932,
0.64278,0.65605,0.66913,0.68199,0.69465,0.70710,0.71934,0.73135,0.74314,0.75470,
0.76604,0.77714,0.78801,0.79863,0.80901,0.81915,0.82903,0.83867,0.84804,0.85716,
0.86602,0.87461,0.88294,0.89100,0.89879,0.90630,0.91354,0.92050,0.92718,0.93358,
0.93969,0.94551,0.95105,0.95630,0.96126,0.96592,0.97029,0.97437,0.97814,0.98162,
0.98480,0.98768,0.99026,0.99254,0.99452,0.99619,0.99756,0.99862,0.99939,0.99984,
1.00000,0.99984,0.99939,0.99862,0.99756,0.99619,0.99452,0.99254,0.99026,0.98768,
0.98480,0.98162,0.97814,0.97436,0.97029,0.96592,0.96126,0.95630,0.95105,0.94551,
0.93969,0.93358,0.92718,0.92050,0.91354,0.90630,0.89879,0.89100,0.88294,0.87461,
0.86602,0.85716,0.84804,0.83867,0.82903,0.81915,0.80901,0.79863,0.78801,0.77714,
0.76604,0.75470,0.74314,0.73135,0.71933,0.70710,0.69465,0.68199,0.66913,0.65605,
0.64278,0.62931,0.61566,0.60181,0.58778,0.57357,0.55919,0.54463,0.52991,0.51503,
0.49999,0.48480,0.46947,0.45398,0.43837,0.42261,0.40673,0.39073,0.37460,0.35836,
0.34201,0.32556,0.30901,0.29237,0.27563,0.25881,0.24192,0.22494,0.20791,0.19080,
0.17364,0.15643,0.13917,0.12186,0.10452,0.08715,0.06975,0.05233,0.03489,0.01745,
-0.00000,-0.01745,-0.03490,-0.05233,-0.06975,-0.08715,-0.10452,-0.12187,-0.13917,-0.15643,
-0.17364,-0.19081,-0.20791,-0.22495,-0.24192,-0.25882,-0.27563,-0.29237,-0.30901,-0.32556,
-0.34202,-0.35836,-0.37460,-0.39073,-0.40673,-0.42261,-0.43837,-0.45399,-0.46947,-0.48481,
-0.50000,-0.51503,-0.52992,-0.54464,-0.55919,-0.57357,-0.58778,-0.60181,-0.61566,-0.62932,
-0.64278,-0.65606,-0.66913,-0.68199,-0.69465,-0.70710,-0.71934,-0.73135,-0.74314,-0.75471,
-0.76604,-0.77714,-0.78801,-0.79863,-0.80901,-0.81915,-0.82903,-0.83867,-0.84804,-0.85716,
-0.86602,-0.87462,-0.88294,-0.89100,-0.89879,-0.90630,-0.91354,-0.92050,-0.92718,-0.93358,
-0.93969,-0.94551,-0.95105,-0.95630,-0.96126,-0.96592,-0.97029,-0.97437,-0.97814,-0.98162,
-0.98480,-0.98768,-0.99026,-0.99254,-0.99452,-0.99619,-0.99756,-0.99862,-0.99939,-0.99984,
-1.00000,-0.99984,-0.99939,-0.99862,-0.99756,-0.99619,-0.99452,-0.99254,-0.99026,-0.98768,
-0.98480,-0.98162,-0.97814,-0.97436,-0.97029,-0.96592,-0.96126,-0.95630,-0.95105,-0.94551,
-0.93969,-0.93357,-0.92718,-0.92050,-0.91354,-0.90630,-0.89879,-0.89100,-0.88294,-0.87461,
-0.86602,-0.85716,-0.84804,-0.83866,-0.82903,-0.81915,-0.80901,-0.79863,-0.78800,-0.77714,
-0.76604,-0.75470,-0.74314,-0.73135,-0.71933,-0.70710,-0.69465,-0.68199,-0.66912,-0.65605,
-0.64278,-0.62931,-0.61565,-0.60181,-0.58778,-0.57357,-0.55919,-0.54463,-0.52991,-0.51503,
-0.49999,-0.48480,-0.46946,-0.45398,-0.43836,-0.42261,-0.40673,-0.39072,-0.37460,-0.35836,
-0.34201,-0.32556,-0.30901,-0.29236,-0.27563,-0.25881,-0.24191,-0.22494,-0.20790,-0.19080,
-0.17364,-0.15643,-0.13917,-0.12186,-0.10452,-0.08715,-0.06975,-0.05233,-0.03489,-0.01744,
0.00000,0.01745,0.03490,0.05233,0.06975,0.08715,0.10453,0.12187,0.13917,0.15643,
0.17365,0.19081,0.20791,0.22495,0.24192,0.25882,0.27564,0.29237,0.30901,0.32557,
0.34202,0.35837,0.37460,0.39073,0.40673,0.42262,0.43837,0.45399,0.46947,0.48481,
0.50000,0.51504,0.52992,0.54464,0.55919,0.57357,0.58778,0.60181,0.61566,0.62932,
0.64278,0.65606,0.66913,0.68200,0.69466,0.70710,0.71934,0.73135,0.74314,0.75471,
0.76604,0.77714,0.78801,0.79863,0.80901,0.81915,0.82903,0.83867,0.84804,0.85716}
'
' A Flash memory table of floating point Cosine values used for the angle calculation
'
Dim fAngleCos_Table As FlashF = {1.00000,0.99984,0.99939,0.99862,0.99756,0.99619,0.99452,0.99254,0.99026,0.98768,
0.98480,0.98162,0.97814,0.97437,0.97029,0.96592,0.96126,0.95630,0.95105,0.94551,
0.93969,0.93358,0.92718,0.92050,0.91354,0.90630,0.89879,0.89100,0.88294,0.87461,
0.86602,0.85716,0.84804,0.83867,0.82903,0.81915,0.80901,0.79863,0.78801,0.77714,
0.76604,0.75470,0.74314,0.73135,0.71933,0.70710,0.69465,0.68199,0.66913,0.65605,
0.64278,0.62932,0.61566,0.60181,0.58778,0.57357,0.55919,0.54463,0.52991,0.51503,
0.49999,0.48480,0.46947,0.45399,0.43837,0.42261,0.40673,0.39073,0.37460,0.35836,
0.34201,0.32556,0.30901,0.29237,0.27563,0.25881,0.24192,0.22495,0.20791,0.19080,
0.17364,0.15643,0.13917,0.12186,0.10452,0.08715,0.06975,0.05233,0.03489,0.01745,
-0.00000,-0.01745,-0.03490,-0.05233,-0.06975,-0.08715,-0.10452,-0.12187,-0.13917,-0.15643,
-0.17364,-0.19080,-0.20791,-0.22495,-0.24192,-0.25881,-0.27563,-0.29237,-0.30901,-0.32556,
-0.34202,-0.35836,-0.37460,-0.39073,-0.40673,-0.42261,-0.43837,-0.45399,-0.46947,-0.48481,
-0.50000,-0.51503,-0.52992,-0.54463,-0.55919,-0.57357,-0.58778,-0.60181,-0.61566,-0.62932,
-0.64278,-0.65605,-0.66913,-0.68199,-0.69465,-0.70710,-0.71934,-0.73135,-0.74314,-0.75471,
-0.76604,-0.77714,-0.78801,-0.79863,-0.80901,-0.81915,-0.82903,-0.83867,-0.84804,-0.85716,
-0.86602,-0.87462,-0.88294,-0.89100,-0.89879,-0.90630,-0.91354,-0.92050,-0.92718,-0.93358,
-0.93969,-0.94551,-0.95105,-0.95630,-0.96126,-0.96592,-0.97029,-0.97437,-0.97814,-0.98162,
-0.98480,-0.98768,-0.99026,-0.99254,-0.99452,-0.99619,-0.99756,-0.99862,-0.99939,-0.99984,
-1.00000,-0.99984,-0.99939,-0.99862,-0.99756,-0.99619,-0.99452,-0.99254,-0.99026,-0.98768,
-0.98480,-0.98162,-0.97814,-0.97436,-0.97029,-0.96592,-0.96126,-0.95630,-0.95105,-0.94551,
-0.93969,-0.93357,-0.92718,-0.92050,-0.91354,-0.90630,-0.89879,-0.89100,-0.88294,-0.87461,
-0.86602,-0.85716,-0.84804,-0.83866,-0.82903,-0.81915,-0.80901,-0.79863,-0.78800,-0.77714,
-0.76604,-0.75470,-0.74314,-0.73135,-0.71933,-0.70710,-0.69465,-0.68199,-0.66912,-0.65605,
-0.64278,-0.62931,-0.61566,-0.60181,-0.58778,-0.57357,-0.55919,-0.54463,-0.52991,-0.51503,
-0.49999,-0.48480,-0.46946,-0.45398,-0.43836,-0.42261,-0.40673,-0.39072,-0.37460,-0.35836,
-0.34201,-0.32556,-0.30901,-0.29237,-0.27563,-0.25881,-0.24192,-0.22494,-0.20791,-0.19080,
-0.17364,-0.15643,-0.13917,-0.12186,-0.10452,-0.08715,-0.06975,-0.05233,-0.03489,-0.01745,
0.00000,0.01745,0.03490,0.05233,0.06975,0.08715,0.10453,0.12187,0.13917,0.15643,
0.17365,0.19081,0.20791,0.22495,0.24192,0.25882,0.27563,0.29237,0.30901,0.32557,
0.34202,0.35837,0.37460,0.39073,0.40673,0.42262,0.43837,0.45399,0.46947,0.48481,
0.50000,0.51503,0.52992,0.54464,0.55919,0.57357,0.58778,0.60181,0.61566,0.62932,
0.64278,0.65606,0.66913,0.68200,0.69466,0.70710,0.71934,0.73135,0.74314,0.75471,
0.76604,0.77714,0.78801,0.79863,0.80901,0.81915,0.82903,0.83867,0.84804,0.85716,
0.86602,0.87462,0.88294,0.89100,0.89879,0.90630,0.91354,0.92050,0.92718,0.93358,
0.93969,0.94551,0.95105,0.95630,0.96126,0.96592,0.97029,0.97437,0.97814,0.98162,
0.98480,0.98768,0.99026,0.99254,0.99452,0.99619,0.99756,0.99862,0.99939,0.99984,
1.00000,0.99984,0.99939,0.99862,0.99756,0.99619,0.99452,0.99254,0.99026,0.98768,
0.98480,0.98162,0.97814,0.97436,0.97029,0.96592,0.96126,0.95630,0.95105,0.94551,
0.93969,0.93357,0.92718,0.92050,0.91354,0.90630,0.89879,0.89100,0.88294,0.87461,
0.86602,0.85716,0.84804,0.83866,0.82903,0.81915,0.80901,0.79863,0.78800,0.77714,
0.76604,0.75470,0.74314,0.73135,0.71933,0.70710,0.69465,0.68199,0.66912,0.65605,
0.64278,0.62931,0.61565,0.60181,0.58778,0.57357,0.55919,0.54463,0.52991,0.51503}
EndProc
'------------------------------------------------------------------------------------------------------------
' Draw 4 pixels on the display
' Input : pXpos holds the X position
' : pYpos holds the Y position
' : pColour holds the 16-bit RGB565 colour
' Output : None
' Notes : Uses the low-level access to the CG9A01 LCD to create a window and write pixels, for faster operation
'
Proc GLCD_Pixel(pXpos As Word, pYpos As Word, pColour As EM34_wColour)
CG9A_hWriteCommand(cCG9A_COL_ADDR_SET) ' Set the X coordinates for the pixels
CG9A_hWriteData16(pXpos) ' X Start
CG9A_hWriteData16(pXpos + 1) ' X End
CG9A_hWriteCommand(cCG9A_ROW_ADDR_SET) ' Set the Y coordinates for the pixels
CG9A_hWriteData16(pYpos) ' Y Start
CG9A_hWriteData16(pYpos + 1) ' Y End
CG9A_hWriteCommand(cCG9A_MEM_WR) ' Put the LCD in memory write mode
'
' Write the pixels to the LCD
'
CG9A_Data_Mode() ' Set the CG9A01 to data mode
CG9A_SPI_Start() ' Start the CG9A01 SPI interface
CG9A_hWrite16(pColour) ' Write the 16-bit RGB565 pixel colour to the window
CG9A_hWrite16(pColour) ' Write the 16-bit RGB565 pixel colour to the window
CG9A_hWrite16(pColour) ' Write the 16-bit RGB565 pixel colour to the window
CG9A_hWrite16(pColour) ' Write the 16-bit RGB565 pixel colour to the window
CG9A_SPI_Finish() ' Finish the SPI interface
EndProc
'------------------------------------------------------------------------------------------------------------
' Setup the ADC peripheral on a PIC18FxxK40 device
' Input : None
' Output : None
' Notes : Set for 10-bit operation
'
Proc ADC_Setup()
ADLTHL = %00000000
ADLTHH = %00000000
ADUTHL = %00000000
ADUTHH = %00000000
ADSTPTL = %00000000
ADSTPTH = %00000000
ADRPT = %00000000
ADPCH = %00000000
ADCAP = %00000000
ADCON0 = %10000100 ' Right justify for 10-bit operation. ADCS is ADCLK
ADCON1 = %00000000
ADCON2 = %00000000 ' Basic_mode
ADCON3 = %00000000
ADSTAT = %00000000
ADREF = %00000000 ' -Vref is VSS. +Vref is VDD
ADACT = %00000000
ADCLK = %00001111 ' fOSC/32 (FOSC / (2 * (n + 1)))
ADACQ = %00000000
EndProc
'------------------------------------------------------------------------------------------------------------
' Read the ADC on a PIC18F26K40 device
' Input : pChan holds the ADC channel to read
' Output : Returns the 10-bit ADC value
' Notes : Requires the ADFM bit set for right justified 10-bit operation
'
Proc ADC_Read10(pChan As WREG), Word
ADPCH = pChan ' Load the channel into the relevant SFR
ADCON0bits_ADON = 1 ' Enable the ADC
DelayUS 100 ' A delay before sampling
ADCON0bits_GO_DONE = 1 ' \
Repeat : Until ADCON0bits_GO_DONE = 0 ' / Start a sample and wait for it to finish
Result.Byte1 = ADRESH ' \
Result.Byte0 = ADRESL ' / Return the sample value
EndProc
'------------------------------------------------------------------------------------------------------------
' Setup the config fuses to use the internal oscillator at 64MHz on PIC18FxxK40 devices
' With pins RA6 and RA7 as general purpose I/O
'
Config_Start
RSTOSC = HFINTOSC_64MHZ ' HFINTOSC with HFFRQ = 64MHz and CDIV = 1:1
FEXTOSC = Off ' External Oscillator not enabled
WDTE = Off ' Watchdog Timer disabled
CLKOUTEN = Off ' CLKOUT function is disabled
CSWEN = On ' Writing to NOSC and NDIV is allowed
FCMEN = Off ' Fail-Safe Clock Monitor disabled
MCLRE = EXTMCLR ' If LVP = 0, MCLR pin is MCLR
PWRTE = On ' Power up timer enabled
LPBOREN = Off ' ULPBOR disabled
BOREN = Off ' Brown-out disabled
BORV = VBOR_245 ' Brown-out Reset Voltage (VBOR) set to 2.45V
ZCD = Off ' ZCD disabled
PPS1WAY = Off ' PPSLOCK bit can be set and cleared repeatedly
STVREN = Off ' Stack full/underflow will not cause reset
Debug = Off ' Background debugger disabled
XINST = Off ' Extended Instruction Set disabled
SCANE = Off ' Scanner module is Not available for use
LVP = Off ' Low Voltage programming disabled
WDTCPS = WDTCPS_2 ' Watchdog Divider Ratio 1:128 (4 milliseconds)
WDTCWS = WDTCWS_7 ' Watchdog Window always open (100%)
WDTCCS = LFINTOSC ' WDT reference clock is the 31.2kHz HFINTOSC
WRT0 = Off ' Block 0 (000800-001FFF) not write-protected
WRT1 = Off ' Block 1 (002000-003FFF) not write-protected
WRTC = Off ' Config registers (300000-30000B) not write-protected
WRTB = Off ' Boot Block (000000-0007FF) write-protected
WRTD = Off ' Data EEPROM not write-protected
Cp = Off ' User NVM code protection disabled
CPD = Off ' Data NVM code protection disabled
EBTR0 = Off ' Block 0 not protected from table reads from other blocks
EBTR1 = Off ' Block 1 not protected from table reads from other blocks
EBTRB = Off ' Boot Block not protected from table reads
Config_End
A circuit diagram for the connection of the CG9A01 TFT display to a PIC18F26K40 device is shown below. The Positron8 code sets the PIC18F26K40 microcontroller to use its internal oscillator, running at 64 MHz, so no crystal or resonator is required. The ADC input (AN0) can be supplied with a voltage from 0 to 3.3 volts, and this will be displayed on the EM34's green phosphur emulation on the CG9A01 TFT display.
A photo of the EM34 emulator running on a breadboard shield, connected to an EasyDriver Amicus8 board with a PIC18F26K40 placed in its socket, is shown below, and the source code for the EM34 emulator written in Positron8 can be downloaded from here: EM34_Emulator_with_CG9A01.zip. The zip file also contains the CG9A01 TFT library source code, and library source code to operate the on-board SPI peripheral for many of the newer 18FxxKxx devices.
And a video of it operating on the EasyDriver Amicus8 board is shown below. As the potentiometer is moved, the EM34 display closes and opens its phosphorus circle. With a higher voltage on the ADC's input closing the circle, and a lower voltage opening it.