Re regulators, don't worry about switching regs if you don't want to. Any reg will be fine. There are several places on the board you can bring in regulated voltages from another place if you want to.
I got most of the components from futurlec, but they can take a couple of weeks to arrive and sometimes it is hard to find parts on their website that you know they sell.
I found a mistake on the board. I'm using P16 for the clock and I need to use P19 or higher. I didn't read the spec sheet closely enough I thought the data was loaded when the load went from low to high, but it isn't - see below.
These counters may be preset using the LOAD input. Presetting
of all four flip-flops is synchronous to the rising edge
of CLOCK. When LOAD is held LOW counting is disabled
and the data on the A, B, C, and D inputs is loaded into the
counter on the rising edge of CLOCK. If the load input is
taken HIGH before the positive edge of CLOCK the count
operation will be unaffected.
So some tracks are going to need to be cut and moved. I think it will be a matter of driving all the clocks from P19 instead of P16, and then driving the memory /RD from P16 instead of P19. I'll need to think about where to put the changes on the board.
addit - found a few more things on the board that are not quite right. Apart from swapping things above, I think the schematic is right though. Hmm - I might have to hold off posting any boards though. Maybe better to build this on a breadboard first?
Sorry I didn't notice the load line error. I guess I should have looked over the schematic a bit closer. I'll take another, closer, look at the schematic tonight.
I did decide to order regulators and all necessary components.
I think it might be a good idea to breadboard first. I always start here if possible. Cutting a few traces is not a huge deal to me, but I will leave this up to you. I've been working on the old ili driver and almost done with ram to hub and hub to ram transfers. I need to get a jump start on homework for next week, but after this is done I will continue working.
*edit*
Okay, I've been working on the driver and hit an issue. I'm looking at the datasheet for my hc counters and see max clock 25MHZ @ 4.5V, 5MHZ @ 2v. *I'm going to slow it down for the LS, but will be going full HC - 3.3V compatible* So. How should I guestimate the timing cycle? Any advice? Just start slow and speed it up till it won't run?
another edit
I've been working on the ram read and write in ASM. None of this is tested, but I'm trying to get a framework. I think this should be close.
DAT
' First part tests ok
'' +--------------------------------------------------------------------------+
'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |
'' +--------------------------------------------------------------------------+
org 0
tbp2_start ' setup the pointers to the hub command interface (saves execution time later
' +-- These instructions are overwritten as variables after start
comptr mov comptr, par ' -| hub pointer to command
hubptr mov hubptr, par ' | hub pointer to hub address
ramptr add hubptr, #4 ' | hub pointer to ram address
lenptr mov ramptr, par ' | hub pointer to length
errptr add ramptr, #8 ' | hub pointer to error status
cmd mov lenptr, par ' | command I/R/W/G/P/Q
hubaddr add lenptr, #12 ' | hub address
ramaddr mov errptr, par ' | ram address
len add errptr, #16 ' | length
err nop ' -+ error status returned (=0=false=good)
' Initialise hardware tristates everything and read/write set the pins
init mov err, #0 ' reset err=false=good
mov dira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error x
wrlong zero, comptr ' command =0 (done)
' wait for a command (pause short time to reduce power)
pause
' mov ctr, delay wz ' if =0 no pause
' if_nz add ctr, cnt
' if_nz waitcnt ctr, #0 ' wait for a short time (reduces power)
rdlong cmd, comptr wz ' command ?
if_z jmp #pause ' not yet
'decode command
'
cmp cmd, #"Z" wz ' Z moves command to the display from hub address, length times
if_z jmp #hubtodisplayCommand ' command format "DoCmd(Z,hub_address, unused, length)
cmp cmd, #"Y" wz ' Y moves data to the display from hub address, length times
if_z jmp #hubtodisplayData ' data format "DoCmd(Y, hub_address, unused, length)
cmp cmd, #"R" wz ' R = read block from external ram to hub
if_z jmp #rdblock
cmp cmd, #"W" wz ' W = write block from hub to external ram
if_z jmp #wrblock
cmp cmd, #"C" wz ' C moves a block of data from ram to the display
if_z jmp #extramtodisplay
' add new commands HERE
' cmp cmd, #"A" wz ' A moves 256 bytes from hub to external ram
' if_z jmp #blockhubtoram
' cmp cmd, #"B" wz ' B moves 256 bytes from external ram to hub
' if_z jmp #blockramtohub
' cmp cmd, #"E" wz ' convert 3 byte .raw format to 2 byte .ili format - hub to hub
' if_z jmp #rawtoiliformat
' cmp cmd, #"F" wz ' draw a transparent icon, pass two locations in hub ram and len = number of pixels
' if_z jmp #drawicon
cmp cmd, #"I" wz ' init
if_z jmp #init
'
mov err, cmd ' error = cmd (unknown command)
jmp #done
ram_open rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
ram_open_ret ret
hubtodisplayData ' send a block of data blocklen from hubaddr to the display (bypasses external ram)
call #ram_open ' gets hubaddr and len (ignores ramaddress)
call #setRShigh ' set pins for data output
:hubdisploop rdword Display, hubaddr ' copy word from hub, not needed ?
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisploop ' loop until done
jmp #init ' set pins to tristate
hubtodisplayCommand call #ram_open ' gets hubaddr and len (ignores ramaddress)
:hubdisplayloop call #setRSlow ' set pins for Command output
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:data ' loop until done
jmp #init ' set pins to tristate
:data call #setRShigh
rdword Display, hubaddr ' copy word from hub
add hubaddr,#2 ' add 2 to hub address changed for word alligned
call #ilidisplayword ' send these bytes to the display
djnz len,#:hubdisplayloop ' loop until done
jmp #init ' set pins to tristate
setRShigh mov outa, PinsInit
mov dira, DirsEnabled ' set rsHigh by tristate pin
setRShigh_ret ret
setRSlow mov outa, PinsInit
mov dira, DirsEnabled wz ' set rsHigh by tristate pin
muxnz dira, RSpin ' set rsLow by enabling pin
setRslow_ret ret
ilidisplayword ' pass data out, sends out to the display
add Display, p2dpins wz 'this add presets the data for control pins and primes WZ flag for mux operation
mov outa, Display 'then make pins = data
muxz dira,EnablePin 'make enable pin low
mov timeout, #$f 'set wait period
:wait1 djnz timeout, :wait1 'and wait
muxnz dira, EnablePin 'make enable pin high
ilidisplayword_ret ret
'***********************************************************************************************************************************
'tests ok
'---------------------------------------------------------------------------------------------------------
'Memory Access Functions
rdblock call #ram_open ' get variables from hub variables
call #load_ram_add ' load first address into counters
rdloop call #read_memory_word ' read word from address into data_8
wrword data_8,hubaddr ' write data_8 to hubaddr ie copy WORD to hub
add hubaddr,#1 ' add 1 to hub address
add ramaddr,#1 ' add 1 to ram address
call #inc_ram_address ' increment RAM address
djnz len,#rdloop ' loop until done
jmp #init ' reinitialise
' write block from hub to external ram
wrblock call #ram_open
call #load_ram_add ' load first address into counters
mov dira, P2RPins
wrloop rdword data_8, hubaddr ' copy word from hub
call #write_memory_word ' write word from data_8 to address
add hubaddr,#1 ' add 1 to hub address
add ramaddr,#1 ' add 1 to ram address
call #inc_ram_address ' increment RAM address
djnz len,#wrloop ' loop until done
jmp #init ' reinitialise
load_ram_add
mov outa, RamLoadPins wz 'preset pins and clear z flag. pins still tri-state
add outa, ramaddr 'move rammaddress onto bus
mov dira, RamLoadDirs 'and enable all pins
'wait here if needed?
muxz outa, EnablePin ' make Enable Pin Low
'wait here if needed?
muxnz outa, EnablePin ' make Enable Pin High
'wait?
mov dira, zero ' tri-state all pins
'wait here if needed?
load_ram_add_ret ret
read_memory_word mov outa, R2PPins ' preset pins for read
mov dira, R2PDirs ' enable pins
add timeout, RAMRDtimeout 'wait here if needed
:wait djnz timeout, #:wait
mov data_8, ina
and data_8, #$FF ' extract 16 bits
read_memory_word_ret ret
write_memory_word and data_8, lowWordMask ' ensure upper bytes=0
add data_8, P2RPins ' add to P2E initPins
mov outa, data_8 wz ' send it out
muxz outa, Cadd1Pin ' make 138 = RAMWR
muxz outa, EnablePin ' make ram WR LOW
add timeout, RAMWRtimeout 'set wait
:wait djnz timeout, #:wait 'and wait
muxnz outa, EnablePin ' make ram WR HIGH
muxz outa, Cadd1Pin ' make 138 = COUNT
write_memory_word_ret ret
inc_ram_address add zero, #0 wz 'prime z flag
muxnz outa, EnablePin 'make Enable Pin LOW
mov timeout, countTimeout 'set wait
:wait djnz timeout, #:wait 'and wait
muxz outa, EnablePin 'make enable Pin High
'and wait again?
' mov timeout, countTimeout 'set wait
':wait djnz timeout, #:wait 'and wait
inc_ram_address_ret ret
'extramtodisplay ' send a block of data blocklen from external memory ramaddress to the ILI9325 display
call #ram_open ' gets ramaddr and len (ignore hubaddr)
call #load_ram_add ' loads ram address for transfer
mov outa, R2DPins ' preset pins for R2D transfer
mov dira, R2DDirs ' enable pins
'and wait if necessary?
add zero, #0 'prime z flag
ililoop muxnz outa, EnablePin ' make enable pin LOW
mov timeout, #$f ' set wait
:wait1 djnz timeout, #:wait1 ' and wait
muxz outa, EnablePin 'make enable pin HIGH
muxnz outa, Cadd0Pin ' set for ramcount
call #inc_ram_address ' and load next ram address
muxz outa, Cadd0Pin ' set for lcd_wr
mov timeout, #$f ' set wait
:wait2 djnz timeout, #:wait2 ' and wait
djnz len,#ililoop ' loop until done
jmp #init ' set pins to tristate
RAMRDtimeout long $0000_00FF
RAMWRtimeout long $0000_00FF
countTimeout long $0000_00FF
lowWordMask long $0000_ffff
'pin settings
EnablePin long %00000000_00000010_00000000_00000000
RSPin long %00000000_00000001_00000000_00000000
LoadPin long %00000010_00000000_00000000_00000000
RamLoadPins long %00001100_01000010_00000000_00000000
RamLoadDirs long %00001111_11100010_11111111_11111111
R2PDirs long %00001101_11100010_00000000_00000000
P2RDirs long %00001001_11100010_00000000_00000000
P2RPins long %00001110_01000010_00000000_00000000
R2PPins long %00000010_01000010_00000000_00000000
R2DPins long %00000000_01100011_00000000_00000000
R2DDirs long %00000101_11100011_00000000_00000000
p2dpins long %00001000_01100000_00000000_00000000 ' propToDisplay enable pin low, but tristate, primed for lcd transfer
PinsInit long %00001001_01100010_00000000_00000000 'pins Inital state, BUS = Prop -> RAM, Not RamRD, BusDisabled, enable pin high
DirsEnabled long %00001001_11100000_11111111_11111111 '' (R4Fh) (POR = 0000h)
CAdd0Pin long %00000000_00100000_00000000_00000000
Cadd1Pin long %00000000_01000000_00000000_00000000
Cadd2Pin long %00000000_10000000_00000000_00000000
timeout res 1
Display res 1
fit
I will keep updating this until it works, I just wanted to get a start so you could make suggestions. Also, here's the schematic
I flipped a quarter and it came up tails, so I started working on a new schematic. I updated to 19 bit address line, and your ram chips. I also added 2 - `374s to save 4 prop pins and add 12 GPOs. Un-buffered access to the 19 prop pins and 1 control pin are also provided. Two audio outs as well as midi I/O round out the connections. I also provided leds on p30 and p31 as you have. Should help debugging? There are a few errors I am aware of. Resistor values are incorrect for audio outs. I am still debating adding 5v reg. For those without midi devices, you can use the midi i/o for a ps2 keyboard? Or maybe even usb?
I did not want to use the inverters, but couldn't think of an easier way. Let me know what you think!
*edited*
I found more issues. I forgot to remove a few resistors from the lcd lines. I am also thinking about adding a 4 pin jumper for midi I/O or PS2 port.
Looking good. Let me know how it goes on a breadboard. Are you still running the ram chips from 5V?
I got routines working tonight to transfer data from hub to ram and ram to hub
PUB HubToRam(RamAddress,Number) | i ' send data from hub to ram in a block
Load161(RamAddress) ' load all the 161 chips with the start value
i := 0
repeat Number
OUTA &= %11111111_11111111_00000000_00000000 ' clear for output
OUTA |= rambuffer[i] ' send out a word to P0-P15
WR_Low ' write to ram
WR_High ' toggle ram write
Clock161_Low ' toggle clock
Clock161_High
i += 1 ' increment i
PUB RamToHub(RamAddress, Number) | i ' send data from ram to hub in a block
Load161(RamAddress) ' load all the 161 chips with the start value
i := 0
DIRA &= %00001111_11111111_00000000_00000000 ' set P0-P15 as inputs
repeat Number
RD_Low ' read pin low
rambuffer[i] := INA ' get the data
RD_High
Clock161_Low ' toggle clock
Clock161_High
i += 1 ' increment i
DIRA |= %00000000_00000000_11111111_11111111 ' restore P0-P15 as outputs
So - move data from SD card to propeller, prop to external ram, external ram back to prop, and external ram to the display. This last one is where the fast refresh works with 30ms to do a screen. It is super simple in spin and so will easily translate over to pasm
PUB RamToDisplay(RamAddress,Number) ' send n words to the display after sending a Draw command
Load161(RamAddress) ' load all the 161 chips with the start value
ILI_RS_High ' RS high for sending data
RD_Low ' memory read low
DIRA &= %00001111_11111111_00000000_00000000 ' set P0-P15 as inputs so no data clash with propeller (prop ignores these pins)
repeat Number
ILI_WR_Low ' send out the data
ILI_WR_High
Clock161_Low ' toggle clock
Clock161_High
RD_High ' memory read high
DIRA |= %00000000_00000000_11111111_11111111 ' restore P0-P15 as outputs
This little bit of code fills the screen from the ram with 76800 pixels (15% of the ram capacity)
Draw(0,0,239,319) ' dump out 76800 words to the display = a full screen
RamToDisplay(0,76800)
and the speed in spin is 5.5 seconds, which I think compares favorably with the previous speed around 9 seconds. This is going to be very fast in pasm.
This 161 driver is brilliant!
Full program:
'' ILI9325 driver using the Touchblade161 design for faster ram to display transfers
'' James Moxham 2012
CON
_clkmode = xtal1 + pll16x ' use crystal x 16
_xinfreq = 5_000_000
_1ms = 1_000_000 / 1_000 ' Divisor for 1 ms
' pins
' P24 = audio out
' 25,26,27 138 one of 8 decoded, active low
' 0=000 = SPI touchscreen input, keyboard, TV VGA enabled
' 1=001 = Load counter
' 2=010 = Memory transfer - P0-P15=bus, P19=161_clk, P17 = ILI_WR, P18=ILI_RS, P16= Ram_RD, P20=Ram_WR,P21-23 = SD card
' 3=011 = ILI Reset
' 4=100 = Digital output (8 bits to a 574 latch)
' 5=101 = spare
' 6=110 = spare
' 7=111 = startup (all above deselected)
OBJ
VAR
long orientation
long curx, cury
long clkcycles ' for the delay routine
PUB Main
curx :=0
cury :=0
PinsHigh
start_ram ' start the cog driver
MemoryTransferSelect ' select 138 and set control pins
Start_ILI9325 ' start the display
HelloWorld ' Bootup message
rambuffer[0] :=$AA55 ' some random word values
rambuffer[1] :=$07FF
rambuffer[2] := %00000111_11100000 ' green pixels
rambuffer[3] := %00000111_11100000
rambuffer[4] := %11111000_00000000 ' red pixels
rambuffer[5] := %11111000_00000000
rambuffer[6] := %11111000_00000000
HubToRam(0,7) ' ramaddress, number. Uses rambuffer (word array) up to 256
rambuffer[1] := 0 ' clear the value for debugging
RamToHub(0,7) ' read data back
MemoryTransferSelect ' reselect 138 for display output for debugging
hex(rambuffer[1],4)
Draw(99,95,108,104) ' draw a little black square
repeat 100
Pixel(0)
Draw(100,100,106,100) ' display pixels
RamToDisplay(0,7) ' dump out from ram to display
repeat
PUB RamToDisplay(RamAddress,Number) ' send n words to the display after sending a Draw command
Load161(RamAddress) ' load all the 161 chips with the start value
ILI_RS_High ' RS high for sending data
RD_Low ' memory read low
DIRA &= %00001111_11111111_00000000_00000000 ' set P0-P15 as inputs so no data clash with propeller (prop ignores these pins)
repeat Number
ILI_WR_Low ' send out the data
ILI_WR_High
Clock161_Low ' toggle clock
Clock161_High
RD_High ' memory read high
DIRA |= %00000000_00000000_11111111_11111111 ' restore P0-P15 as outputs
PUB HubToRam(RamAddress,Number) | i ' send data from hub to ram in a block
Load161(RamAddress) ' load all the 161 chips with the start value
i := 0
repeat Number
OUTA &= %11111111_11111111_00000000_00000000 ' clear for output
OUTA |= rambuffer[i] ' send out a word to P0-P15
WR_Low ' write to ram
WR_High ' toggle ram write
Clock161_Low ' toggle clock
Clock161_High
i += 1 ' increment i
PUB RamToHub(RamAddress, Number) | i ' send data from ram to hub in a block
Load161(RamAddress) ' load all the 161 chips with the start value
i := 0
DIRA &= %00001111_11111111_00000000_00000000 ' set P0-P15 as inputs
repeat Number
RD_Low ' read pin low
rambuffer[i] := INA ' get the data
RD_High
Clock161_Low ' toggle clock
Clock161_High
i += 1 ' increment i
DIRA |= %00000000_00000000_11111111_11111111 ' restore P0-P15 as outputs
PUB Load161(RamAddress)
Select138(7) ' deselect previous 138 value
DIRA |= %00000000_00011111_11111111_11111111 ' P0-P18 enabled for output plus P19,P20
OUTA &= %00001110_11111000_00000000_00000000 ' preserve previous values but set A0-18 low
OUTA |= RamAddress ' output address to the 161 chips
Clock161_Low ' clock low
Select138(1) ' 161 load low
Clock161_High ' load in value
OUTA |= %00000000_11111111_00000000_00000000 ' set P16-P23 high prior to changing 138
Select138(2) ' 161 load high and back to mem transfer
PUB Clock161_Low
OUTA &= %11111111_11110111_11111111_11111111 ' P19 low
PUB Clock161_High
OUTA |= %00000000_00001000_00000000_00000000 ' P19 high
PUB WR_Low
OUTA &= %11111111_11101111_11111111_11111111 ' P20 low
PUB WR_High
OUTA |= %00000000_00010000_00000000_00000000 ' P20 high
PUB RD_Low
OUTA &= %11111111_11111110_11111111_11111111 ' P16 low
PUB RD_High
OUTA |= %00000000_00000001_00000000_00000000 ' P16 high
PUB PinsHigh
DIRA := %00001111_11111111_11111111_11111111 ' enable all pins as outputs
OUTA := %00001110_11111111_11111111_11111111 ' all except P24 audio out are high
PUB MemoryTransferSelect
Select138(2) ' enable memory transfer group
DIRA |= %00001110_11111111_11111111_11111111 ' Pins all as outputs
OUTA |= %00000000_11111111_00000000_00000000 ' all control pins high
PUB Select138(n) ' pass n=0 to 7
n := n<<25 ' shift left so pins 25,26,27
DIRA |= %00001110_00000000_00000000_00000000 ' enable these pins for output
OUTA &= %11110001_11111111_11111111_11111111 ' mask 3 pins low
OUTA |= n ' send out
PUB Clearscreen
Draw(0,0,239,319) ' clear the screen - slow spin version
repeat 76800
Pixel($0000)
PUB HelloWorld ' use propeller font in the rom for bootup messages when debugging sd cards
Propfont_string(string("Hello World")) ' string to send
PUB Propfont_string(stringptr) 'print at curx,cury
repeat strsize(stringptr)
Propfont_out(byte[stringptr++])
crlf
PUB crlf
curx := 0
cury += 32 ' new line at end of string
if cury >319 ' bottom of screen so new screen
curx:=0
cury:=0
PUB Propfont_out(ascii) | address,pixels
Draw(curx,cury,curx+15,cury+31) ' location to start drawing
address := $8000 + (ascii >> 1) << 7 ' get rom address
repeat 32 ' 32 rows per character, split in two parts
pixels := long[address] ' get rom font data
pixels := pixels >> (ascii & 1) ' shift for odd characters
repeat 16 ' 16 columns
if pixels & 1
Pixel(%00000111_11100000) ' foreground color RRRRRGGG_GGGBBBBB
else
Pixel(%00000000_00000000) ' background color
pixels := pixels >> 2 ' alternate pixels interleaved so shift 2
address += 4
curx +=16
if curx >239 ' new line
crlf
PUB Start_ILI9325 ' pass orientation true = portrait, false = landscape
ILI_Reset_High
pause1ms(5)
ILI_Reset_Low
pause1ms(5)
ILI_Reset_High
ILI_CS_High
ILI_RD_High
ILI_WR_High
pause1ms(5)
ILI_CS_Low
' ************* Start Initial Sequence **********
ILIcmd($00E5,$78F0) ' set SRAM internal timing
ILIcmd($0001,$0100) ' set SS and SM bit 0001 0100 portrait
ILIcmd($0002,$0700) ' set 1 line inversion
ILIcmd($0003,$1030) ' set GRAM write direction and BGR=1. $0003 $1030
ILIcmd($0004,$0000) ' Resize register
ILIcmd($0008,$0207) ' set the back porch and front porch
ILIcmd($0009,$0000) ' set non-display area refresh cycle ISC[3:0]
ILIcmd($000A,$0000) ' FMARK function
ILIcmd($000C,$0000) ' RGB interface setting
ILIcmd($000D,$0000) ' Frame marker Position
ILIcmd($000F,$0000) ' RGB interface polarity
' *************Power On sequence ****************//
ILIcmd($0010,$0000) ' SAP, BT[3:0], AP, DSTB, SLP, STB
ILIcmd($0011,$0007) ' DC1[2:0], DC0[2:0], VC[2:0]
ILIcmd($0012,$0000) ' VREG1OUT voltage
ILIcmd($0013,$0000) ' VDV[4:0] for VCOM amplitude
ILIcmd($0007,$0001)
pause1ms(50) ' Dis-charge capacitor power voltage
ILIcmd($0010,$1090) ' 1490//SAP, BT[3:0], AP, DSTB, SLP, STB
ILIcmd($0011,$0227) ' DC1[2:0], DC0[2:0], VC[2:0]
pause1ms(50) ' delay
ILIcmd($0012,$001F) ' 001C// Internal reference voltage= Vci;
pause1ms(50) ' delay
ILIcmd($0013,$1500) ' $1000//1400 Set VDV[4:0] for VCOM amplitude 1A00
ILIcmd($0029,$0027) ' $0012 //001a Set VCM[5:0] for VCOMH //$0025 0034
ILIcmd($002B,$000D) ' Set Frame Rate 000C
pause1ms(50) ' delay
ILIcmd($0020,$0000) ' GRAM horizontal Address
ILIcmd($0021,$0000) ' GRAM Vertical Address
' ----------- Adjust the Gamma Curve ----------//
ILIcmd($0030,$0000)
ILIcmd($0031,$0707)
ILIcmd($0032,$0307)
ILIcmd($0035,$0200)
ILIcmd($0036,$0008)
ILIcmd($0037,$0004)
ILIcmd($0038,$0000)
ILIcmd($0039,$0707)
ILIcmd($003C,$0002)
ILIcmd($003D,$1D04)
' ------------------ Set GRAM area ---------------//
ILIcmd($0050,$0000) ' Horizontal GRAM Start Address
ILIcmd($0051,$00EF) ' Horizontal GRAM End Address
ILIcmd($0052,$0000) ' Vertical GRAM Start Address
ILIcmd($0053,$013F) ' Vertical GRAM Start Address
ILIcmd($0060,$A700) ' Gate Scan Line
ILIcmd($0061,$0001) ' NDL,VLE, REV
ILIcmd($006A,$0000) ' set scrolling line
' -------------- Partial Display Control ---------/
ILIcmd($0080,$0000)
ILIcmd($0081,$0000)
ILIcmd($0082,$0000)
ILIcmd($0083,$0000)
ILIcmd($0084,$0000)
ILIcmd($0085,$0000)
' //-------------- Panel Control -------------------//
ILIcmd($0090,$0010)
ILIcmd($0092,$0600)
ILIcmd($0007,$0133) ' 262K color and display ON
ChangeOrientation(true) ' default to portrait
PUB ChangeOrientation(n) ' pass true = portrait or false = landscape, changes global variable orientation in this object
orientation := n
if orientation
ILIcmd($0001,$0100) ' set SS and SM bit 0001 0100 portrait
ILIcmd($0003,$1030) ' set GRAM write direction and BGR=1. $0003 $1030
else
ILIcmd($0001,$0000) ' set SS and SM bit 0001 0000 landscape
ILIcmd($0003,$1038) ' landscape $1028 = original but 1038 is correct - not mirror image
PUB Draw(x1, y1, x2, y2) ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
ifnot orientation ' landscape mode so swap x and y
result :=x1 ' swap x1 and y1
x1 := y1
y1 := result
result := x2 ' swap x2 and y2
x2 :=y2
y2 := result
ILIcmd($0050,x1)
ILIcmd($0052,y1)
ILIcmd($0051,x2)
ILIcmd($0053,y2)
ILIcmd($0020,x1)
ILIcmd($0021,y1)
Lcd_Write_Com($0022)
PUB Pixel(pixelcolor) ' send out a pixel
Lcd_Write_Data(pixelcolor)
PUB pause1ms(period)
'' Pause execution for period (in units of 1 ms).
clkcycles := ((clkfreq / _1ms * period) - 4296) #> 381 ' Calculate 1 ms time unit
waitcnt(clkcycles + cnt) ' Wait for designated time
PUB hex(value, digits)
'' Print a hexadecimal number
propfont_out("O")
propfont_out("x")
value <<= (8 - digits) << 2
repeat digits
propfont_out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
crlf
PRI ILIcmd(c,d) ' instruction in one method
Lcd_Write_Com(c) ' send out a word
Lcd_Write_Data(d)
PRI Lcd_Write_Com(ILIlong)
ILI_RS_low
LCD_Writ_Bus(ILIlong)
PRI Lcd_Write_Data(ILIlong)
ILI_RS_High
LCD_Writ_Bus(ILIlong)
PRI LCD_Writ_Bus(ILILong)
'ILILong &= %00000000_00000000_11111111_11111111 ' mask to a word. Not needed if care taken always to send a word value
OUTA &= %11111111_11111111_00000000_00000000 ' set P0-P15 to zero ready to OR
OUTA |= ILILong ' merge with the word to output
ILI_WR_Low ' send out the data
ILI_WR_High
PRI ILI_RS_Low
OUTA &= %11111111_11111011_11111111_11111111 ' P18 low
PRI ILI_RS_High
OUTA |= %00000000_00000100_00000000_00000000 ' P18 high
PRI ILI_RD_Low ' pulled high in hardware, not used
PRI ILI_RD_High
PRI ILI_WR_Low
OUTA &= %11111111_11111101_11111111_11111111 ' p17 low
PRI ILI_WR_High
OUTA |= %00000000_00000010_00000000_00000000 ' p17 high
PRI ILI_CS_Low ' not used as setting 138 to %010 does this
PRI ILI_CS_High
PRI ILI_RESET_Low ' reset low
Select138(3) ' reset low
PRI ILI_RESET_High
Select138(2) ' 138 back to memselect
DAT
sdbuffer byte $0[512] ' 512 byte buffer for sd card interface
rambuffer word $0[256]
'************************** Cog driver for the 16 bit ILI9325 screen *********************
VAR
' communication params(5) between cog driver code - only "command" and "errx" are modified by the driver
long command, hubaddrs, ramaddrs, blocklen, errx, cog ' rendezvous between spin and assembly (can be used cog to cog)
' command = R, W, H I,D etc =0 when operation completed by cog
' hubaddrs = hub address for data buffer
' ramaddrs = ram address for data ($0000 to $FFFF)
' blocklen = ram buffer length for data transfer
' errx = returns =0 (false=good), else <>0 (true & error code)
' cog = cog no of driver (set by spin start routine)
PUB start_ram : err_
' Initialise the Drac Ram driver. No actual changes to ram as the read/write routines handle this
command := "I"
cog := 1 + cognew(@tbp2_start, @command)
if cog == 0
err_ := $FF ' error = no cog
else
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
PUB stop_ram
if cog
cogstop(cog~ - 1)
PUB DoCmd(command_, hub_address, ram_address, block_length) : err_
' Do the command: R, W, N, F, H,I,D
hubaddrs := hub_address ' hub address start
ramaddrs := ram_address ' ram address start
blocklen := block_length ' block length
command := command_ ' must be last !!
' Wait for command to complete and get status
repeat while command ' driver cog sets =0 when done
err_ := errx ' driver cog sets =0 if no error, else xx = error code
DAT
'' +--------------------------------------------------------------------------+
'' | Dracblade Ram Driver (with grateful acknowlegements to Cluso) |
'' +--------------------------------------------------------------------------+
org 0
tbp2_start ' setup the pointers to the hub command interface (saves execution time later
' +-- These instructions are overwritten as variables after start
comptr mov comptr, par ' -| hub pointer to command
hubptr mov hubptr, par ' | hub pointer to hub address
ramptr add hubptr, #4 ' | hub pointer to ram address
lenptr mov ramptr, par ' | hub pointer to length
errptr add ramptr, #8 ' | hub pointer to error status
cmd mov lenptr, par ' | command I/R/W/G/P/Q
hubaddr add lenptr, #12 ' | hub address
ramaddr mov errptr, par ' | ram address
len add errptr, #16 ' | length
err nop ' -+ error status returned (=0=false=good)
' Initialise hardware tristates everything and read/write set the pins
init mov err, #0 ' reset err=false=good
mov dira,zero ' tristate the pins
done wrlong err, errptr ' status =0=false=good, else error x
wrlong zero, comptr ' command =0 (done)
pause
rdlong cmd, comptr wz ' command ?
if_z jmp #pause ' not yet
' decode command
cmp cmd,#"M" wz ' move a block from ram to the display
if_z jmp #moveblock
cmp cmd, #"I" wz ' init
if_z jmp #init
mov err, cmd ' error = cmd (unknown command)
jmp #done
'---------------------------------------------------------------------------------------------------------
ram_open rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
ram_open_ret ret
Moveblock ' uses ramaddr and len
' OUTA := address ' address is not latched - this is where the speed is
' OUTA &= %11111111_10111111_11111111_11111111 ' ILI write low
' OUTA |= %00000000_01000000_00000000_00000000 ' ILI write high
' address++ ' increment address
mov dira,direction ' set P0-P23 as outputs
call #ram_open ' get ramaddr and len
or ramaddr,pin22 ' start with pin 22 high
Moveblock_loop mov outa,ramaddr ' send out the address value
andn outa,pin22 ' set pin 22 low
or outa,pin22 ' set pin 22 high
add ramaddr,#1 ' increment ram address
djnz len,#moveblock_loop
jmp #init
halt jmp #halt
' ************************ Variables ******************************
delay long 80 ' waitcnt delay to reduce power (#80 = 1uS approx)
Zero long %00000000_00000000_00000000_00000000 ' for tristating all pins
pin22 long %00000000_01000000_00000000_00000000
direction long %00000000_11111111_11111111_11111111
fit 496
Wonderful! I am still running ram chips @5v. I am debating the switch to 3.3v, but looking at the timings I think 5v will be best. My new board will allow for either voltage with the change of a jumper. Please take a close look at the new schematic and let me know if you see any errors or room for improvement. I will be ordering a short run of boards as soon as I figure out how to do a large layout with the free version of eagle. I plan on sending you one when I get them done.
Here's the schematics, and a basic idea for a layout. I am unable to layout a board because I am using eagle light. If you would do me a HUGE favor and throw a layout together, I will send you one when they're printed.
Can you repost that .jpg a bit bigger - I can see the chips but not the text that goes with them. (I added a .pdf 'printer' to my computer which you can then print to from any program. I think there are a number of these free pdf printers around. The pdf files can be zoomed better than a .jpg)
Re getting boards made I wonder if 3.3V memory chips would be better as there would be an extra cost with the board space required for the resistors?
The rar archive contains the schematic, png copy of the schematic as well as a basic idea for the layout. I will start printing as .pdf from now on, as per your advice.
Concerning switching to 3.3v, I guess it's really a trade-off between speed and board footprint. I'm not sure how much space those resistors would add, nor how much more it would cost. I am also unsure what difference running @5v will do to clock speed. The 161's are rated @ 4.5 and 2 volts supply. Max frequency @2v is 6mhz, at 4.5v it's 30mhz. I'm wondering if this will help speed transfers from hub to ram and ram to hub. This will not improve ram to display writes, but should double working frequency? I would be interested to see what the max you're clocking your boards at. If it's close to the 30mhz side then I would say the switch to 3.3v would be ok. If it's under half I think the 5v would be best.
If we can get the cost of a 3.3-5v board under $20 bucks, then it would be worth a short run to me.
*edit*
JP2 could be removed, and ext_out replaced with a single pin or this pin could be added to FPouts. This would save a bit of board space.
The rar archive contains the schematic, png copy of the schematic as well as a basic idea for the layout. I will start printing as .pdf from now on, as per your advice.
Yes, sorry about that - not able to extract things from the work computer. I'll take a look when I get home.
Thanks for the hints re the clock freq. Hopefully over the next few days I'll get a chance to push it all to pasm speeds. Start with some NOPs and then remove them one by one. The loop to move data from ram to display is only 4 pasm instructions plus one DJNZ so we shall see how fast it can go. I suspect the propogation of the overflow through the five 161 chips might be a limiting factor. Shouldn't matter though - 30ms vs 60ms for a screen refresh would not be noticable.
I'd still hold re getting boards made. Still a few things to test out. My working board is becoming a mess of wire wrap links and drilled out vias but it is helping refine what the final working board is going to look like. I know with what we have that this is going to be quick. I think we can get it to 'ipad' speeds - touch the display and something happens instantly. Compared with my android pandapad, I can say we have already moved beyond 'android speed' for some things. (especially bootup time). All very exciting.
I think the ram voltage is key with getting the hw as fast as possible. I agree that 30ms vs 60ms screen refresh is not perceivable, but doubling transfer speed to and from ram will be huge for me. Especially considering I will be using the 19 pins for quite a bit more than just transferring to screen and ram. My schematic allows reads from the screen, which I plan on using to dump a screen to Sd card. I also plan on being able to use p0-18 WHILE transferring from ram to display. I'm working on output expansion boards in the next few days. I'm planning several different modules, but the first to be completed will be * 2 - 4 x 40 LCD screens with 16 rotary encoders with push buttons, 16 leds and some buttons. *
I apologize for being antsy to print boards, but I do not have enough room on the breadboards I have to put this together. Don't want to buy ANOTHER board, but just might. I'm ordering parts REAL soon, having larger ram will be nice.
I totally agree that we are moving beyond android speeds. I switched back to my DUMB OLD hardware to work on Midi implementation, as well as put the finishing touches on my guitar switcher. I added mono audio out and midi i/o. Have not tested either because I'm trying to get the screen working again. I don't know what I did, but I messed something up.
I found the problem a little while ago. The wire on the ribbon cable for pin2 had broke at the solder joint with the propRPM board. This is the second wire I've had to fix. That's what happens when you ghetto rig.
So I was just looking over the datasheet for the 161's again. Found a neat little formula for cascaded counting.
1/ (CP to TC prop. delay + TE to CP setup +TE to CP hold) = about max frequency
So for my figuring from the datasheet, for 2v operation.
1 / (185 + 50 + 0) = about 4MHZ
This is a long way from 21MHZ spec'd @ 4.5V. I know we're not running @2v, but 3.3. Not sure how this scales across, but it will be interesting to see your results. Now back to making new code work on old hardware. *headache*
*edited*
I just flashed on an idea to save some board space for the PropERMidi board. Move the resistors for the lcd screen to a board that stands between the two. Not the most elegant solution, but a solution nonetheless.
Re designs, I am working tonight on the SD driver and looking at the code out there, eg Kye's driver, it really does make things a lot simpler to devote 4 dedicated prop pins to the SD card. I had devoted P21-P23 with the /CS line decoded elsewhere but it will mean customising Kye's driver and I'd rather keep it as the standard version.
So I'm going to steal P24 which is the audio output for /CS and then for audio, borrow P29 which is the eeprom data line.
Schematic attached.
I've got some spare breadboards - I'll post them to you tomorrow.
Dedicated sd pins makes things easier by far. I was able to get fsrw going with minor adjustments. On my HW 3.4, I used a decoded /cs line and passed the address of the enable pin for this line. Then before doing an sd transfer, I set the address before calling. It works, but there are problems with this. I have thought about using locks to control access to the demux lines. This will use a few clock cycles, but should provide easy, safe sharing of the demux among cogs.
Yes 4 lines just for SD card makes things easier. I'm mulling over ways of running Catalina at the same time. Instead of using the 3 pins to decode a 138, use a MCP 23008 on the I2C bus, then take 3 of those pins and decode to a 138. That frees up 3 prop pins that could be used for external SPI memory (or even more cunning things like decoding a MCP23016 or two and feeding the data via I2C.) Terribly slow compared with parallel ram, but speed does not matter so much with C programs that use caching. I might post over on the Catalina thread about this.
Also for audio, I might use some lower number pins rather than P29, and then use two pins and get stereo. Kye's original SD driver contained a wav player and it would be cool to have a music player as one of the touchscreen icons.
In a general sense, once all the prop pins have been used to move pictures around from SD card to ram to the screen, that part can go to sleep and there are now a lot of free propeller pins for MIDI and other i/o.
Hey Doc, how's the project coming? Just one quick question, what do you think about doing a left-shift every bus transaction? Would this waste too many clock cycles or do you think we could fit this in? I've been thinking about using the first 4 pins for Audio and Midi I/O.
Project slowly getting there. SD card working, touchscreen working. Display is working in Spin and now porting it over to pasm. I'm about half way through that at the moment.
I'm not sure about left shifting. It isn't just the speed, it is also whether there are enough pins. The way I am doing things, once a picture has been sent to the screen, P0-P20 are free. In practice that would mean that if you want to play a song, you can't update the screen at the same time. But you can be polling for the screen being touched. There is a potential solution though - instead of decoding P25-P27 through a 138, use a MCP23008 on the I2C bus.
Midi is a bit like RS232, right? In which case, outputs can be pins that you can enable when you need them. Inputs on the other hand need dedicated pins.
So maybe we can free up P25-P27, use two for audio, one for Midi IN, and then intermittently enable another prop pin for midi OUT (ie you can only output if the screen is not being updated).
Eh, it sounds like my idea may have taken me further from the solution. Two propeller chips are sounding better and better. One for the screen, one for the sound module. If this is the case, we could ditch midi and audio on the controller. That would free 4 pins, and chip to chip communication would be done through EEPROM pins? I don't want to mess with the programming pins, but they could be re-purposed for midi *or something else?* later. I still think I will need that `245 since I would very much like to use the 19 pins while transferring from ram to display. I have ALL SORTS of plans for these pins actually.
Midi is quite a lot like 232. 7-bit asynchronous-serial, inverted, at 31.25k? I can't remember the number exactly. The spec also uses opto-isolators to combat ground loops. Not too big of a deal. The only reason my design requires CONSTANT midi in AND OUT is because I plan on doing Midi Time Code to Midi Clock conversion and vice versa. Not a feature I will be using all the time, but it will come in VERY handy when I do need it .
Hit the reset button, it boots into a simple text display running from the propeller ROM to display "SD". If the SD card works, it loads a font and displays a message. And then it reads a picture off the SD card and displays it.
Unzip the file and put the .ili picture and the .ifn font file on the SD card.
There was a fair bit of recoding - everything changed from big-endian to little-endian. Lots of pasm code to rewrite.
But the 161 concept is sound - it is (surprisingly) faster to have 5 external counter chips than it is to use the propeller's internal counters.
The code to update the display from ram did not need any NOPs or delays. It is just 5 pasm instructions to send two bytes.
ramtodisplay_loop andn outa,maskP17 ' ILI write low
or outa,maskP17 ' ILI write high
andn outa,maskP19 ' clock 161 low
or outa,maskP19 ' clock 161 high
djnz len,#ramtodisplay_loop
76800 words = 153600 bytes, transferred in 30ms = 5.12 megabytes per second = 40.96 megabits per second.
WOW! Lemme repeat. WOW. 40.96 megabits per second is very very nice. I'll do the math but this should work quite well. I received my parts today, but decided to wait till after the expo to play with this. There's too much to work on right now, and not enough time. I pulled everything out of the project box because the inside was looking quite gross. I'm stripping the inside to bare metal and will rattle can quickly. Then put everything back together with version 3.4.2 hardware *my old pin for pin hardware with midi and audio* with some slight adjustments. Also quite a bit of coding left. I will not be working on any "throw away" code *drivers for 3.4.2 have a couple bugs, nothing major.* I can't wait to get working on the 161 based board, and I am getting close to a proposed schematic.
Keep up the great work!
I sent you a breadboard and some chips - should arrive next week. It is a large breadboard so you should be able to get all the project on one board.
I think you started off with a spin version that took 9 seconds to refresh the screen. So we are just under 300x faster than that. I've very pleased that there were no problems with the overflow delays through the 161 chips. Your circuit is so simple but so clever!
One nice thing about these fast screen refreshes - you can get on with other things like making music without having to worry about the screen so much.
I need to think about icons. The previous code used .raw files with RGBA where A is a transparency layer. I takes longer to process on the fly. I am thinking that when you load an icon, take the background where it is going to go and store that in a file and combine it with the icon file so that when you re-display that icon it draws the background at the same time. So icon files are two bytes per pixel not four, and there is a separate transparency file. It means you can't move icons so easily, but generally they stay in the same place anyway. Should speed up icon refreshes about 100x so I think it is worth it.
Have a look at how Microsoft did icons for Windows. Basically instead of an Alpha layer, they did chroma keying -- a special color is designated as "transparent" and you avoid replacing the background where that color is.
Thank you SO much! 300x is a HUGE improvement! To be honest, the credit goes to whoever came up with the idea of using a counter in the first place. The block transfer thingy you had on one of your pdf's made me think why not use 161's. Once again the idiot savant in me shines through!
Transparency is very nice, I've had some issues because I have not programmed anything for that. I don't see moving icons as too big of a deal. As long as we can define a decent sized character and move that easily *remember the old faders? gotta finish that eventually!*
G2G, Thank you SO SO SO much!
Joe
*edit*
I've been thinking about a screen designer. There are many ways to go, but my initial efforts playing with the fader idea were slow and laborious. A bank of custom, system characters will be needed. This includes transport controls such as play, pause, stop, FF, and RW. I HAD example layouts in PF, but lost these due to stupidity. They were very slow to draw since they used multiple characters. This will work WAY better and be WAY faster
Also, you need a name for your current board. Eurocard_Touchscreen_161 is too long I like "Euro-Touch++" I will examine it a few more times but it looks quite nice. Perfect for most Touch applications!
Playing around with images. Drawing a screen is so fast that it is ok to spend half a second doing a transfer from a standard file format. I took a picture off google images, ran it through paint shop pro, rotated it 90 degrees (not necessary if you reconfig the screen for landscape) resized it to 240x320 and saved it as a .raw file which is a standard RGB 3 bytes per pixel. Then convert with this little routine:
PUB RawPicture | i' take a standard RGB .raw file and convert to two byte RRRRRGGGGGGBBBBB format and fill memory
fat.openfile(string("synth.raw"),"R") ' a .raw file 240 wide, 320 high
i := 0
repeat 600
fat.readdata(@sdbuffer,384) ' 240x320=76800 bytes x3
docmd("E",@sdbuffer,@rambuffer,128) ' convert to 2 byte
HubToRam(i,128) ' send to external ram
i += 128 ' increment external ram counter
fat.closefile ' close file
DisplayPicture ' display the picture
Photo of this displaying "synth.raw"
This is what we need for audio - but maybe sliders might be better than circular knobs? Easier to use with a touchscreen?
You know that is the one problem I have been mulling over. Even the faders are a bit difficult to control. Faster screens mean drag n drop faders will be possible now, but accurately setting during live performance might be difficult. I would like at least 1 rotary encoder and probably a minimum of 8 *since I've had 3 of my friends say they think 8 minimum. A stylus will be a big improvement too!
I sent you a breadboard and some chips - should arrive next week. It is a large breadboard so you should be able to get all the project on one board. ...
Is there a PCB available? If so I would like to have one for doing a software reference design for this type of hardware. I've been thinking about this 161 load and strobe idea a long time like used int NES cartridges, but have been too busy to act on it. It would be nice to use and support an existing hardware design before making my own.
Dr Acula should have the schematic just about perfected. I'm not sure how many mods are needed for the boards he printed but if they are as extensive as he suggested, we might need a re-print. I will be supporting his hardware since I will be using modified versions of his low-level code. I need to look at the printed boards vs new schematic before I give the nod this time. If I would have been really THINKING about using the board as opposed to just looking it over, I would have caught one mistake. I am sorry about that again! Hopefully another run of boards will be made soon. I'm sure a few people will be interested even if they decide to use them purely for the ram.
I'm confused with the 74161 part of the schematic.
Ripple Carry Out "RCO" transitions low to high when Q outputs go from X to $F.
How can you guarantee that the next "nibble" counter is 0 while the first stage counter is $F?
That is: if you load $0000E to 5 counters and strobe the clock once, you want to get $0000F. Then strobe again to get $00010.
So the sequence you want is : load $0000E, strobe one gets $0000F, strobe two gets $00010.
This seems to happen instead: load $0000E, strobe one gets $0001F, strobe two gets $00010.
What really happens? Don't you need an inverter on the RCO for clocking the next stage?
It's ok, these chips can be a bit confusing. Pay close attention to the operation of load. That's what got Drac the first time. He was worried about propagation delays and the like when these things seem to work quite well. One more piece of advice, Dr Acula's very nice design keeps all chips at 3.3v. If you look at the datasheets, they are quite de-rated at 2 volts. I'm sure 3.3 is quite better, but 5v seems best for super-high speed operation. Plus 5v tolerant ram is less expensive than 3v. I plan on using 5v and some additional circuitry but need to actually try a few things before I commit. My thread has the most recent schematic I've written. It is not done and changes are small at this point. The inverter on the reset line is going away and getting replaced with an transistor - inverter. LCD wr/rd will be hooked up to Function Register. '374 http://forums.parallax.com/showthread.php?137999-LCD-touchscreen-A-development-thread
See, this is what I'm worried about myself. That's why I'm going to try it after the expo. I'm stuck with thru-hole components for now. Adapters are not out of the question, but if that's the case I may just go completely SMD and have an excuse to upgrade my tools.
Comments
I got most of the components from futurlec, but they can take a couple of weeks to arrive and sometimes it is hard to find parts on their website that you know they sell.
I found a mistake on the board. I'm using P16 for the clock and I need to use P19 or higher. I didn't read the spec sheet closely enough I thought the data was loaded when the load went from low to high, but it isn't - see below.
So some tracks are going to need to be cut and moved. I think it will be a matter of driving all the clocks from P19 instead of P16, and then driving the memory /RD from P16 instead of P19. I'll need to think about where to put the changes on the board.
addit - found a few more things on the board that are not quite right. Apart from swapping things above, I think the schematic is right though. Hmm - I might have to hold off posting any boards though. Maybe better to build this on a breadboard first?
I did decide to order regulators and all necessary components.
I think it might be a good idea to breadboard first. I always start here if possible. Cutting a few traces is not a huge deal to me, but I will leave this up to you. I've been working on the old ili driver and almost done with ram to hub and hub to ram transfers. I need to get a jump start on homework for next week, but after this is done I will continue working.
*edit*
Okay, I've been working on the driver and hit an issue. I'm looking at the datasheet for my hc counters and see max clock 25MHZ @ 4.5V, 5MHZ @ 2v. *I'm going to slow it down for the LS, but will be going full HC - 3.3V compatible* So. How should I guestimate the timing cycle? Any advice? Just start slow and speed it up till it won't run?
another edit
I've been working on the ram read and write in ASM. None of this is tested, but I'm trying to get a framework. I think this should be close. I will keep updating this until it works, I just wanted to get a start so you could make suggestions. Also, here's the schematic
I did not want to use the inverters, but couldn't think of an easier way. Let me know what you think!
*edited*
I found more issues. I forgot to remove a few resistors from the lcd lines. I am also thinking about adding a 4 pin jumper for midi I/O or PS2 port.
I got routines working tonight to transfer data from hub to ram and ram to hub
So - move data from SD card to propeller, prop to external ram, external ram back to prop, and external ram to the display. This last one is where the fast refresh works with 30ms to do a screen. It is super simple in spin and so will easily translate over to pasm
This little bit of code fills the screen from the ram with 76800 pixels (15% of the ram capacity)
and the speed in spin is 5.5 seconds, which I think compares favorably with the previous speed around 9 seconds. This is going to be very fast in pasm.
This 161 driver is brilliant!
Full program:
Here's the schematics, and a basic idea for a layout. I am unable to layout a board because I am using eagle light. If you would do me a HUGE favor and throw a layout together, I will send you one when they're printed.
Re getting boards made I wonder if 3.3V memory chips would be better as there would be an extra cost with the board space required for the resistors?
Concerning switching to 3.3v, I guess it's really a trade-off between speed and board footprint. I'm not sure how much space those resistors would add, nor how much more it would cost. I am also unsure what difference running @5v will do to clock speed. The 161's are rated @ 4.5 and 2 volts supply. Max frequency @2v is 6mhz, at 4.5v it's 30mhz. I'm wondering if this will help speed transfers from hub to ram and ram to hub. This will not improve ram to display writes, but should double working frequency? I would be interested to see what the max you're clocking your boards at. If it's close to the 30mhz side then I would say the switch to 3.3v would be ok. If it's under half I think the 5v would be best.
If we can get the cost of a 3.3-5v board under $20 bucks, then it would be worth a short run to me.
*edit*
JP2 could be removed, and ext_out replaced with a single pin or this pin could be added to FPouts. This would save a bit of board space.
Yes, sorry about that - not able to extract things from the work computer. I'll take a look when I get home.
Thanks for the hints re the clock freq. Hopefully over the next few days I'll get a chance to push it all to pasm speeds. Start with some NOPs and then remove them one by one. The loop to move data from ram to display is only 4 pasm instructions plus one DJNZ so we shall see how fast it can go. I suspect the propogation of the overflow through the five 161 chips might be a limiting factor. Shouldn't matter though - 30ms vs 60ms for a screen refresh would not be noticable.
I'd still hold re getting boards made. Still a few things to test out. My working board is becoming a mess of wire wrap links and drilled out vias but it is helping refine what the final working board is going to look like. I know with what we have that this is going to be quick. I think we can get it to 'ipad' speeds - touch the display and something happens instantly. Compared with my android pandapad, I can say we have already moved beyond 'android speed' for some things. (especially bootup time). All very exciting.
I apologize for being antsy to print boards, but I do not have enough room on the breadboards I have to put this together. Don't want to buy ANOTHER board, but just might. I'm ordering parts REAL soon, having larger ram will be nice.
I totally agree that we are moving beyond android speeds. I switched back to my DUMB OLD hardware to work on Midi implementation, as well as put the finishing touches on my guitar switcher. I added mono audio out and midi i/o. Have not tested either because I'm trying to get the screen working again. I don't know what I did, but I messed something up.
So I was just looking over the datasheet for the 161's again. Found a neat little formula for cascaded counting.
1/ (CP to TC prop. delay + TE to CP setup +TE to CP hold) = about max frequency
So for my figuring from the datasheet, for 2v operation.
1 / (185 + 50 + 0) = about 4MHZ
This is a long way from 21MHZ spec'd @ 4.5V. I know we're not running @2v, but 3.3. Not sure how this scales across, but it will be interesting to see your results. Now back to making new code work on old hardware. *headache*
*edited*
I just flashed on an idea to save some board space for the PropERMidi board. Move the resistors for the lcd screen to a board that stands between the two. Not the most elegant solution, but a solution nonetheless.
Re designs, I am working tonight on the SD driver and looking at the code out there, eg Kye's driver, it really does make things a lot simpler to devote 4 dedicated prop pins to the SD card. I had devoted P21-P23 with the /CS line decoded elsewhere but it will mean customising Kye's driver and I'd rather keep it as the standard version.
So I'm going to steal P24 which is the audio output for /CS and then for audio, borrow P29 which is the eeprom data line.
Schematic attached.
I've got some spare breadboards - I'll post them to you tomorrow.
Also for audio, I might use some lower number pins rather than P29, and then use two pins and get stereo. Kye's original SD driver contained a wav player and it would be cool to have a music player as one of the touchscreen icons.
In a general sense, once all the prop pins have been used to move pictures around from SD card to ram to the screen, that part can go to sleep and there are now a lot of free propeller pins for MIDI and other i/o.
I'm not sure about left shifting. It isn't just the speed, it is also whether there are enough pins. The way I am doing things, once a picture has been sent to the screen, P0-P20 are free. In practice that would mean that if you want to play a song, you can't update the screen at the same time. But you can be polling for the screen being touched. There is a potential solution though - instead of decoding P25-P27 through a 138, use a MCP23008 on the I2C bus.
Midi is a bit like RS232, right? In which case, outputs can be pins that you can enable when you need them. Inputs on the other hand need dedicated pins.
So maybe we can free up P25-P27, use two for audio, one for Midi IN, and then intermittently enable another prop pin for midi OUT (ie you can only output if the screen is not being updated).
Midi is quite a lot like 232. 7-bit asynchronous-serial, inverted, at 31.25k? I can't remember the number exactly. The spec also uses opto-isolators to combat ground loops. Not too big of a deal. The only reason my design requires CONSTANT midi in AND OUT is because I plan on doing Midi Time Code to Midi Clock conversion and vice versa. Not a feature I will be using all the time, but it will come in VERY handy when I do need it .
Hit the reset button, it boots into a simple text display running from the propeller ROM to display "SD". If the SD card works, it loads a font and displays a message. And then it reads a picture off the SD card and displays it.
Unzip the file and put the .ili picture and the .ifn font file on the SD card.
There was a fair bit of recoding - everything changed from big-endian to little-endian. Lots of pasm code to rewrite.
But the 161 concept is sound - it is (surprisingly) faster to have 5 external counter chips than it is to use the propeller's internal counters.
The code to update the display from ram did not need any NOPs or delays. It is just 5 pasm instructions to send two bytes.
76800 words = 153600 bytes, transferred in 30ms = 5.12 megabytes per second = 40.96 megabits per second.
Keep up the great work!
I think you started off with a spin version that took 9 seconds to refresh the screen. So we are just under 300x faster than that. I've very pleased that there were no problems with the overflow delays through the 161 chips. Your circuit is so simple but so clever!
One nice thing about these fast screen refreshes - you can get on with other things like making music without having to worry about the screen so much.
I need to think about icons. The previous code used .raw files with RGBA where A is a transparency layer. I takes longer to process on the fly. I am thinking that when you load an icon, take the background where it is going to go and store that in a file and combine it with the icon file so that when you re-display that icon it draws the background at the same time. So icon files are two bytes per pixel not four, and there is a separate transparency file. It means you can't move icons so easily, but generally they stay in the same place anyway. Should speed up icon refreshes about 100x so I think it is worth it.
Transparency is very nice, I've had some issues because I have not programmed anything for that. I don't see moving icons as too big of a deal. As long as we can define a decent sized character and move that easily *remember the old faders? gotta finish that eventually!*
G2G, Thank you SO SO SO much!
Joe
*edit*
I've been thinking about a screen designer. There are many ways to go, but my initial efforts playing with the fader idea were slow and laborious. A bank of custom, system characters will be needed. This includes transport controls such as play, pause, stop, FF, and RW. I HAD example layouts in PF, but lost these due to stupidity. They were very slow to draw since they used multiple characters. This will work WAY better and be WAY faster
Also, you need a name for your current board. Eurocard_Touchscreen_161 is too long I like "Euro-Touch++" I will examine it a few more times but it looks quite nice. Perfect for most Touch applications!
Photo of this displaying "synth.raw"
This is what we need for audio - but maybe sliders might be better than circular knobs? Easier to use with a touchscreen?
Is there a PCB available? If so I would like to have one for doing a software reference design for this type of hardware. I've been thinking about this 161 load and strobe idea a long time like used int NES cartridges, but have been too busy to act on it. It would be nice to use and support an existing hardware design before making my own.
Thanks,
--Steve
Ripple Carry Out "RCO" transitions low to high when Q outputs go from X to $F.
How can you guarantee that the next "nibble" counter is 0 while the first stage counter is $F?
That is: if you load $0000E to 5 counters and strobe the clock once, you want to get $0000F. Then strobe again to get $00010.
So the sequence you want is : load $0000E, strobe one gets $0000F, strobe two gets $00010.
This seems to happen instead: load $0000E, strobe one gets $0001F, strobe two gets $00010.
What really happens? Don't you need an inverter on the RCO for clocking the next stage?
Thanks,
--steve
The 74LV161 widely available in TSSOP and SO packages. That plus an extra $1 per SRAM beats analog uncertainty to me.