Okay, burst read working. I have not stuffed it into the touch.spin but I'll try to get that done soon.
needed to set up Pcounters for burst read, done on init
get_values mov ptr, hubaddr ' get hub address
mov count, line_size ' get ram address
'shr count, #1 ' shift data to word alligned from byte
'shr vmaddr, #1 ' shift data to word alligned from byte
mov dirb,latchvalue ' make copy of latchvalue here for restore
or outa,maskP16P20 ' set control pins high
or dira,maskP16P20 ' set control pins P16-P20 as outputs
get_values_ret ret
set373 or outa,maskP22 ' pin 22 high
or dira,#%1_11111111 ' enable pins 0-7 and 8 as outputs
and outa,maskP0P8low ' P0-P8 low
or outa,latchvalue ' send out the data
or outa,maskP8 ' P8 high, clocks out data
andn outa,maskP22 ' pin 22 low
set373_ret ret
set161 mov latchvalue,#%11111110 ' group 1, displays all off
call #set373 ' send out to the latch
and outa,maskP0P20low '%11111111_11100000_00000000_00000000
or dira,maskP0P20 '%00000000_00011111_11111111_11111111
or outa,vmaddr ' send out ramaddr
or outa,maskP20 ' clock high
or outa,maskP19 ' load high
or outa,maskP16P20 ' set control pins high
mov latchvalue,#%11111101 ' group 2, displays all off
call #set373 ' send out to the latch
set161_ret ret
and the transfers
' command S
pasmhubtoram call #get_values ' get hubaddr,ramaddr,len and set control pins
call #set161
hubtoram_loop and outa,maskP16P31 '%11111111_11111111_00000000_00000000 ' clear for output
rdword data_16,ptr ' get the word from hub
and data_16,maskP0P15 ' mask to a word only
or outa,data_16 ' send out the byte to P0-P15
andn outa,maskP17 ' set mem write low
add ptr,#2 ' increment by 2 bytes = 1 word. Put this here for small delay while writes
or outa,maskP17 ' mem write high
andn outa,maskP20 ' clock 161 low
or outa,maskP20 ' clock 161 high
djnz count,#hubtoram_loop ' loop this many times
mov latchvalue, dirb ' restore latch value
call #set373
and dira, maskP0P20low ' tristates all the common pins, leaves P22 as is though
' jmp #done ' tristate pins and listen for commands
' command S
wr_cache_line_ret ret
'-----------------------------------------------
' setups needed for burst read
'-----------------------------------------------
_frqa long $1000_0000
_ctra long 4<<26 | 20 ' NCO mode on P20
_phsa long $0000_0000 ' phsa offset for adjusting clock start
_frqb long 2 ' phsb accumulates twice per edge
_ctrb long $A<<26| 20 ' Edge Accumulate mode on P20
'----------------------------------------------------------------------------------------------------
'
' rd_cache_line - read a cache line from external memory
'
' vmaddr is the external memory address to read
' hubaddr is the hub memory address to write
' line_size is the number of bytes to read
'
'----------------------------------------------------------------------------------------------------
rd_cache_line
' command T
pasmramtohub call #get_values ' get hubaddr,ramaddr,len and set control pins
call #set161
and dira,maskP16P31 '%11111111_11111111_00000000_00000000 inputs
andn outa,maskP16 ' memory /rd low
'insert bus read here
or outa,maskP20 ' get clock line?
mov phsa, _phsa ' init counters phsa
mov phsb, ptr ' save hub ptr to phsb
mov ctrb, _ctrb ' set ctr be mode
andn outa,maskP20 ' start counters
rdword data_16,phsb ' sync up only
mov ctra, _ctra ' enable address counter clk
ramtohub_loop ' 10MB/s read loop uses phsb for hub pointer
mov data_16,ina ' get first data
wrword data_16,phsb ' move data to hub
djnz count,#ramtohub_loop
or outa,maskP20 ' stop clock
mov ctra, #0 ' stop counter
or outa,maskP16 ' memory /rd high
' or dira,maskP0P15 ' %00000000_00000000_11111111_11111111 restore P0-P15as outputs
and dira, maskP0P20low ' tristates all the common pins, leaves P22 as is though
rd_cache_line_ret ret
' variables
pasm_n long 0 ' general purpose value
data_16 long 0 ' general purpose value
latchvalue long %00000000_00000000_00000000_00000000 ' current 373 value
' constants
'Zero long %00000000_00000000_00000000_00000000 ' used in several places
maskP0P2low long %11111111_11111111_11111111_11111000 ' P0-P2 low
maskP0P20 long %00000000_00011111_11111111_11111111 ' P0-P18 enabled for output plus P19,P20
maskP0P18low long %11111111_11111000_00000000_00000000 ' P0-P18 low
maskP16 long %00000000_00000001_00000000_00000000 ' pin 16
maskP17 long %00000000_00000010_00000000_00000000 ' pin 17
maskP18 long %00000000_00000100_00000000_00000000 ' pin 18
maskP19 long %00000000_00001000_00000000_00000000 ' pin 19
maskP20 long %00000000_00010000_00000000_00000000 ' pin 20
maskP22 long %00000000_01000000_00000000_00000000 ' pin 22
maskP16P31 long %11111111_11111111_00000000_00000000 ' pin 16 to pin 31
maskP0P15 long %00000000_00000000_11111111_11111111 ' for masking words
maskP16P20 long %00000000_00011111_00000000_00000000
maskP0P20low long %11111111_11100000_00000000_00000000 ' for returning all group pins HiZ
maskP16P17P20 long %00000000_00010011_00000000_00000000
maskP0P8low long %11111111_11111111_11111110_00000000 ' P0-P7 low
maskP8 long %00000000_00000000_00000001_00000000 ' pin 8
I needed a break from the cache driver, so I decided to see how fast I could get transfers to run... Using the counters for burst read was not too hard thanks to Jazzed.
'setups for burst read
'-----------------------------------------------
' setups needed for burst read
'-----------------------------------------------
rd_phsa long $0000_0000 ' phsa offset for adjusting clock start
rd_frqa long $1000_0000
rd_ctra long 4<<26 | 20 ' NCO mode on P20
rd_frqb long 2 ' phsb accumulates twice per edge
rd_ctrb long $A<<26| 20 ' Edge Accumulate mode on P20
pasmramtohub call #get_values ' get hubaddr,ramaddr,len and set control pins
call #set161
or outa,maskP16P20 ' set control pins high
mov latchvalue,#%11111101 ' group 2, displays all off
call #set373 ' send out to the latch
and dira,maskP16P31 '%11111111_11111111_00000000_00000000 inputs
andn outa,maskP16 ' memory /rd low
'insert burst read here
or outa,maskP20 ' get clock line?
mov phsa, rd_phsa ' init counters phsa
mov phsb, hubaddr ' save hub ptr to phsb
'ctrb setup for burst read
mov frqb, rd_frqb ' setup EDGE freq
mov ctrb, rd_ctrb ' set ctr be mode
'ctra setup for burst read
mov frqa, rd_frqa ' setup NCO freq
andn outa,maskP20 ' start counters
rdword data_16,phsb ' sync up only 1-2
mov ctra, rd_ctra ' enable address counter clk 3 1
ramtohub_loop ' 10MB/s read loop uses phsb for hub pointer
mov data_16,ina ' get first data 4 2
wrword data_16,phsb ' move data to hub 1-2 3-4
djnz len,#ramtohub_loop ' 3 5
or outa,maskP20 ' stop clock
mov ctra, #0 ' stop counter
or outa,maskP16 ' memory /rd high
jmp #done
Then I wanted to see if I could tune the hub to display, as it was taking 3 hub-slots to complete...
' command V
pasmhubtodisplay call #get_values ' get hubaddr,ramaddr,len and set control pins high
andn outa,maskP19 ' CS low
or dira,maskP0P15 '%00000000_00000000_11111111_11111111
hubtodisplay_loop and outa,maskP16P31 '%11111111_11111111_00000000_00000000 ' clear for output
rdword data_16,hubaddr ' get the word from hub
'and data_16,maskP0P15 ' mask to a word only
or outa,data_16 ' send out the byte to P0-P15
andn outa,maskP18 ' ILI write low
or outa,maskP18 ' ILI write high
add hubaddr,#2 ' one word
djnz len,#hubtodisplay_loop
or outa,maskP19 ' CS high
jmp #done
Then I tried to get hub to ram running the burst... and failed. and failed. and failed...
So I moved on to the ram to display... Not much to trim really, just 5 instructions. Well it took forever but I got it down to 2.
'-----------------------------------------------
' setups needed for burst read to display
'-----------------------------------------------
ds_phsa long $0000_0000 ' phsa offset for adjusting clock start
ds_frqa long $2000_0000
ds_ctra long 4<<26 | 20 ' NCO mode on P20
ds_phsb long $0000_0000 ' phsb offset for adjusting clock start
ds_frqb long $2000_0000 ' phsb accumulates twice per edge
ds_ctrb long 4<<26 | 18 ' NCO mode on P18
fastpasmramtodisplay call #get_values ' get hubaddr,ramaddr,len (only uses len) and set control pins
sub len, #2
call #set161
or outa,maskP16P20 ' set control pins high
mov latchvalue, dirb
call #set373
and dira,maskP16P31 ' %11111111_11111111_00000000_00000000 so prop pins 0-15 HiZ
andn outa,maskP19 ' CS low
andn outa,maskP16 ' ram /rd low
'ctra setup for burst read
mov phsa, ds_phsa ' init counters phsa P20
mov phsb, ds_phsb ' init to phsb P18
mov frqa, ds_frqa ' setup NCO freq P20
mov frqb, ds_frqb ' setup NCO freq P18
andn outa,maskP20 ' start counters P20
andn outa,maskP18 ' start counters P18
' P20 Count P18 Write
mov ctrb, ds_ctrb ' enable display clk P18 0 2 4 6 8
mov ctra, ds_ctra ' enable address counter clk P20 2 4 6 8 10 12 14 0
fastramtodisplay_loop 'andn outa,maskP18 ' ILI write low
'or outa,maskP18 ' ILI write high
'andn outa,maskP20 ' clock 161 low
'or outa,maskP20 ' clock 161 high
nop ' 10 12 14 0 2 4 6 8
djnz len,#fastramtodisplay_loop ' 2 4 6 8 10 12 14 0
' 10 12 14 0 2 4 6 8
mov ctrb, #0 ' stop counter 2 4 6 8 10 12 14 0
mov ctra, #0 ' stop counter
or outa,maskP20 ' stop clock
or outa,maskP18 ' stop clock
or outa,maskP16 ' mem /rd high
or outa,maskP19 ' CS high
jmp #done
One slight problem, seems it doesn't quite work right? I am able to draw backgrounds, but everything else draws garbage? I need to think through it a bit, but if I can get the counter code to work, it will be as fast as the display can draw! Now that I have it partially working, I will take a look at hub to ram. It might help me figure out what I'm doing wrong.
Now, just for my sanity in case I screw something up
DAT
'' +-----------------------------------------------------------------------------------------------+
'' | Touchblade 161 Ram Driver (with grateful acknowlegements to Cluso Jazzed and Average Joe) |
'' +-----------------------------------------------------------------------------------------------+
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)
init 'set up latches here
or outa,maskP22 ' pin 22 high
or dira,maskP22 ' and now set as an output
mov dirb, #%11111111 'set latch All hi
' Initialise hardware tristates everything and read/write set the pins
done mov err, #0 ' reset err=false=good
mov latchvalue, dirb ' restore latch value
call #set373
and dira,maskP0P20low ' tristates all the common pins, leaves P22 as is though
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, #"S" wz ' hub to ram ''S
if_z jmp #pasmhubtoram
cmp cmd, #"T" wz ' ram to hub ''T
if_z jmp #pasmramtohub
cmp cmd, #"U" wz ' ram to display ''U
if_z jmp #pasmramtodisplay
cmp cmd, #"V" wz ' hub to display ''V
if_z jmp #pasmhubtodisplay
cmp cmd, #"E" wz ' convert 3 byte .raw format to 2 byte .ili format - hub to hub ''E
if_z jmp #rawtoiliformat
cmp cmd, #"F" wz ' convert 3 byte .bmp format BGR to 2 byte ili format (same as E but order reversed) ''F
if_z jmp #bmptoiliformat
cmp cmd, #"X" wz ' merge icon and background based on a mask ''X
if_z jmp #mergeicons
cmp cmd, #"Z" wz ' set the 161 counters ''Z
if_z jmp #extset161
cmp cmd, #"M" wz ' pass current latch value to pasm ''M
if_z jmp #latch373value
cmp cmd, #"I" wz ' init ''I
if_z jmp #init
cmp cmd, #"W" wz ' fast RAM to display, doesn't work right? ''I
if_z jmp #init
mov err, cmd ' error = cmd (unknown command)
jmp #done
' ----------------- common routines -------------------------------------
get_values rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
mov dirb,latchvalue ' make copy of latchvalue here for restore
or outa,maskP16P20 ' set control pins high
or dira,maskP16P20 ' set control pins P16-P20 as outputs
get_values_ret ret
set373 or outa,maskP22 ' pin 22 high
or dira,#%1_11111111 ' enable pins 0-7 and 8 as outputs
and outa,maskP0P8low ' P0-P8 low
or outa,latchvalue ' send out the data
or outa,maskP8 ' P8 high, clocks out data
andn outa,maskP22 ' pin 22 low
set373_ret ret
set161 mov latchvalue,#%11111110 ' group 1, displays all off
call #set373 ' send out to the latch
and outa,maskP0P20low '%11111111_11100000_00000000_00000000
or dira,maskP0P20 '%00000000_00011111_11111111_11111111
or outa,ramaddr ' send out ramaddr
or outa,maskP20 ' clock high
or outa,maskP19 ' load high
set161_ret ret
'' *** command Z **********
'changes the latch so displays won't work unless resend the spin value for the latch
extset161 call #get_values ' gets ramaddr = the 161 value to set
mov dirb, latchvalue
call #set161
jmp #done ' tristates pins etc
' *** command M - pass current latch value and send out
latch373value call #get_values
mov dirb,hubaddr
jmp #done
' variables
pasm_n long 0 ' general purpose value
data_16 long 0 ' general purpose value
ililow long 0 ' low data byte
ilihigh long 0 ' high data byte
red long 0 ' red, green blue variables
green long 0
blue long 0
' constants
Zero long %00000000_00000000_00000000_00000000 ' used in several places
'maskP0P2low long %11111111_11111111_11111111_11111000 ' P0-P2 low
maskP0P20 long %00000000_00011111_11111111_11111111 ' P0-P18 enabled for output plus P19,P20
maskP0P18low long %11111111_11111000_00000000_00000000 ' P0-P18 low
maskP16 long %00000000_00000001_00000000_00000000 ' pin 16
maskP17 long %00000000_00000010_00000000_00000000 ' pin 17
maskP18 long %00000000_00000100_00000000_00000000 ' pin 18
maskP19 long %00000000_00001000_00000000_00000000 ' pin 19
maskP20 long %00000000_00010000_00000000_00000000 ' pin 20
maskP22 long %00000000_01000000_00000000_00000000 ' pin 22
maskP16P31 long %11111111_11111111_00000000_00000000 ' pin 16 to pin 31
maskP0P15 long %00000000_00000000_11111111_11111111 ' for masking words
maskP16P20 long %00000000_00011111_00000000_00000000
maskP0P20low long %11111111_11100000_00000000_00000000 ' for returning all group pins HiZ
maskP0P8low long %11111111_11111111_11111111_00000000 ' P0-P7 low
maskP8 long %00000000_00000000_00000001_00000000 ' pin 8
latchvalue long %00000000_00000000_00000000_00000000 ' current 373 value
Wow, pushing things to the limit there. I'm a bit lost with the cache driver - I need to step back and understand it at a more fundamental level. Can you do it with a simple pasm call? I see code inserted here and there, maybe we can simply add a cache driver to this pasm driver and put some common routines into their own subroutines? I don't know how much space there is left in that cog but it would be really nifty if the cache driver used the same cog as you don't even need locks then.
Once the boards arrive, are you going to solder one up just to double check it works? If you do, take some photos along the way as that could be useful for a writeup of how to build the board.
The expansion boards are on the way, will be maybe another couple of weeks to get to you.
I'm playing around with some crazy stuff trying to translate vb.net into spin. (and then with ersmith's routine, spin into C).
Rather than work with objects, which spin is not very good at, I'm thinking more in terms of a single database. You put data in and then you request it out again. So a description of a screen like a synthesizer or a button is a list of information.
With a few minor changes, you can send that straight into a database as strings. Maybe lose the "new system.drawing.size" and just store the numbers. Storing strings is easy with the touch.spin object.
Then do a sort on the entire database. Either pre compilation or in code, it does not matter. Then request data out of the database, eg an object name, then the size of the object and that gives you areas of the screen that respond when you touch them.
So two essential things here are a sort algorithm (ideally a quicksort, but since this is only done once, ye olde inefficient bubble sort will do). Then a binary search algorithm to extract the data. So I have this silly little bit of code
PUB Main | touchtest ' debug value
tch.BeginProgram
Bubblesort(1,6) ' sort the list
tch.stringstore(0,string("Elephant")) ' search for this
touchtest := BinarySearch(1,6) ' do a binary search
tch.text(string("Found answer"))
tch.hex(touchtest,2) ' zero if no match
PUB BubbleSort(start,finish) | i,swap
tch.stringdim(10) ' uses string0 as a temp store
tch.stringstore(1,string("Bee"))
tch.stringstore(2,string("Cow"))
tch.stringstore(3,string("Dog"))
tch.stringstore(4,string("Aardvark"))
tch.stringstore(5,string("Elephant"))
tch.stringstore(6,string("Giraffe"))
repeat
swap := false
repeat i from start to (finish-1)
if tch.stringcompare(i,i+1) >0
tch.stringcopy(0,i) ' swap
tch.stringcopy(i,i+1)
tch.stringcopy(i+1,0)
swap := true
until swap == false ' repeat until no swaps happened
repeat i from start to finish ' print out the answers in alphabetical order
tch.stringdebug(i)
PUB BinarySearch(start,finish) | imid, imin, imax,compare ' http://en.wikipedia.org/wiki/Binary_search_algorithm
imin := start
imax := finish ' string(0) is the key to search
compare := -1 ' if not found returns zero
repeat while (imax => imin) ' repeat until found
imid := (imin + imax) >> 1 ' (imin+imax)/2
compare := tch.stringcompare(0,imid)
if compare > 0 ' search the upper half
imin := imid + 1
if compare < 0 ' search the lower half
imax := imid - 1
if compare == 0
result := imid
imax := 0 ' ends the routine
And I think we can pull data in and out of that database without having to worry about getting mixed string/number objects working in spin. A database working in just strings, and only in external memory is a very nice thing as you don't have to worry about conserving memory any more. Store all the descriptions of the screen objects long hand like vb.net does and you can always go and extract data later. Plus it demonstrates some of the string routines (thanks Kye!).
Guys
I have been following this thread since post 1 and as a result purchased a 3.2" board from egochina and have had hours of 'fun'.
I was thinking along the lines of using counters and ram and then off you went and did it, but I didn't!
First of all I must come clean and admit that I am using an arduino at the moment which means that at a clock of 16 Mhz and ONLY a single processor my computing resources are small in comparison to the mighty prop. (I have a cameleon on the shelf but to my shame its only been used in arduino mode - I also have a raspberry pi in the same place - I just dont have the time to invest in learning new architectures while I am able to play with interesting periferals like this touch screen).
Because of my shortage of pins I have had to use spi and a couple of 574's used as shift registers to provide the 16 data pins, so where you are getting 30 frames a second I get 1/2. But thats ok because for my needs thats PLENTY fast enough, and I am able to display bitmaps recalculated for the 5-6-5 screen colour format, and fonts - I have used the DOS font 8 bit by 16, ie 16 bytes per character, and saved as an array, and by having global backgroung forground colours use these when reading the on/off bits that make up the character as I write/overwrite the display .
Now to my question - it regards the relatively trivial task of reading the touch screen position. My code works, and if I hadn't read your post that when the screen is not touched the reading gives co-ordinates off screen, and therefore using the interrupt pin is not required, I wouldn't be bothering you now.
Well I dont get the same results and it is a REAL PAIN; I get a no touch reading of somewhere in the middle of the screen!
So I wonder if you could share the code/method you use to read the touch position.
I use 8 bit mode; so I set CS low, and (for x axis) send 0x93 (0xD3 for 'Y' axis) and ignore the return byte, then I send 0x00 and use the returned byte as my result. I know that I am wasting the lsbit but I still get results of 1 - 110 on both X and Y axis. This I do 32 times for each axis and average the result (>>5).
I have not put a pullup resistor on the int pin (since I'm not using it) and maybe doing this gives a no touch bias to offscreen - I dont know, I havent had the energy to try.
Perhaps you are doing it differently; I would really like to know.
If you could summarise the way you have connected yours and the mode and algorythm you use I would be grateful.
By the way - just as a matter of interest - The arduino is 5v and the display is 3 volt - and all I do is put a 22K resistor in series in the data and control lines and so far the screen hasn't complained - I guess the protection diodes in the display are doing their stuff.
In My opinion threads like this are like gold and are required daily reading.
Thanks
Dave
Hi Dave,
Not much time but hopefully this will help.
PRI TouchX
SPI.SHIFTOUT(Touch_DataIn, Touch_Clock, 5, 8 , %1101_0000) ' reads x from 500 to 3700 (off < 500 )
result := SPI.SHIFTIN(Touch_DataOut,Touch_Clock,2, 12)
PRI TouchY
SPI.SHIFTOUT(Touch_DataIn, Touch_Clock, 5, 8 , %1001_0000) ' reads y from 400 to 3800 (off > 3800 )
result := SPI.SHIFTIN(Touch_DataOut,Touch_Clock,2, 12)
The shiftout is Data, Clock MSBFIRST, 8bits. The shiftin is Data, Clock, MSBPost, 12bits..
I'll be around later to try and clarify
Joe
*edit*
I've had some more time to re-read the post and I'm not entirely sure of your communication algorithm. I will see if I can track down the C code for the touchscreen.
The INT pin is not needed and left unconnected on our board.
Now in my experience, *and this may or may not apply toward your issue* if there is "gunk" on the display it can register a false touch. There is also the issue of the first read from the touchscreen returning incorrectly occasionally. To me it sounds as if the 8bit SPI mode may or may not be an issue.
Now, we are sending "D0" for touchX and "90" for touchY. The ADS7843 touchscreen controller datasheet is here : http://www.ti.com/lit/ds/symlink/ads7843.pdf
No time to double check right now but RTFM may help!
If you have the display, then you may be interested in our board. It's VERY nice and quite a bit faster than 30fps. A full screen draw from RAM file is well under 30ms. Calculating ACTUAL fps depends on the number of FILES drawn from ram * Size of draw, plus spin overhead to setup the draw, ect. I will be taking video soon, but all I can say is Propeller+161addressed SRAM is "The Way To Go!" Well worth the $55 for components.
BTW: If you are interested in JUST the board, I would send you one if you pay shipping. Also able to arrange Full/Partial kits. PM for details
James,
Re Cache driver: I'm still trying to figure things out, need to take a break for a couple days. It should be quite possible to integrate the cache driver with the PASM driver. There should be plenty of room in the cog, it's just a matter of getting things to work properly. My cache driver passed the cache tests, but failed running "hello world" from SimpleIDE. Like I said, need a short break. I'll resume work next week.
Production boards arrived today. I plan on soldering one up and taking photos/video when I do.. Sadly I'm quite short on bypass caps, so I need to get the 2 kits together and see if I have enough to build the new board. It will be close, that's for sure. If I don't, I can de-solder a few from previous boards. *Waiting for my new heat-gun to arrive to bulk de-solder previous boards.*
Very, Very interesting stuff you've been working on. I think it should make some things a snap. WAY cool!
I've been concerned with getting the PASM driver perfected, and as fast as possible. We're to the point where it shouldn't need changing any time soon. This is proving to be a bit of a challenge since I've never DIRECTLY programmed for the propeller counters. I'm getting it though and learning quite a bit, so that's good. The one thing that's boggling me is the FASTRamToDisplay... I have not really "played" with it too much so it's probably simple. The one thing I've observed is this: When running my simple splash screen test, I can draw the background *first file* but when drawing textT *don't know where yet* it garbles the display and gets stuck in the R2D loop? I'll play with this later, hopefully more information can solve the problem.
This is the working/old transfer
pasmramtodisplay call #get_values ' get hubaddr,ramaddr,len (only uses len) and set control pins
call #set161
or outa,maskP16P20 ' set control pins high
mov latchvalue, dirb
call #set373
andn outa,maskP19 ' CS low
and dira,maskP16P31 ' %11111111_11111111_00000000_00000000 so prop pins 0-15 HiZ
andn outa,maskP16 ' ram /rd low
ramtodisplay_loop andn outa,maskP18 ' ILI write low
or outa,maskP18 ' ILI write high
andn outa,maskP20 ' clock 161 low
or outa,maskP20 ' clock 161 high
djnz len,#ramtodisplay_loop
or outa,maskP16 ' mem /rd high
or outa,maskP19 ' CS high
jmp #done
The new transfer starts the same but adds
sub len, #2
To make up for the 2 extra transfers, one at the beginning of the loop when turning counters on, and one at the end when turning them off.
THEN set the counters up:
mov ctrb, #0 ' stop counter 2 4 6 8 10 12 14 0
mov ctra, #0 ' stop counter
or outa,maskP20 ' stop clock
or outa,maskP18 ' stop clock
or outa,maskP16 ' mem /rd high
or outa,maskP19 ' CS high
jmp #done
The numbers on the side are the counter accumulation. This helped me figure out what was going on in the counters. I think it should work properly, but as I said it fails drawing text. I'll try drawing elements with it to determine more and let you know what I figure out!
*aedit*
After some more testing, fastR2D works in all cases of DrawBMPToRam, now to figure out why TextT doesn't work right?
*more edit!*
Seems fast draws now work correctly? Still need to debug. Speaking of bugs, I found one in the photo app, need to add code below after checking touchscreen to keep 2 < picturenumber < 7
if result > 0
if picturenumber > 2
picturenumber --
else
picturenumber := 6
else
picturenumber ++
I'm also missing several bmps for the signal generator as well as all files for HTML.
Hi average joe
Thanks for your help, especially seeing how busy you must be with your project, and please do not go to any trouble searching out any more info for me, but if you have 5 minutes you might find some of my findings interesting.
Oh I've read the data sheet over and over and there is also a 'tips' pdf.
I see you send 0x90 or 0xD0 as an 8 bit command then read 12 bits in for a result.
This means you are in a mode where the touch chip powers down while CS is high and the int pin is activated even though you don't use it - I've elected to keep mine powered up all the time - that together with my using 8 bit mode gives the different command byte.
You are doing what the C51 code in the supplied (downloaded from sellers site) info' files does. (and why not)
I was thinking that an eight bit result would be plenty big enough for my purposes and when using the 'built in' avr spi hardware, 8 bits at a time is all it will do. Of course I could read two bytes (16 bits) and shift and adjust as required but seemed a bit over the top for my needs.
I send 0x9B or 0xDB as an 8 bit command then read 8 bits in for a result. (in my first post I mistyped 3 for .
Did you know you can interleave these commands and read data? This allows you to get a 12 bit result every 16 bits?
This is only relevent if you want to achieve maximum speed.
example on one axis
send- 10010000 00000000 10010000 00000000 10010000 00000000...........etc
recv- ???????? ?BA98765 43210??? ?BA98765 43210??? ?BA98765...........etc
The data sheet suggests doing multiple reads and averaging the result (as one method) or keep reading until you get a number of reads all the same.
Also, if I read the data sheet correctly, the data you get from the first clock of the twelve you send to receive a result is invalid! I suppose you should actually send 13 and lose the first? Of course this would mean you get a much bigger result (double) - I hope this makes some sense because really I'm thinking aloud - I might be rambling.....
AHA - and maybe that is why you get the result you do!!
PERHAPS for some reason when the screen is not touched that first bit is set and gives a large answer??? I dont know I must do some tests. It certainly doesn't in 8 bit mode.
Since you are satisfied with the way its works for you this is all just mental musing.
Anyway - thanks
Happy hunting
Dave
Hi again
Well I've done some more testing this time sending 0x98 and 0xD8, still using 8 bit mode but with PD1 & PD0 =00 which puts it in 'power down and PENIRQ enabled mode'.(but not using the penirq pin). IT WORKS - with nothing touching the panel I get X=127 and Y=0 reliably! So thats a result! I can move on and do some button pushing.
It seems in portrait mode the touch pad regards the x axis as the vertical axis numbering from 1 at the bottom to 120 at the top and the Y as the horizontal numbering 1 to the left up to 120 at the right. It seems you have asked the display for the x value but assign it to y etc and I will do the same.
Regarding 12 /13 clocks I have been looking at your data sheet (Fig5 page 8) and zooming in to the clock/data signals it really looks as if the first clock after the command returns invalid data - try counting back from the positive clock in the middle of the lsb of the result and you get 13! - so perhaps you are losing the lsbit and in fact the result can give you twice the resolution!
When you get time have a look.
And thanks because without that chance remark about not needing penirq I would have wasted a precoius I/O pin.
Dave
Hi Dave,
Interesting observations! As far as the 12/13 clock, you are probably right. It may explain some of the results I've witnessed. I'm also unsure of the x/y at this time, maybe Dr.A could shed some light on this. Perhaps I will investigate this further after I solve some other issues. Glad to hear you have things working though!
I've spent the majority of my time working on the PASM portion and I'm stumped. I have been able to get fastR2D and fastR2H working but H2R is kickin my butt. Hopefully the guru's can help so I will start another thread in regards to this. My previous code may be faulty so I'm posting my recent efforts.
'--------------------------------------------------------------------------
' setups needed for burst write to display Thanks to Jazzed (Steve Denson)
'--------------------------------------------------------------------------
ds_ctra long 4<<26 | 20 ' NCO mode on P20
ds_frq long $2000_0000 ' phsb accumulates twice per edge
ds_ctrb long 4<<26 | 18 ' NCO mode on P18
fastpasmramtodisplay call #get_values ' get hubaddr,ramaddr,len (only uses len) and set control pins
sub len, #2
add ramaddr, #1
call #set161
or outa,maskP16P20 ' set control pins high
mov latchvalue, dirb
call #set373
and dira,maskP16P31 ' %11111111_11111111_00000000_00000000 so prop pins 0-15 HiZ
andn outa,maskP19 ' CS low
andn outa,maskP16 ' ram /rd low
'ctra setup for burst read
mov phsa, #0 ' init counters phsa P20
mov phsb, #0 ' init to phsb P18
mov frqa, ds_frq ' setup NCO freq P20
mov frqb, ds_frq ' setup NCO freq P18
andn outa,maskP20 ' start counters P20
andn outa,maskP18 ' start counters P18
' P20 Count P18 Write
mov ctrb, ds_ctrb ' enable display clk P18
mov ctra, ds_ctra ' enable address counter clk P20 0 2 4 6 8
fastramtodisplay_loop nop ' 2 4 6 8 10 12 14 0 2 4 6 8
djnz len,#fastramtodisplay_loop ' 10 12 14 0 2 4 6 8
' 2 4 6 8 10 12 14 0
or outa,maskP18 ' stop clock
mov ctrb, #0 ' stop counter 10 12 14 0
mov ctra, #0 ' stop counter 2 4 6 8 10 12 14 0
or outa,maskP20 ' stop clock 2 4 6 8
or outa,maskP19 ' CS high
or outa,maskP16 ' mem /rd high
jmp #done
and
'-----------------------------------------------------------------------
' setups needed for burst read from ram Thanks to Jazzed (Steve Denson)
'-----------------------------------------------------------------------
rd_frqa long $1000_0000
rd_ctra long 4<<26 | 20 ' NCO mode on P20
rd_ctrb long $A<<26| 20 ' Edge Accumulate mode on P20
fastpasmramtohub call #get_values ' get hubaddr,ramaddr,len and set control pins
call #set161
or outa,maskP16P20 ' set control pins high
mov latchvalue,#%11111101 ' group 2, displays all off
call #set373 ' send out to the latch
and dira,maskP16P31 ' %11111111_11111111_00000000_00000000 inputs
andn outa,maskP16 ' memory /rd low
mov phsa, #0 ' init counters phsa
mov frqa, rd_frqa ' setup NCO freq
mov phsb, hubaddr ' save hub ptr to phsb
mov frqb, #2 ' setup EDGE freq
'ctra setup for burst read
or outa,maskP20 ' get clock line?
andn outa,maskP20 ' start counters
mov ctrb, rd_ctrb ' set ctr be mode
rdword data_16,phsb ' sync up only
mov ctra, rd_ctra ' enable address counter clk
fastramtohub_loop ' 10MB/s read loop uses phsb for hub pointer
mov data_16,ina ' get first data 1 2 3 4
wrword data_16,phsb ' move data to hub 5 6 7 8 9 A B C
djnz len,#fastramtohub_loop ' D E F 0
or outa,maskP20 ' stop clock
mov ctra, #0 ' stop counter
mov ctrb, #0 ' stop counter
or outa,maskP16 ' memory /rd high
jmp #done
James, I think I have it! I believe this is the final "tuned" PASM driver. Just replace current code with code below. It's MUCH faster. and seems to work flawless. Please let me know if you find any bugs!
DAT
'' +-------------------------------------------------------------------------------------------------------+
'' | Touchblade 161 Ram Driver (with grateful acknowlegements to Cluso, Jazzed, Kuroneko, and Average Joe) |
'' +-------------------------------------------------------------------------------------------------------+
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)
init 'set up latches here
or outa,maskP22 ' pin 22 high
or dira,maskP22 ' and now set as an output
mov dirb, #%11111111 'set latch All hi
' Initialise hardware tristates everything and read/write set the pins
done mov err, #0 ' reset err=false=good
mov latchvalue, dirb ' restore latch value
call #set373
and dira,maskP0P20low ' tristates all the common pins, leaves P22 as is though
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, #"S" wz ' hub to ram ''S
if_z jmp #fastpasmhubtoram
cmp cmd, #"T" wz ' ram to hub ''T
if_z jmp #fastpasmramtohub
cmp cmd, #"U" wz ' ram to display ''U
if_z jmp #fastpasmramtodisplay
cmp cmd, #"V" wz ' hub to display ''V
if_z jmp #pasmhubtodisplay
cmp cmd, #"E" wz ' convert 3 byte .raw format to 2 byte .ili format - hub to hub ''E
if_z jmp #rawtoiliformat
cmp cmd, #"F" wz ' convert 3 byte .bmp format BGR to 2 byte ili format (same as E but order reversed) ''F
if_z jmp #bmptoiliformat
cmp cmd, #"X" wz ' merge icon and background based on a mask ''X
if_z jmp #mergeicons
cmp cmd, #"Z" wz ' set the 161 counters ''Z
if_z jmp #extset161
cmp cmd, #"M" wz ' pass current latch value to pasm ''M
if_z jmp #latch373value
cmp cmd, #"I" wz ' init ''I
if_z jmp #init
mov err, cmd ' error = cmd (unknown command)
jmp #done
' ----------------- common routines -------------------------------------
get_values rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
mov dirb,latchvalue ' make copy of latchvalue here for restore
or outa,maskP16P20 ' set control pins high
or dira,maskP16P20 ' set control pins P16-P20 as outputs
get_values_ret ret
set373 or outa,maskP22 ' pin 22 high
or dira,#%1_11111111 ' enable pins 0-7 and 8 as outputs
and outa,maskP0P8low ' P0-P8 low
or outa,latchvalue ' send out the data
or outa,maskP8 ' P8 high, clocks out data
andn outa,maskP22 ' pin 22 low
set373_ret ret
set161 mov latchvalue,#%11111110 ' group 1, displays all off
call #set373 ' send out to the latch
and outa,maskP0P20low '%11111111_11100000_00000000_00000000
or dira,maskP0P20 '%00000000_00011111_11111111_11111111
or outa,ramaddr ' send out ramaddr
or outa,maskP20 ' clock high
or outa,maskP19 ' load high
set161_ret ret
' command T
fastpasmramtohub call #get_values ' get hubaddr,ramaddr,len and set control pins
call #set161 '
or outa,maskP16P20 ' set control pins high
mov latchvalue,#%11111101 ' group 2, displays all off
call #set373 ' send out to the latch
and dira,maskP16P31 ' %11111111_11111111_00000000_00000000 inputs
andn outa,maskP16 ' memory /rd low
'ctr setup for burst read
mov phsa, #0 ' init counters phsa
mov frqa, rd_frqa ' setup NCO freq
mov phsb, hubaddr ' save hub ptr to phsb
mov frqb, #2 ' setup EDGE freq
andn outa,maskP20 ' start counters
mov ctrb, rd_ctrb ' set ctr be mode
rdword data_16,phsb ' sync up only
mov ctra, _ctra ' enable address counter clk
' 10MB/s read loop uses phsb for hub pointer
fastramtohub_loop mov data_16,ina ' get first data
wrword data_16,phsb ' move data to hub
djnz len,#fastramtohub_loop
or outa,maskP20 ' stop clock
mov ctra, #0 ' stop counter
mov ctrb, #0 ' stop counter
or outa,maskP16 ' memory /rd high
jmp #done
' command U
fastpasmramtodisplay call #get_values ' get hubaddr,ramaddr,len (only uses len) and set control pins
sub len, #2 ' offset 1 extra clock at start and 1 at end
add ramaddr, #1 ' ???not sure???
call #set161 ' Set start address
or outa,maskP16P20 ' set control pins high
mov latchvalue, dirb ' restore latchvalue saved at get_values
call #set373 ' and set
and dira,maskP16P31 ' %11111111_11111111_00000000_00000000 so prop pins 0-15 HiZ
andn outa,maskP19 ' CS low
andn outa,maskP16 ' ram /rd low
'ctr setup for burst read
mov phsa, #0 ' init counters phsa P20
mov phsb, #0 ' init counters phsb P18
mov frqa, ds_frq ' setup NCO freq P20
mov frqb, ds_frq ' setup NCO freq P18
andn outa,maskP20 ' start counters P20
andn outa,maskP18 ' start counters P18
mov ctrb, ds_ctrb ' enable display clk P18
mov ctra, _ctra ' enable address counter clk P20
' 20MB/s read loop uses ctra for address clock and ctrb for display clock
fastramtodisplay_loop nop ' idle
djnz len,#fastramtodisplay_loop '
or outa,maskP18 ' stop clock
mov ctrb, #0 ' stop counter
mov ctra, #0 ' stop counter
or outa,maskP20 ' stop clock
or outa,maskP19 ' CS high
or outa,maskP16 ' mem /rd high
jmp #done
' command S
fastpasmhubtoram call #get_values ' get hubaddr,ramaddr,len and set control pins
sub ramaddr,#1 '??????
call #set161
or outa,maskP16P20 ' set control pins high
mov latchvalue,#%11111101 ' group 2, displays all off
call #set373 ' send out to the latch
'ctr setup for burst read
mov phsa, wr_phsa ' init counters phsa
mov frqa, wr_frqa ' setup NCO freq
andn outa,maskP20 ' start counters
rdword data_16,hubaddr ' sync up only
mov ctra, _ctra ' enable address counter clk
' 5MB/s write loop uses ctra for address clock
fasthubtoram_loop and outa,maskP16P31 '%11111111_11111111_00000000_00000000 clear for output
rdword data_16,hubaddr ' get the word from hub
or outa,data_16 ' send out the byte to P0-P15
andn outa,maskP17 ' set mem write low
add hubaddr,#2 ' increment by 2 bytes = 1 word. Put this here for small delay while writes
or outa,maskP17 ' mem write high
djnz len,#fasthubtoram_loop ' loop this many times
or outa,maskP20 ' stop clock '
mov ctra, #0 ' stop counter
jmp #done ' tristate pins and listen for commands
' command V
pasmhubtodisplay call #get_values ' get hubaddr,ramaddr,len and set control pins high
andn outa,maskP19 ' CS low
or dira,maskP0P15 '%00000000_00000000_11111111_11111111
hubtodisplay_loop and outa,maskP16P31 ' %11111111_11111111_00000000_00000000 ' clear for output
rdword data_16,hubaddr ' get the word from hub
or outa,data_16 ' send out the byte to P0-P15
andn outa,maskP18 ' ILI write low
or outa,maskP18 ' ILI write high
add hubaddr,#2 ' one word
djnz len,#hubtodisplay_loop
or outa,maskP19 ' CS high
jmp #done
'command E
RawtoILIformat ' takes a .raw 3 byte RRRRRRRR GGGGGGGG BBBBBBBB and converts to 2 byte RRRRRGGG GGGBBBBB
' pass hubaddr, ramaddr and len
' hubaddr is source location, len is number of pixels
' ramaddr is destination in hub (messy naming) and length is 2/3 of blocklength
call #get_values ' gets hubaddress, ramaddress and len (ignores ramaddress)
rawloop
rdbyte red,hubaddr
add hubaddr,#1
rdbyte green,hubaddr
add hubaddr,#1
rdbyte blue,hubaddr
add hubaddr,#1
call #rgbtoili
wrbyte ililow,ramaddr
add ramaddr,#1
wrbyte ilihigh,ramaddr
add ramaddr,#1
djnz len,#rawloop ' loop until done
jmp #done ' set pins to tristate
RGBtoILI ' pass red,green, blue, returns ililow and ilihigh
shr red,#3 ' 000RRRRR
shl red,#3 ' RRRRR000
shr green,#2 ' 00GGGGGG
mov ilihigh,green ' ilihigh = 00GGGGGG
shr ilihigh,#3 ' ilihigh = 00000GGG
or ilihigh,red ' ilihigh = RRRRRGGG
and green,#%00000111 ' 00000GGG
shl green,#5 ' GGG00000
mov ililow,green ' ililow = GGG00000
shr blue,#3 ' blue = 000BBBBB
or ililow,blue ' ililow = GGGBBBBB
RGBtoILI_ret ret
BMPtoILIformat ' takes a .bmp 3 byte BBBBBBBB GGGGGGGG RRRRRRRR and converts to 2 byte RRRRRGGG GGGBBBBB
' same as E above but BGR instead of RGB
' pass hubaddr, ramaddr and len
' hubaddr is source location, len is number of pixels
' ramaddr is destination in hub (messy naming) and length is 2/3 of blocklength
call #get_values ' gets hubaddress, ramaddress and len (ignores ramaddress)
bmploop
rdbyte blue,hubaddr
add hubaddr,#1
rdbyte green,hubaddr
add hubaddr,#1
rdbyte red,hubaddr
add hubaddr,#1
call #rgbtoili
wrbyte ililow,ramaddr
add ramaddr,#1
wrbyte ilihigh,ramaddr
add ramaddr,#1
djnz len,#bmploop ' loop until done
jmp #done ' set pins to tristate
' **** command X *********************
MergeIcons call #get_values ' gets hubaddress, ramaddress,len which are used here as background,icon,mask
mov pasm_n,#59 ' do a single row
mergeiconsloop rdbyte ililow,len ' reuse ililow, so this is rdword mask,maskcounter
and ililow,#%11111 ' mask off low 5 bits and use just the blue as this is a grayscale bitmap
rdword red,hubaddr ' reuse red, so actually this is rdword background,backgroundcounter
cmp ililow,#%10000 wc ' compare if >128 (ie mid level gray)
if_c jmp #mergeskip
rdword green,ramaddr ' reuse green, so this is rdword iconpixel, iconpixelcounter
wrword green,hubaddr ' if replace, then move icon pixel to the background
mergeskip add hubaddr,#2
add ramaddr,#2
add len,#2
djnz pasm_n,#mergeiconsloop ' loop until done
jmp #done 'set pins to tristate
'' *** command Z **********
'changes the latch so displays won't work unless resend the spin value for the latch
extset161 call #get_values ' gets ramaddr = the 161 value to set
mov dirb, latchvalue
call #set161
jmp #done ' tristates pins etc
' *** command M - pass current latch value and send out
latch373value call #get_values
mov dirb,hubaddr
jmp #done
stop jmp #stop ' for debugging
'delaynop nop
' nop
' nop
' nop
'delaynop_ret ret
' variables
pasm_n long 0 ' general purpose value
data_16 long 0 ' general purpose value
ililow long 0 ' low data byte
ilihigh long 0 ' high data byte
red long 0 ' red, green blue variables
green long 0
blue long 0
' constants
Zero long %00000000_00000000_00000000_00000000 ' used in several places
'maskP0P2low long %11111111_11111111_11111111_11111000 ' P0-P2 low
maskP0P20 long %00000000_00011111_11111111_11111111 ' P0-P18 enabled for output plus P19,P20
maskP0P18low long %11111111_11111000_00000000_00000000 ' P0-P18 low
maskP16 long %00000000_00000001_00000000_00000000 ' pin 16
maskP17 long %00000000_00000010_00000000_00000000 ' pin 17
maskP18 long %00000000_00000100_00000000_00000000 ' pin 18
maskP19 long %00000000_00001000_00000000_00000000 ' pin 19
maskP20 long %00000000_00010000_00000000_00000000 ' pin 20
maskP22 long %00000000_01000000_00000000_00000000 ' pin 22
maskP16P31 long %11111111_11111111_00000000_00000000 ' pin 16 to pin 31
maskP0P15 long %00000000_00000000_11111111_11111111 ' for masking words
maskP16P20 long %00000000_00011111_00000000_00000000
maskP0P20low long %11111111_11100000_00000000_00000000 ' for returning all group pins HiZ
maskP0P8low long %11111111_11111111_11111111_00000000 ' P0-P7 low
maskP8 long %00000000_00000000_00000001_00000000 ' pin 8
latchvalue long %00000000_00000000_00000000_00000000 ' current 373 value
'--------------------------------------------------------------------------
' setups needed for burst read/write Thanks to Jazzed (Steve Denson)
'--------------------------------------------------------------------------
_ctra long 4<<26 | 20 ' NCO mode on P20
ds_frq long $2000_0000 ' 10 MHZ
ds_ctrb long 4<<26 | 18 ' NCO mode on P18
rd_frqa long $1000_0000 ' 5 MHZ
rd_ctrb long $A<<26| 20 ' Edge Accumulate mode on P20
wr_phsa long $8800_0000 ' phsa offset for adjusting clock start
wr_frqa long $0800_0000 ' 2.5 MHZ
Ok, we have both been writing code for the last week and now we need to reunify the code.
Attached is my current package of .spin files. In particular, I modified the stringcompare routine so that it returns 0 if equal, and negative or positive values if the strings are more or less than each other. I needed that for a bubblesort routine. But it broke the desktop.spin program (that displays the icons). There might be some other tweaks to the touch.spin program, but it will all be the spin part, not the pasm part. So you have been working on the pasm so hopefully it is not to hard to re-merge things.
Can you take a look at my code and double check it runs on your board, then let me know if I just drop your pasm bit into the code?
I'm not sure about the touch variables you have been discussing. A lot of it was trial and error with swapping x and y with the orientation. I'm still not sure of the best solution. I have a vague idea about a board with a little mercury/ball bearing tilt sensor and you tilt the board and it changes the orientation. If you did that, you want x and y to swap. Or do you? All the icons get rotated 90 degrees too. Or would you ever use such a tilt sensor?
You have found some other bugs - can you list them wrt that aug25 zip?
In an ideal world hopefully the touch.spin program becomes fairly stable and then who cares if you/we alter other apps, but we obviously need to work very closely on that common .spin program. And the desktop.spin as well.
The speed increases are due to using counters to generate the clocks, as well as hubaddr for burst read. This reduces the loops by 1 hub cycle per rep. Also tweaked hub2display for a "tight" timing cycle. There is a bit more overhead but since most transfers are more than one word, it turns out faster. Removing the "maskToWord" from hub2display allows it to complete in 2 hub slots *32 clocks* instead of 3. Hub2ram is reduced by 2 instructions, allowing it to complete in 2 hub slots as well. Ram2Hub is reduced by several clock cycles to fit into 1 hub slot instead of *I think it was* 2. Ram2Display is the fastest since there is no hub slots used so it completes in 8 clock cycles! See loops below
fastramtohub_loop mov data_16,ina ' get first data
wrword data_16,phsb ' move data to hub, phsb is ptr to hub address
djnz len,#fastramtohub_loop
fastramtodisplay_loop nop ' idle
djnz len,#fastramtodisplay_loop '
fasthubtoram_loop and outa,maskP16P31 '%11111111_11111111_00000000_00000000 clear for output
rdword data_16,hubaddr ' get the word from hub
or outa,data_16 ' send out the byte to P0-P15
andn outa,maskP17 ' set mem write low
add hubaddr,#2 ' increment by 2 bytes = 1 word. Put this here for small delay while writes
or outa,maskP17 ' mem write high
djnz len,#fasthubtoram_loop ' loop this many times
Boy those counters are handy!
Hopefully the PASM will "just work." I'll double check your latest code in a bit, as well as test the updated PASM in it.
Re: tilt sensor. This could be interesting but I see some inherent issues with it. First, I believe we would need 2 files for background images *or any image with one axis resolution over 240px.* Also, in my experience with my Android, I just find it annoying. Better to provide an option to change orientation through user interaction IMO.
Re: x/y. I'm not sure of the best way of handling this either. I will keep thinking about this too.
I think the "bugs" I mentioned were more "user error" than anything else. If I find any I will let you know.
The BMPs I was missing are the ones for HTML and Signal Generator.
*edit*
Just found out the PASM is not compatible. I'll figure out why and get back to you.
You are onto something clever with those counters. Ok, take my code, drop in the one line that changes the display settings in the desktop.spin program and hopefully you can copy and paste the new pasm.
Oh darn, I remember I did change the pasm. I stuck the
call #get_values ' get hubaddr,ramaddr,len and set control pins
at the beginning as I noticed that it was called by every routine anyway. Sorry. I might have changed other bits too. Might have been one of those intense alcohol/caffeine fueled coding sessions. Why are those the most productive??!
re missing .bmp files, hopefully it prints the missing filename on the screen - can you give me the names of the missing files?
We both probably need to have version numbers of these files and spend more time documenting changes than making changes. Not quite the way I tend to code but with collaborative efforts I guess that is the only solution...
I figured out the problem with the new PASM. It has to do with setting the latch value. I need to think about the best way to handle the latch value. To me, it seems best left to the program running to keep track of *?and possibly store in SRAM when swapping programs?* My only issue with the "A/O" is *I THINK* it requires more work to set the latch value. *2 PASM calls in some cases* That plus starting a new program will wipe the latch value anyway. I could be wrong though.
*edit*
OKAY, digging deeper and it's going to require quite a bit of modification one way or another. I've made some hefty changes to the PASM driver, and that requires changes to the SPIN portion. This could get complicated....
Spent time working on the Touch.spin and I have things working. Lots of changes here, I tried to note most of them. I will elaborate a bit.
First and least important, these commands were changed to reduce number of jumps *by 1*
PUB HubToRam(RamAddress,Number) ' send pixels from rambuffer hub to ram
CogCmd("S",@rambuffer,RamAddress,Number)
PUB RamToHub(RamAddress,Number) ' send pixels from ram to hub at rambuffer
CogCmd("T",@rambuffer,Ramaddress, number)
PUB RamToDisplay(RamAddress,Number) ' send pixels from ram to display
CogCmd("U",0,Ramaddress,Number) ' pasm alternative to code below, much faster
Also, removed
'Latch_AllHighStart ' all Latch pins high and enables pin 22, ''done by cog init
Since this is now done by cogInit.
Then, changed all Spin code containing DIRAs to clear bit23 *p22* since P22 is only controlled by cog.
PUB SelectMemGroup ' select group 1 for memory transfer
spi.stop ' and stop any other cogs here too if needed
LatchGroup2
DIRA |= %00000000_01011111_11111111_11111111 ' enable these pins for output ''P22 controlled by cog
OUTA |= %00000000_00011111_00000000_00000000 ' set /rd /wr /disp wr and 161 clock high
PUB SelectSPIGroup
LatchGroup3 ' select group 2 for spi transfers
DIRA &= %11111111_10111111_11111111_11000000 ' so no clashes with the cog using P0-P2 set these as inputs and P3-P5 ''P22 controlled by cog
TouchStart ' start the touchscreen cog
Then changed SpinRamToDisplay, this is where things get interesting.
PRI SpinRamToHub(hubaddress,ramaddress,number) ' move data from ram to hub
CogCmd("T",hubaddress,ramaddress,number) ' pasm block move
not
PRI SpinRamToDisplay(ramaddress,number) ' ramaddress, number of words (pixels), display = 1 or 2
Load161(ramaddress) ' load the 161 counters
LatchGroup2 ' group 2 is block data transfers
DisplayEnable ' latch output one or both displays
CogCmd("U",0,0,number) ' pasm alternative to code below, much faster
The reductions here are pushing the ramaddress into the CogCmd. Group changes auto by cog. Display enable is not needed since cog backs up/ restores latch value automatically. Set and forget until changing display.
Changes to CogCmd are fairly simple, remove bit 23 *p22* from DIR command, and restore outa BEFORE dira:
..
DIRA &= %11111111_10100000_00000000_00000000 ' tristate all common pins that cog can change so no conflicts
..
..
outa := b
dira := a ' restore dira and outa ''restore dirb last
Now the big changes... The PASM driver,...First off, at end of loops, jump to "done", not "init," init is used to enable P22 and set latch all high. Also, get_values saves current latch value into dirb for restore @ done, or ramToDisplay. Not needed for hubToDisplay since latch value never changes. Changing latches is done to dirb instead of latchvalue, then jump to done which updates the contents of the latch from dirb.
init 'set up latches here ''only call init on start, all loops return to done JH
or outa,maskP22 ' pin 22 high
or dira,maskP22 ' and now set P22 as an output
mov dirb, #%11111111 ' set latch All hi
' Initialise hardware tristates everything and read/write set the pins
done mov err, #0 ' reset err=false=good
mov latchvalue, dirb ' restore latch value
call #set373 ' and update latch
and dira,maskP0P20low ' tristates all the common pins, leaves P22 as is though
wrlong err, errptr ' status =0=false=good, else error x
wrlong zero, comptr ' command =0 (done)
get_values rdlong hubaddr, hubptr ' get hub address
rdlong ramaddr, ramptr ' get ram address
rdlong len, lenptr ' get length
mov err, #5 ' err=5
mov dirb,latchvalue ' make copy of latchvalue here for restore ''All changes to latch value applied to dirb
or outa,maskP16P20 ' set control pins high
or dira,maskP16P20 ' set control pins P16-P20 as outputs
get_values_ret ret
set373 or outa,maskP22 ' pin 22 high
'or dira,maskP22 ' and now set as an output 'P22 always controlled by cog
or dira,#%1_11111111 ' enable pins 0-7 and 8 as outputs
'andn outa,maskP8 ' P8 low
and outa,maskP0P8low ' P0-P8 low ''P8 is made low at the same time as P0-P7
or outa,latchvalue ' send out the data
or outa,maskP8 ' P8 high, clocks out data
'andn outa,maskP8 ' P8 low ''P8 low not needed
andn outa,maskP22 ' pin 22 low
set373_ret ret
set161 mov latchvalue,#%11111110 ' group 1, displays all off
call #set373 ' send out to the latch
and outa,maskP0P20low '%11111111_11100000_00000000_00000000
or dira,maskP0P20 '%00000000_00011111_11111111_11111111
or outa,ramaddr ' send out ramaddr
or outa,maskP20 ' P20 clock high
or outa,maskP19 ' p19 load high
'andn outa,maskP20 ' clock low ''Not needed since
'andn outa,maskP19 ' load low
'or outa,maskP20 ' clock high
'or outa,maskP19 ' load high
or outa,maskP16P20 ' P16-P20 high in case the next thing is a group change and P16/P17 are low and hence upset the ram chip
set161_ret ret
' *** command O - logical OR hubaddr with latchvalue and send out (set desired bits) ***
latch373_OR or dirb,hubaddr ''Makes changes to dirb
'call #set373 '' Changes retored on call to done
jmp #done
' *** command A - logical AND hubaddr with latchvalue and send out (clear desired bits) ***
latch373_AND and dirb,hubaddr ''Makes changes to dirb
'call #set373 '' Changes retored on call to done
jmp #done
This covers most of the changes. I removed some instructions here and there since they were not needed.
*edit*
I've been attempting to test the driver and there's something interesting going on. I can't quite put my finger on it yet, but it seems "BeginProgram" does not work? If I change to BeginDesktop("S"), everything seems to work. I've also missed a few optimizations unifying the driver so it's a bit slower than my previous version. *About 1/2 second for photo app.* Not sure what exactly is going on with BeginProgram...
*more edit*
RGBtoWord(255,255,255) causes program to crash?
The ILI9325 is well supported I believe, and at that price (£10 in UK money, not sure what the $ cost is) I'm ordering a couple. Pin out not clear but it looks like it might have 2 latch chips to drive 16bit interface from 8 data lines? Seems to need 5V (backlight?) but IO is 3V3.
Interesting! I have not seen these exact display modules. The ILI9325 seems to be a nice display and have a better viewing angle than the SSD1289s I'm using. Not sure about the latch chips but you are probably correct. At a cost of about $13, they are similarly priced with the ILI9325 Dr.A is using. The I/Os are 3v3 and backlight will be 5v. They will likely require 5v supply for display as the modules we use have 3v3 regulators on them. I'm assuming the modules you referenced are the same.
A word of caution. You CAN connect the propeller chip directly to the display. Display draws will be SLOW if not using the external memory. I started out using my display connected directly to the propeller. Performance is less than ideal with full display draws taking several seconds.
I've been very busy this week, as I have family in town. The production board is ALMOST completely built and I should have the video done next week. As a side note, I just sold a fully assembled Touchburger!
I've been playing around with writing Pacman for this display using tile driver code. I'm also experimenting with a programming technique where you write and debug more quickly using a GUI on the PC and try to use routines with similar names so translating over to spin is quicker and easier. So, this is the propeller code, with a very strange alphanumeric description of the layout. It is a convenient way to work because it is easy to edit. Nothing is moving yet - this is just drawing the display. However, that byte array also is a useful descriptor for the code, as the pacman can use the ascii letters to work out where walls are, and the ghosts can work out where pacman is.
CON
_clkmode = xtal1 + pll16x ' use crystal x 16
_xinfreq = 5_000_000
OBJ
tch: "Touch" ' touchscreen driver
PUB Main | touchtest ' debug value
tch.BeginProgram
Pacman
repeat
tch.SetWarmBoot ' clears screen, sets a warm boot and reboots
PUB Pacman | address
tch.Clearscreen(%00000000_00000000) ' so something happens immediately
tch.ClearRam
tch.SDBMPtoRam(string("pactiles.bmp")) ' file 2. File is a .bmp image but each 6x6 tile is continous for fast output
tch.SDBMPtoRam(string("pacbut.bmp")) ' file 3 - control buttons
tch.DrawBMPRam(3,70,215) ' draw the control buttons
PacText(string("PACMAN"),0,300)
DrawMaze
PUB DrawTile(n,x,y) ' draw tile n in location x,y
tch.draw(x,y,x+5,y+5)
tch.ramtodisplay(tch.getramlocation(2)+$36+(n*36),36) ' $36 is the bitmap header offset, 36 is number of pixels to draw
PUB PacText(stringptr,x,y) ' the tiles also include text but only capitals. Happens to be stored at position 65 up (though numbers are not in the ascii position)
repeat strsize(stringptr)
DrawTile(byte[stringptr++],x,y)
x += 6
PUB DrawMaze | x,y,address,c
repeat y from 0 to 30
repeat x from 0 to 39
c := byte[@maze][40*y+x]
case c
32..120:address := 143 + c ' walls of the maze
126: address := 16 ' ~ is small food
125: address := 20 ' } is large food
121: address := 32 * 14 + 24 ' y is part of pacman
122: address := 32 * 14 + 25 ' part of pacman
123: address := 32 * 15 + 24 ' part of pacman
124: address := 32 * 15 + 25 ' part of pacman
drawtile(address,x*6,y*6)
DAT
Maze byte "BKKKKKKKKKKKKKKKKKKlkKKKKKKKKKKKKKKKKKKA"
byte "D~~~~~~~~~~~~~~~~~~ZY~~~~~~~~~~~~~~~~~~C"
byte "D~XPPPPPW~XPPPPPPW~ZY~XPPPPPPW~XPPPPPW~C"
byte "D}ZwwwwwY~ZwwwwwwY~ZY~ZwwwwwwY~ZwwwwwY}C"
byte "D~\VVVVV[~\VVVVVV[~\[~\VVVVVV[~\VVVVV[~C"
byte "D~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C"
byte "D~XPPPPPW~XW~XPPPPPPPPPPPPW~XW~XPPPPPW~C"
byte "D~\VVVVV[~ZY~\VVVVVWXVVVVV[~ZY~\VVVVV[~C"
byte "D~~~~~~~~~ZY~~~~~~~ZY~~~~~~~ZY~~~~~~~~~C"
byte "HPPPPPPPW~ZePPPPPW~ZY~XPPPPPfY~XPPPPPPPG"
byte "nwwwwwwwY~ZcVVVVV[~\[~\VVVVVdY~Zwwwwwwwm"
byte "nwwwwwwwY~ZY~~~~~~~~~~~~~~~~ZY~Zwwwwwwwm"
byte "VVVVVVVV[~\[~^MMMMb??aMMMM]~\[~\VVVVVVVV"
byte "~~~~~~~~~~~~~C!",34,"w'(w-.w34wD~~~~~~~~~~~~~"
byte "PPPPPPPPW~XW~C#$w)*w/0w56wD~XW~XPPPPPPPP"
byte "DwwwwwwwY~ZY~C%&w+,w12w78wD~ZY~ZwwwwwwwC"
byte "DwyzwwwwY~ZY~`KKKKKKKKKKKK_~ZY~ZwwwwwwwC"
byte "Dw{|wwwwY~ZY~~~~~~~~~~~~~~~~ZY~ZwwwwwwwC"
byte "DwwwwwwwY~ZY~XPPPPPPPPPPPPW~ZY~ZwwwwwwwC"
byte "JVVVVVVV[~\[~\VVVVVWXVVVVV[~\[~\VVVVVVVI"
byte "D~~~~~~~~~~~~~~~~~~ZY~~~~~~~~~~~~~~~~~~C"
byte "D~XPPPW~XPPPPPPPPW~ZY~XPPPPPPPPW~XPPPW~C"
byte "D~\VVWY~\VVVVVVVV[~\[~\VVVVVVVV[~ZXVV[~C"
byte "D}~~~ZY~~~~~~~~~~~~~~~~~~~~~~~~~~ZY~~~}C"
byte "HPPW~ZY~XW~XPPPPPPPPPPPPPPPPW~XW~ZY~XPPG"
byte "JVV[~\[~ZY~\VVVVVVVWXVVVVVVV[~ZY~\[~\VVI"
byte "D~~~~~~~ZY~~~~~~~~~ZY~~~~~~~~~ZY~~~~~~~C"
byte "D~XPPPPPfePPPPPPPW~ZY~XPPPPPPPfePPPPPW~C"
byte "D~\VVVVVVVVVVVVVV[~\[~\VVVVVVVVVVVVVV[~C"
byte "D~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C"
byte "FMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMME"
So this started life as vb.net code and was/is being debugged in vb.net
Public Class Form1
Dim Pixelarray(192 * 144) As Color ' array with all the tiles, each 6x6
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
CreateArray()
MazeLayout()
End Sub
Private Sub CreateArray()
Dim MyBitmap As New System.Drawing.Bitmap(PictureBox1.BackgroundImage) 'image from picture box
Dim i, x, y, sizex, sizey, tilex, tiley, startx, starty, finx, finy, width, height As Integer
Dim Mycolor As Color
sizex = 192
sizey = 144
width = 6
height = 6
i = 0
For tiley = 0 To (sizey / width) - 1
For tilex = 0 To (sizex / height) - 1
startx = tilex * width
finx = tilex * width + (width - 1)
starty = tiley * height
finy = tiley * height + (height - 1)
For y = starty To finy
For x = startx To finx
Mycolor = MyBitmap.GetPixel(x, y) ' get the color
Pixelarray(i) = Mycolor
i += 1
Next
Next
Next
Next
End Sub
Sub DrawTile(ByVal tileN As Integer, ByVal startx As Integer, ByVal starty As Integer)
Dim address As Integer
Dim finx, finy, screenwidth, x, y As Integer
Dim MyBitmap As New System.Drawing.Bitmap(PictureBox3.BackgroundImage)
address = tileN * 36
finx = startx + 5
finy = starty + 5
screenwidth = 240
For y = starty To finy
For x = startx To finx
MyBitmap.SetPixel(x, y, Pixelarray(address))
address += 1
Next
Next
PictureBox3.BackgroundImage = MyBitmap
End Sub
Private Sub MazeLayout()
' describe the maze in letters with A starting at the first maze symbol on the tile map
' B=top left, A=top right, C= right side, D=left side, E=bottom right, F=bottom left
' K= top double, M=bottom double
' f = food
' 40 wide, 53 high
Dim Maze(53) As String
Dim x, y, address, c As Integer
Maze(0) = "BKKKKKKKKKKKKKKKKKKlkKKKKKKKKKKKKKKKKKKA"
Maze(1) = "D~~~~~~~~~~~~~~~~~~ZY~~~~~~~~~~~~~~~~~~C"
Maze(2) = "D~XPPPPPW~XPPPPPPW~ZY~XPPPPPPW~XPPPPPW~C"
Maze(3) = "D}ZwwwwwY~ZwwwwwwY~ZY~ZwwwwwwY~ZwwwwwY}C"
Maze(4) = "D~\VVVVV[~\VVVVVV[~\[~\VVVVVV[~\VVVVV[~C"
Maze(5) = "D~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C"
Maze(6) = "D~XPPPPPW~XW~XPPPPPPPPPPPPW~XW~XPPPPPW~C"
Maze(7) = "D~\VVVVV[~ZY~\VVVVVWXVVVVV[~ZY~\VVVVV[~C"
Maze(8) = "D~~~~~~~~~ZY~~~~~~~ZY~~~~~~~ZY~~~~~~~~~C"
Maze(9) = "HPPPPPPPW~ZePPPPPW~ZY~XPPPPPfY~XPPPPPPPG"
Maze(10) = "nwwwwwwwY~ZcVVVVV[~\[~\VVVVVdY~Zwwwwwwwm"
Maze(11) = "nwwwwwwwY~ZY~~~~~~~~~~~~~~~~ZY~Zwwwwwwwm"
Maze(12) = "VVVVVVVV[~\[~^MMMMb??aMMMM]~\[~\VVVVVVVV"
Maze(13) = "~~~~~~~~~~~~~C!" + Strings.Chr(34) + "w'(w-.w34wD~~~~~~~~~~~~~"
Maze(14) = "PPPPPPPPW~XW~C#$w)*w/0w56wD~XW~XPPPPPPPP"
Maze(15) = "DwwwwwwwY~ZY~C%&w+,w12w78wD~ZY~ZwwwwwwwC"
Maze(16) = "DwyzwwwwY~ZY~`KKKKKKKKKKKK_~ZY~ZwwwwwwwC"
Maze(17) = "Dw{|wwwwY~ZY~~~~~~~~~~~~~~~~ZY~ZwwwwwwwC"
Maze(18) = "DwwwwwwwY~ZY~XPPPPPPPPPPPPW~ZY~ZwwwwwwwC"
Maze(19) = "JVVVVVVV[~\[~\VVVVVWXVVVVV[~\[~\VVVVVVVI"
Maze(20) = "D~~~~~~~~~~~~~~~~~~ZY~~~~~~~~~~~~~~~~~~C"
Maze(21) = "D~XPPPW~XPPPPPPPPW~ZY~XPPPPPPPPW~XPPPW~C"
Maze(22) = "D~\VVWY~\VVVVVVVV[~\[~\VVVVVVVV[~ZXVV[~C"
Maze(23) = "D}~~~ZY~~~~~~~~~~~~~~~~~~~~~~~~~~ZY~~~}C"
Maze(24) = "HPPW~ZY~XW~XPPPPPPPPPPPPPPPPW~XW~ZY~XPPG"
Maze(25) = "JVV[~\[~ZY~\VVVVVVVWXVVVVVVV[~ZY~\[~\VVI"
Maze(26) = "D~~~~~~~ZY~~~~~~~~~ZY~~~~~~~~~ZY~~~~~~~C"
Maze(27) = "D~XPPPPPfePPPPPPPW~ZY~XPPPPPPPfePPPPPW~C"
Maze(28) = "D~\VVVVVVVVVVVVVV[~\[~\VVVVVVVVVVVVVV[~C"
Maze(29) = "D~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C"
Maze(30) = "FMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMME"
For y = 0 To 30
For x = 0 To 39
c = Strings.Asc(Strings.Mid(Maze(y), x + 1, 1))
If c > 32 And c < 121 Then
address = 208 + c - 65
End If
If c = 126 Then ' ~ = small food
address = 16
End If
If c = 125 Then
address = 20 ' } is large food
End If
If c = 121 Then ' y is part of pacman
address = 32 * 14 + 24
End If
If c = 122 Then ' z is part of pacman
address = 32 * 14 + 25
End If
If c = 123 Then ' { is part of pacman
address = 32 * 15 + 24
End If
If c = 124 Then ' | is part of pacman
address = 32 * 15 + 25
End If
DrawTile(address, x * 6, y * 6)
Next
Next
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim MyBitmap As New System.Drawing.Bitmap(PictureBox2.BackgroundImage) ' for export
Dim address As Integer = 0
For y = 0 To 143
For x = 0 To 191
MyBitmap.SetPixel(x, y, Pixelarray(address))
address += 1
Next
Next
PictureBox2.BackgroundImage = MyBitmap
PictureBox2.BackgroundImage.Save("c:\Pactiles.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
End Sub
End Class
The pictures all exist as tiles, and for simplicity the tiles are all 6x6 pixels. So some things like ghosts end up needing 4 tiles. We will also be needing a transparency layer down the track. Take the tile data and work out how all the little curves and straight lines go together. Lots of fun!
For both vb.net and Spin, it is more convenient to convert a two dimensional array to a one dimensional array. That way, tiles can be sent to the display with a single call to a pasm routine, which is less than a microsecond to send out a tile. Hence the rather strange "smeared" bitmap which the spin version uses.
Next step is to start coding the rules for movement. Then pull in the .wav files (many available on the internet for pacman) and the controls.
Very nice work! I completed building the first board and it passed initial testing. I have found something puzzling. When both displays are installed, the desktop will not boot properly. Either display by itself works fine, so I suspect a weak power supply. I'm also wondering if it could be due to 100k resistor networks. Still need to investigate the exact cause. I'll keep you up to date.
Keep up the excellent work and thanks again!
Joe
*edit*
Voltage rails look good and I'm not seeing any transients on the /reset line either. I'm confused as to what the issue is. Need to scavenge some 10k resistor networks from previous boards. Resistor networks *as well as 4 sets of regulators* are on their way from futurlec.
*aedit*
Replaced RN1 and RN6 with 10k. Still rebooting randomly. Really starting to make me wonder.
*more edit*
OKAY, I figured it out! I guess wall-wart selection is more important than I thought. Seems the 12v .9a I have been using doesn't have the amps to push 2 displays? *14.3v out* Tried a 5v 2.5a and it works, although 5v is 4.3 and 3.3v is 3.17-3.23. I'll test some more warts and see what I find!
*final edit*
Power supply issues confirmed. I suspect the buck regs are allowing a very quick voltage drop I'm not able to see on my slow meters. None of the wall-warts I've tried have the guts to push this board. Pulled the rack-mount out and it's supply runs the board just fine @7.5v with a peak observable draw of 175ma?*The supply is fused @750ma. I've tried 6-9v warts from 900ma to 2100ma and the only ones that "work" are "switching" 5v warts. One rated 2.5a, the other rated 2a. They boot and run programs, but I've had the occasional random reboot. I'm guessing the recommended wall-wart should be 6-9v 2A?
Well I've tried a bunch of different stuff and still can't get the dual-display to run stable. Seems to be random rebooting during SD mount.
I tried soldering a .1uf ceramic and 10 uf to the sd card pins. Tried many wall warts. I even tried swapping a 5v linear regulator. I'm really starting to wonder what is going on.
Curious what you're using to power the boards?
*edit*
I just got a VERY interesting result when I removed the MAX chip. It looks like the 3v3 rail is sagging, during sd mount. This is (somehow) causing the MAX to pull a reset. Need to investigate further, but at least I'm getting somewhere...
*aedit*
Okay, removing the MAX2323 solved the "reset bug." As I stated, my meters are too "slow" to really "see" the spike. It seems to be the 3v3, not 5 as I had though. Propplug works just fine *if not better than the MAX3232* so this is a bonus.
After re-installing the 5v buck reg, I tested several wall-warts and they work fine with both displays installed. Not recommending the 5v "switching" supplies as the rails are too weak, seeing 4.37-4.4v and 3.21v.
Tested "working" warts have 4.85v and 3.25-3.27 respectively.
Radioshack 9v 800ma. CAT 273-1770
Panasonic 12v 0.9A Model BAD7001 *my MAIN wart, from NICAD charger.*
Cannon 8.4v 2.0A Model CA-570 *nice and lightweight, voltages seem stable?*
More testing soon!
The whole time I've been wondering the EXACT details of my reset bug. Need to dig through the data-sheets for the SIPEX SP3232ECP. Removing this chip restored stability *even the rackmount PSU started to bug*
I think an SD mount can surge up to 200mA. Still well under the switching reg limit of 1A. My wallwart is 9V 1A and open circuit runs around 13V.
I was going to suggest some bigger caps eg 4700uF on each of the 3V and 5V supplies. It is strange that the display on the 5V supply is upsetting something on the 3V supply.
I've pulled apart my wallwart and it has a 4700uF cap inside. It is possible that different wall warts have smaller caps inside, so maybe worth putting 4700uF across the input instead of the 470uF?
I'm a bit puzzled because after all the testing, removing the SP chip "solved" the issue. I must think about this a bit more, and will experiment a bit. The Panasonic *which is close to your specs* has a large cap, I'd guess 4700-10,000uf can't tell exactly since it's ??wrapped in heat-shrink tubing?? and I'm not interested in cutting it off ATM. A bit of a puzzle, I will try adding more caps to the supply.
It's curious I have this issue and you do not. Perhaps the SP3232 is sensitive in a way the MAX is not? I'm fairly certain the issue involves a "saggy rail," although I'm not happy with 3.25 and 4.85 nominal voltages. IMO should be 3.31v and 5.02v to 3.28v and 4.97v. I've tried a number of warts and none could handle SD mount. I can "see" sag on my meters, but can't estimate "ACTUAL" sag. I'm going to look into the sound-card -scope programs. No substitue for good test equipment, but might help track the issue. The GB "GDT-11" is about as worthless as they come, and my analog meter is not much help either.
*edit*
Well I must have something messed up since Lorem is showing up with a "1" or "3" at the beginning?
*aedit*
About Lorem... It was indicating an error in my driver. I was aware that things were not working correctly and have solved this. Seems I tried optimizing TOO far and broke Set161... The correct version is
set161 mov latchvalue,#%11111110 ' group 1, displays all off
call #set373 ' send out to the latch
and outa,maskP0P20low '%11111111_11100000_00000000_00000000
or dira,maskP0P20 '%00000000_00011111_11111111_11111111
or outa,ramaddr ' send out ramaddr
or outa,maskP20 ' P20 clock high
or outa,maskP19 ' p19 load high
andn outa,maskP20 ' clock low
andn outa,maskP19 ' load low
'or outa,maskP20 ' clock high ''Not needed since
'or outa,maskP19 ' load high
or outa,maskP16P20 ' P16-P20 high in case the next thing is a group change and P16/P17 are low and hence upset the ram chip
set161_ret ret
I went back and re-compiled everything, updated SD and some things work. I think buttons has a glitch, not sure what yet. There's a few other things. Need to check your tile driver. I hope I didn't break that..
Once again, all bugs were on my end... I believe the PASM driver is ALMOST done. There's a bit of room left in the cog, and I've been thinking about what to do with it.
#1. More code. I have an idea that might speed things up a fraction of a MS... Moving all display commands to cog. Fill rambuffer with commands as longs, hi-word command, low-word data. Call PASM driver, which outputs command, data... until reaching command #22, *write gddr*
I've also been thinking about Ram2display and Hub2display. Before calling these commands, we must be in group2, with RS high, and the display(s) selected. Seems best to me if we only be concerned about having the proper display selected and everything else is automatic. This way if we're in group3 and the display is touched, just select the proper display and update. Then return to caller will be in group3, *or 4* just like you left.
#2. I've also been thinking about "stuffing" SPI into cog-driver. This will obviously not work for the cache driver, but could save a cog? Stuffing FATe is not a possibility.
The idea is to improve performance, increase flexibility, and not break anything in the process. I'm still not 100% sure the driver is correct. I still can't account for all of the instructions in the burst-transfers. The propeller's counters and our external 161 counters are dynamite together. Making it work properly is not so easy. I tried to import one portion at a time, checking against the other 2 for reference. The set161 bug might have a "ripple" effect, or that's what I'm afraid of. I'll revive the OTHER post on this issue as maybe one of the guru's can guide me in the right direction.
I'm still wrapping my head around the reset bug. I'll build a few more boards and see if I can find a difference. I still need to document the linear regulator mod. More photos and video will always help. The last build session was in low light and came out with a bit of video-noise. The outside portion was full of glare. A few good clips, but need more footage. I'm attaching the "fixed" touch.spin. Notice change in revision#.
There is much we can do with putting code into cogs - we haven't even started with that but hopefully with more builders others will be able to contribute.
One thing for instance is the Spin "draw" routine that sets up where to draw a picture x,y,sizex,sizey eg - for a 36 pixel tile like in pacman, the time to do the "draw" may well be taking longer than the actual outputting of the bytes.
In one sense I kind of like the idea of handing over code to other builders with 2/3 of the hub free, with most cogs free and with pasm drivers still with spare space. There were some instances a few years back with the 8080 and Z80 drivers where some of the object code came with "one long free".
I haven't had a chance to do any coding for the last few days but hopefully later this week.
I've been thinking about "draw" a bit too. There are many ways of streamlining the draw setup, and I'm not sure of the best way yet. I've been thinking a separate command for displaycmd, in PASM. This would help a bit, I'm sure. Maybe slipping the draw into the first write would be most efficient. Either way, I think it's best to get command transfers working in PASM first.
Re: free hub memory... I've been thinking about this A LOT. Things like the display initialization code could be stored on the SD card to save space. Then there's the problem of what happens when something goes wrong with the SD... Not easy to diagnose. May not be worth the trouble. Other things could be done and, if worse came to worse, builders could remove unused PUBs in touch.spin. Dynamic loading could also save some memory. For instance, if ALL programs expect to be called from desktop, no need for all the initializations in the PROGRAM's touch.spin
The last thing is, thinking about expanding the desktop app. It would be interesting to be able to "add" a program to the desktop without manually editing cvs... Say open keyboard, enter command string and desktop edits CVS? Maybe change name of background file? A file browser/selection would be handy... Many things to do! Many possibilities!
I CERTAINLY want to leave builders enough room to do "useful" stuff. I don't want to "force" them to use the SRAM... And I don't think it will be necessary. A few longs in PASM will be worth the savings in SPIN, in speed and program size, IMO. Draw is the first to "go under the knife" just not sure the best way to implement the command buffer. I'm thinking of allocating 5 longs JUST BEFORE rambuffer to store draw cmds... X,Y,SizeX,SizeY, AND gddrwr... Or maybe 2 calls to PASM driver is better? I'll start writing for seperate calls since it will be the easiest to debug. I have a basic idea, now just need to flesh it out!
Oh and no, reset bug is still "buggin" me. Only 1 board built ATM and MAX circuit was removed. Must save this for another day since it's not "top of stack." The 3 sold boards will be using propPlugs for programming *I think* Still not happy with the Supply rails being as low as they are... Or am I just paranoid??
Not much goes wrong with the SD but Kye's code allows you to print debug error messages to the screen and the code for that is there for things like not finding a .bmp file.
Re adding things to the .csv, well that would be an app that we need to write. Take the keyboard app and display the .csv file in it and then allow the user to scroll up and down and insert text. The text buffer is small so plenty of room in hub to fit that, which makes coding easier.
Re the low supply rails, I'm measuring values a little higher and I did once put all my multimeters on a rail and they all disagreed but 0.1 to 0.3V.
I see on facebook you got your other half to do all the soldering. Wish my wife would learn to solder!
Not much goes wrong with the SD but Kye's code allows you to print debug error messages to the screen and the code for that is there for things like not finding a .bmp file.
Re adding things to the .csv, well that would be an app that we need to write. Take the keyboard app and display the .csv file in it and then allow the user to scroll up and down and insert text. The text buffer is small so plenty of room in hub to fit that, which makes coding easier.
Re the low supply rails, I'm measuring values a little higher and I did once put all my multimeters on a rail and they all disagreed but 0.1 to 0.3V.
I see on facebook you got your other half to do all the soldering. Wish my wife would learn to solder!
I've been thinking about things a bit, and have come up with some ideas...
RE: sd debugging. My thought is pushing the display setups to the SD could save quite a bit of space. This means the sd card needs to mount before the display can be initialized. Perhaps we could have more than 1 version of touch.spin? One contains display inits and all code touch.spin currently has. Desktop will be compiled with this version. A "slim" version could be built for user programs that pulls all display inits from SD card. Or something like that, still need to think on it.
The idea I stated about editing the CVS is one "function" of a larger "desktop settings" program I'm thinking about. Still need to think of all the things necessary to make this work.
I have done some work on display commands in PASM. I started with draw which seems to work. Still need to experiment but the basics *for verification*
PUB Draw(x1, y1, x2, y2) | drcmd[7] ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
' DisplayEnable ' enable one or both displays already in cog!
' SelectMemGroup ' select memory group already in cog!
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
if displaymode == "I" ' ILI9325 display
drcmd[0] := ($0050_0000 + x1)
drcmd[1] := ($0052_0000 + y1)
drcmd[2] := ($0051_0000 + x2)
drcmd[3] := ($0053_0000 + y2)
drcmd[4] := ($0020_0000 + x1)
drcmd[5] := ($0021_0000 + y1)
drcmd[6] := ($0022_0000)
if displaymode == "S" ' SSD1289 display
drcmd[0] := ($0044_0000 + ((x2<<8)+x1))
drcmd[1] := ($0045_0000 + y1)
drcmd[2] := ($0046_0000 + y2)
drcmd[3] := ($004e_0000 + x1)
drcmd[4] := ($004f_0000 + y1)
drcmd[5] := ($0022_0000)
CogCmd("W", @drcmd, 0,0)
..
cmp cmd, #"W" wz ' hub to display command, terminated with gddrwr
if_z jmp #pasm_disp_cmd
..
..
pasm_disp_cmd or dira,maskP0P15 '%00000000_00000000_11111111_11111111
'prepare for command, display(s) selected, /rs low, group2
:loop and latchvalue, #%0111_0000 'isolate display and reset
or latchvalue, #%0000_1101 'group2, /rs low
call #set373 'and set
' and send command to display
andn outa,maskP19 ' CS low
and outa,maskP16P31 '%11111111_11111111_00000000_00000000 ' clear for output
rdlong data_32,hubaddr 'read command/data from hub
mov pasm_n, data_32 'copy to pasm_n
shr pasm_n, #16 'isolate command
or outa,pasm_n ' send out the word to P0-P15
andn outa,maskP18 ' ILI write low
or outa,maskP18 ' ILI write high
or outa,maskP19 ' CS high
'prepare for data, display(s) selectd, /rs high, group2
and latchvalue, #%0111_0000 'isolate display and reset
or latchvalue, #%1000_1101 'group2, /rs high
call #set373 'and set
'and check if wrGDDR was last command
cmp pasm_n, #$22 wz ' is gddwr cmd?
if_z jmp #done ' then finish, otherwise continue
'if not, continue sending data
andn outa,maskP19 ' CS low
and outa,maskP16P31 '%11111111_11111111_00000000_00000000 ' clear for output
and data_32,maskP0P15 ' mask off data word
or outa,data_32 ' send out the word to P0-P15
andn outa,maskP18 ' ILI write low
or outa,maskP18 ' ILI write high
add hubaddr,#4 ' one word
or outa,maskP19 ' CS high
jmp #:loop 'continue until wrGDDR cmd
pasm_disp_cmd_ret ret
This could be optimized a bit and in several ways. I'm thinking of optimizing for speed first...
Still need to work on cache driver. I'll try that later tonight.
I am VERY lucky my better half takes an interest in my hobbies. She soldered together a few of the early boards to help keep things moving. *None of this would be possible without her love and support*
*edit*
I've come up with an idea but wanted to bounce the details off of you. What I've been thinking about is trying to cut as much SPIN as possible. Also simplify the draw command so, instead of the above draw
PUB Draw(x1, y1, x2, y2) | drcmd[7] ' sets the pixel to x1,y1 and then fills the next (x2-x1)*(y2-y1) pixels
' DisplayEnable ' enable one or both displays already in cog!
' SelectMemGroup ' select memory group already in cog!
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
CogCmd("W", @x1, 0,0)
And have the cog setup the proper draw commands. This would require a command to configure the selected display? Or could we do this on INIT?
Re passing multiple parameters to the display cog, one answer could be to use the existing three arrays we have - eg sdbuffer or rambuffer. Then just pass the location of the array in, say, hubaddress and the command letter, and a cog routine can send it out. How much pasm space do we have left in that cog?
Thinking in a generic sense, what you could do is put a whole series of commands in that array and send them out. You could have a simple language for that, maybe it is a bit inefficient but if you have one long and 8 bits are for the data and one bit defines whether it is a command or data, and another bit could define if it is the end of sequence. Then you could store all the startup sequence as a series of longs. And that could be stored as a file on the SD card like you say, and save a pile of hub ram code space.
I've been pondering cache drivers in C. The fundamental problem holding this all back is that both C++ and C89 don't suit this board, because the cache driver and the code both may want to share access to external memory at the same time. I'm not sure how to explain it fully on the C threads - it is our hardware so I think we have to solve it. So - store the program on the SD card and you can't use the SD card. Store it in ram and the code can't use ram. I have an idea that you run Kye's SD driver through the Spin2C program and run it but it is not that simple.
Fundamentally, I'd like to have the C program in external ram rather than on the SD card because it is faster. I see two solutions - one uses two cogs - one running the C cache driver and one running our touchscreen driver. Between those you have a lock and control is handed back and forth between those cogs. An alternative is three cogs where one is the master cog (either running spin or pasm) which handles which cog has control of the system.
It is complicated thinking about the code needed to do a large block transfer from SD out to external ram. Such a block transfer is going to need the C code running in order for the SD code to be running. But if the C code is running, the user does not have access to the ram to do the data transfer. You end up sending the data in 512 byte chunks through hub with multiple resetting of the 161 counters rather than one smooth transfer. And yet Spin can do that transfer in one go. At the deep down fundamental level, XMM C still can't seem to replicate what Spin can do. Maybe it can - I just need to think about it some more. I think the problem is that C that fits just in hub will work, but C is bigger than Spin for given equivalent code so a realistic program won't fit in hub. So you are stuck with putting the C program in some form of external storage and that creates all the problems. Perhaps the answer is to allocate a much bigger SD buffer in hub - maybe 8k or something, and then transfer everything in 8k chunks, thus decreasing the number of swaps back and forth between the display driver and the cache driver.
I guess I have bailed out and gone back to coding everything in Spin. Solve the simple problems first. Certainly putting the draw routine in pasm will speed up pacman and other tile programs, and putting the init code on the SD card as a file will save hub space.
I have been pondering the cache driver quite a bit, and I think the answer is a one cog solution. Cache driver and ram driver in one cog. There should still be room to do this, and it seems all that will be needed is to re-code all the spin in C with appropriate wrappers. I think there is a way to use the existing Spin, but I'm still trying to understand that a bit more.
I should be able to have the "basic" cache driver soon. My previous attempt was foiled due to poor coding of MY touch.spin. I'm fairly sure this is fixed. The only program that highlighted the bug was Lorem. Now things run properly and BeginProgram works again. Sorry about that.
I still need to optimize touch.spin a bit more. I see quite a bit of room for improvement. I would very much like to pass draw commands as an address to a an array of 4 long, x1,x2,y1,y2 and have the cog do the rest... Quite possible, but may take a bit of self-modifying code... Not my strongest suit but it will help improve my skills. I feel the driver may be headed in 2 paths in the future. The one path mentioned previously, where the driver does not include display inits, should be named differently for reference. The other path is best for initial development of programs, containing debug code and display inits. From my point of view, most programs should be expected to run from the desktop. The desktop inits the display so there should be no need for that code in the driver... EXCEPT for initial development where program will most likely be run from unknown state. Not my favorite solution but seems better than using conditional compiles and BST. We don't need to worry about this quite yet, just something to think about.
There's quite a bit to think about, all quite possible... Just several levels of difficulty. Oh, there's 227 longs left in the RAM cog. I'll keep you updated!
PS. please test VER 0.0.8.6, I think it's okay but need a second set of eyes. The cache driver test did not show bug in old code, but when trying to run Hello.c failed. Hopefully I'll have better luck tonight.
Comments
needed to set up Pcounters for burst read, done on init the "overhead" and the transfers It's FAST!
Then I wanted to see if I could tune the hub to display, as it was taking 3 hub-slots to complete... Then I tried to get hub to ram running the burst... and failed. and failed. and failed...
So I moved on to the ram to display... Not much to trim really, just 5 instructions. Well it took forever but I got it down to 2.
One slight problem, seems it doesn't quite work right? I am able to draw backgrounds, but everything else draws garbage? I need to think through it a bit, but if I can get the counter code to work, it will be as fast as the display can draw! Now that I have it partially working, I will take a look at hub to ram. It might help me figure out what I'm doing wrong.
Now, just for my sanity in case I screw something up
Once the boards arrive, are you going to solder one up just to double check it works? If you do, take some photos along the way as that could be useful for a writeup of how to build the board.
The expansion boards are on the way, will be maybe another couple of weeks to get to you.
I'm playing around with some crazy stuff trying to translate vb.net into spin. (and then with ersmith's routine, spin into C).
Rather than work with objects, which spin is not very good at, I'm thinking more in terms of a single database. You put data in and then you request it out again. So a description of a screen like a synthesizer or a button is a list of information.
With a few minor changes, you can send that straight into a database as strings. Maybe lose the "new system.drawing.size" and just store the numbers. Storing strings is easy with the touch.spin object.
Then do a sort on the entire database. Either pre compilation or in code, it does not matter. Then request data out of the database, eg an object name, then the size of the object and that gives you areas of the screen that respond when you touch them.
So two essential things here are a sort algorithm (ideally a quicksort, but since this is only done once, ye olde inefficient bubble sort will do). Then a binary search algorithm to extract the data. So I have this silly little bit of code
And I think we can pull data in and out of that database without having to worry about getting mixed string/number objects working in spin. A database working in just strings, and only in external memory is a very nice thing as you don't have to worry about conserving memory any more. Store all the descriptions of the screen objects long hand like vb.net does and you can always go and extract data later. Plus it demonstrates some of the string routines (thanks Kye!).
I have been following this thread since post 1 and as a result purchased a 3.2" board from egochina and have had hours of 'fun'.
I was thinking along the lines of using counters and ram and then off you went and did it, but I didn't!
First of all I must come clean and admit that I am using an arduino at the moment which means that at a clock of 16 Mhz and ONLY a single processor my computing resources are small in comparison to the mighty prop. (I have a cameleon on the shelf but to my shame its only been used in arduino mode - I also have a raspberry pi in the same place - I just dont have the time to invest in learning new architectures while I am able to play with interesting periferals like this touch screen).
Because of my shortage of pins I have had to use spi and a couple of 574's used as shift registers to provide the 16 data pins, so where you are getting 30 frames a second I get 1/2. But thats ok because for my needs thats PLENTY fast enough, and I am able to display bitmaps recalculated for the 5-6-5 screen colour format, and fonts - I have used the DOS font 8 bit by 16, ie 16 bytes per character, and saved as an array, and by having global backgroung forground colours use these when reading the on/off bits that make up the character as I write/overwrite the display .
Now to my question - it regards the relatively trivial task of reading the touch screen position. My code works, and if I hadn't read your post that when the screen is not touched the reading gives co-ordinates off screen, and therefore using the interrupt pin is not required, I wouldn't be bothering you now.
Well I dont get the same results and it is a REAL PAIN; I get a no touch reading of somewhere in the middle of the screen!
So I wonder if you could share the code/method you use to read the touch position.
I use 8 bit mode; so I set CS low, and (for x axis) send 0x93 (0xD3 for 'Y' axis) and ignore the return byte, then I send 0x00 and use the returned byte as my result. I know that I am wasting the lsbit but I still get results of 1 - 110 on both X and Y axis. This I do 32 times for each axis and average the result (>>5).
I have not put a pullup resistor on the int pin (since I'm not using it) and maybe doing this gives a no touch bias to offscreen - I dont know, I havent had the energy to try.
Perhaps you are doing it differently; I would really like to know.
If you could summarise the way you have connected yours and the mode and algorythm you use I would be grateful.
By the way - just as a matter of interest - The arduino is 5v and the display is 3 volt - and all I do is put a 22K resistor in series in the data and control lines and so far the screen hasn't complained - I guess the protection diodes in the display are doing their stuff.
In My opinion threads like this are like gold and are required daily reading.
Thanks
Dave
Not much time but hopefully this will help.
The shiftout is Data, Clock MSBFIRST, 8bits. The shiftin is Data, Clock, MSBPost, 12bits..
I'll be around later to try and clarify
Joe
*edit*
I've had some more time to re-read the post and I'm not entirely sure of your communication algorithm. I will see if I can track down the C code for the touchscreen.
The INT pin is not needed and left unconnected on our board.
Now in my experience, *and this may or may not apply toward your issue* if there is "gunk" on the display it can register a false touch. There is also the issue of the first read from the touchscreen returning incorrectly occasionally. To me it sounds as if the 8bit SPI mode may or may not be an issue.
Now, we are sending "D0" for touchX and "90" for touchY. The ADS7843 touchscreen controller datasheet is here : http://www.ti.com/lit/ds/symlink/ads7843.pdf
No time to double check right now but RTFM may help!
If you have the display, then you may be interested in our board. It's VERY nice and quite a bit faster than 30fps. A full screen draw from RAM file is well under 30ms. Calculating ACTUAL fps depends on the number of FILES drawn from ram * Size of draw, plus spin overhead to setup the draw, ect. I will be taking video soon, but all I can say is Propeller+161addressed SRAM is "The Way To Go!" Well worth the $55 for components.
BTW: If you are interested in JUST the board, I would send you one if you pay shipping. Also able to arrange Full/Partial kits. PM for details
Re Cache driver: I'm still trying to figure things out, need to take a break for a couple days. It should be quite possible to integrate the cache driver with the PASM driver. There should be plenty of room in the cog, it's just a matter of getting things to work properly. My cache driver passed the cache tests, but failed running "hello world" from SimpleIDE. Like I said, need a short break. I'll resume work next week.
Production boards arrived today. I plan on soldering one up and taking photos/video when I do.. Sadly I'm quite short on bypass caps, so I need to get the 2 kits together and see if I have enough to build the new board. It will be close, that's for sure. If I don't, I can de-solder a few from previous boards. *Waiting for my new heat-gun to arrive to bulk de-solder previous boards.*
Very, Very interesting stuff you've been working on. I think it should make some things a snap. WAY cool!
I've been concerned with getting the PASM driver perfected, and as fast as possible. We're to the point where it shouldn't need changing any time soon. This is proving to be a bit of a challenge since I've never DIRECTLY programmed for the propeller counters. I'm getting it though and learning quite a bit, so that's good. The one thing that's boggling me is the FASTRamToDisplay... I have not really "played" with it too much so it's probably simple. The one thing I've observed is this: When running my simple splash screen test, I can draw the background *first file* but when drawing textT *don't know where yet* it garbles the display and gets stuck in the R2D loop? I'll play with this later, hopefully more information can solve the problem.
This is the working/old transfer The new transfer starts the same but adds To make up for the 2 extra transfers, one at the beginning of the loop when turning counters on, and one at the end when turning them off.
THEN set the counters up: And the actual transfer loop: Then shut it down The numbers on the side are the counter accumulation. This helped me figure out what was going on in the counters. I think it should work properly, but as I said it fails drawing text. I'll try drawing elements with it to determine more and let you know what I figure out!
*aedit*
After some more testing, fastR2D works in all cases of DrawBMPToRam, now to figure out why TextT doesn't work right?
*more edit!*
Seems fast draws now work correctly? Still need to debug. Speaking of bugs, I found one in the photo app, need to add code below after checking touchscreen to keep 2 < picturenumber < 7
I'm also missing several bmps for the signal generator as well as all files for HTML.
Thanks for your help, especially seeing how busy you must be with your project, and please do not go to any trouble searching out any more info for me, but if you have 5 minutes you might find some of my findings interesting.
Oh I've read the data sheet over and over and there is also a 'tips' pdf.
I see you send 0x90 or 0xD0 as an 8 bit command then read 12 bits in for a result.
This means you are in a mode where the touch chip powers down while CS is high and the int pin is activated even though you don't use it - I've elected to keep mine powered up all the time - that together with my using 8 bit mode gives the different command byte.
You are doing what the C51 code in the supplied (downloaded from sellers site) info' files does. (and why not)
I was thinking that an eight bit result would be plenty big enough for my purposes and when using the 'built in' avr spi hardware, 8 bits at a time is all it will do. Of course I could read two bytes (16 bits) and shift and adjust as required but seemed a bit over the top for my needs.
I send 0x9B or 0xDB as an 8 bit command then read 8 bits in for a result. (in my first post I mistyped 3 for .
Did you know you can interleave these commands and read data? This allows you to get a 12 bit result every 16 bits?
This is only relevent if you want to achieve maximum speed.
example on one axis
send- 10010000 00000000 10010000 00000000 10010000 00000000...........etc
recv- ???????? ?BA98765 43210??? ?BA98765 43210??? ?BA98765...........etc
The data sheet suggests doing multiple reads and averaging the result (as one method) or keep reading until you get a number of reads all the same.
Also, if I read the data sheet correctly, the data you get from the first clock of the twelve you send to receive a result is invalid! I suppose you should actually send 13 and lose the first? Of course this would mean you get a much bigger result (double) - I hope this makes some sense because really I'm thinking aloud - I might be rambling.....
AHA - and maybe that is why you get the result you do!!
PERHAPS for some reason when the screen is not touched that first bit is set and gives a large answer??? I dont know I must do some tests. It certainly doesn't in 8 bit mode.
Since you are satisfied with the way its works for you this is all just mental musing.
Anyway - thanks
Happy hunting
Dave
Well I've done some more testing this time sending 0x98 and 0xD8, still using 8 bit mode but with PD1 & PD0 =00 which puts it in 'power down and PENIRQ enabled mode'.(but not using the penirq pin). IT WORKS - with nothing touching the panel I get X=127 and Y=0 reliably! So thats a result! I can move on and do some button pushing.
It seems in portrait mode the touch pad regards the x axis as the vertical axis numbering from 1 at the bottom to 120 at the top and the Y as the horizontal numbering 1 to the left up to 120 at the right. It seems you have asked the display for the x value but assign it to y etc and I will do the same.
Regarding 12 /13 clocks I have been looking at your data sheet (Fig5 page 8) and zooming in to the clock/data signals it really looks as if the first clock after the command returns invalid data - try counting back from the positive clock in the middle of the lsb of the result and you get 13! - so perhaps you are losing the lsbit and in fact the result can give you twice the resolution!
When you get time have a look.
And thanks because without that chance remark about not needing penirq I would have wasted a precoius I/O pin.
Dave
Interesting observations! As far as the 12/13 clock, you are probably right. It may explain some of the results I've witnessed. I'm also unsure of the x/y at this time, maybe Dr.A could shed some light on this. Perhaps I will investigate this further after I solve some other issues. Glad to hear you have things working though!
I've spent the majority of my time working on the PASM portion and I'm stumped. I have been able to get fastR2D and fastR2H working but H2R is kickin my butt. Hopefully the guru's can help so I will start another thread in regards to this. My previous code may be faulty so I'm posting my recent efforts. and
Ok, we have both been writing code for the last week and now we need to reunify the code.
Attached is my current package of .spin files. In particular, I modified the stringcompare routine so that it returns 0 if equal, and negative or positive values if the strings are more or less than each other. I needed that for a bubblesort routine. But it broke the desktop.spin program (that displays the icons). There might be some other tweaks to the touch.spin program, but it will all be the spin part, not the pasm part. So you have been working on the pasm so hopefully it is not to hard to re-merge things.
Can you take a look at my code and double check it runs on your board, then let me know if I just drop your pasm bit into the code?
I'm not sure about the touch variables you have been discussing. A lot of it was trial and error with swapping x and y with the orientation. I'm still not sure of the best solution. I have a vague idea about a board with a little mercury/ball bearing tilt sensor and you tilt the board and it changes the orientation. If you did that, you want x and y to swap. Or do you? All the icons get rotated 90 degrees too. Or would you ever use such a tilt sensor?
You have found some other bugs - can you list them wrt that aug25 zip?
In an ideal world hopefully the touch.spin program becomes fairly stable and then who cares if you/we alter other apps, but we obviously need to work very closely on that common .spin program. And the desktop.spin as well.
BTW were you missing some .bmp files?
Hopefully the PASM will "just work." I'll double check your latest code in a bit, as well as test the updated PASM in it.
Re: tilt sensor. This could be interesting but I see some inherent issues with it. First, I believe we would need 2 files for background images *or any image with one axis resolution over 240px.* Also, in my experience with my Android, I just find it annoying. Better to provide an option to change orientation through user interaction IMO.
Re: x/y. I'm not sure of the best way of handling this either. I will keep thinking about this too.
I think the "bugs" I mentioned were more "user error" than anything else. If I find any I will let you know.
The BMPs I was missing are the ones for HTML and Signal Generator.
*edit*
Just found out the PASM is not compatible. I'll figure out why and get back to you.
Oh darn, I remember I did change the pasm. I stuck the at the beginning as I noticed that it was called by every routine anyway. Sorry. I might have changed other bits too. Might have been one of those intense alcohol/caffeine fueled coding sessions. Why are those the most productive??!
re missing .bmp files, hopefully it prints the missing filename on the screen - can you give me the names of the missing files?
We both probably need to have version numbers of these files and spend more time documenting changes than making changes. Not quite the way I tend to code but with collaborative efforts I guess that is the only solution...
*edit*
OKAY, digging deeper and it's going to require quite a bit of modification one way or another. I've made some hefty changes to the PASM driver, and that requires changes to the SPIN portion. This could get complicated....
First and least important, these commands were changed to reduce number of jumps *by 1* Also, removed Since this is now done by cogInit.
Then, changed all Spin code containing DIRAs to clear bit23 *p22* since P22 is only controlled by cog. Then changed SpinRamToDisplay, this is where things get interesting. not The reductions here are pushing the ramaddress into the CogCmd. Group changes auto by cog. Display enable is not needed since cog backs up/ restores latch value automatically. Set and forget until changing display.
Changes to CogCmd are fairly simple, remove bit 23 *p22* from DIR command, and restore outa BEFORE dira: Now the big changes... The PASM driver,...First off, at end of loops, jump to "done", not "init," init is used to enable P22 and set latch all high. Also, get_values saves current latch value into dirb for restore @ done, or ramToDisplay. Not needed for hubToDisplay since latch value never changes. Changing latches is done to dirb instead of latchvalue, then jump to done which updates the contents of the latch from dirb. This covers most of the changes. I removed some instructions here and there since they were not needed.
*edit*
I've been attempting to test the driver and there's something interesting going on. I can't quite put my finger on it yet, but it seems "BeginProgram" does not work? If I change to BeginDesktop("S"), everything seems to work. I've also missed a few optimizations unifying the driver so it's a bit slower than my previous version. *About 1/2 second for photo app.* Not sure what exactly is going on with BeginProgram...
*more edit*
RGBtoWord(255,255,255) causes program to crash?
The ILI9325 is well supported I believe, and at that price (£10 in UK money, not sure what the $ cost is) I'm ordering a couple. Pin out not clear but it looks like it might have 2 latch chips to drive 16bit interface from 8 data lines? Seems to need 5V (backlight?) but IO is 3V3.
A word of caution. You CAN connect the propeller chip directly to the display. Display draws will be SLOW if not using the external memory. I started out using my display connected directly to the propeller. Performance is less than ideal with full display draws taking several seconds.
I've been very busy this week, as I have family in town. The production board is ALMOST completely built and I should have the video done next week. As a side note, I just sold a fully assembled Touchburger!
I've been playing around with writing Pacman for this display using tile driver code. I'm also experimenting with a programming technique where you write and debug more quickly using a GUI on the PC and try to use routines with similar names so translating over to spin is quicker and easier. So, this is the propeller code, with a very strange alphanumeric description of the layout. It is a convenient way to work because it is easy to edit. Nothing is moving yet - this is just drawing the display. However, that byte array also is a useful descriptor for the code, as the pacman can use the ascii letters to work out where walls are, and the ghosts can work out where pacman is.
So this started life as vb.net code and was/is being debugged in vb.net
The pictures all exist as tiles, and for simplicity the tiles are all 6x6 pixels. So some things like ghosts end up needing 4 tiles. We will also be needing a transparency layer down the track. Take the tile data and work out how all the little curves and straight lines go together. Lots of fun!
For both vb.net and Spin, it is more convenient to convert a two dimensional array to a one dimensional array. That way, tiles can be sent to the display with a single call to a pasm routine, which is less than a microsecond to send out a tile. Hence the rather strange "smeared" bitmap which the spin version uses.
Next step is to start coding the rules for movement. Then pull in the .wav files (many available on the internet for pacman) and the controls.
Keep up the excellent work and thanks again!
Joe
*edit*
Voltage rails look good and I'm not seeing any transients on the /reset line either. I'm confused as to what the issue is. Need to scavenge some 10k resistor networks from previous boards. Resistor networks *as well as 4 sets of regulators* are on their way from futurlec.
*aedit*
Replaced RN1 and RN6 with 10k. Still rebooting randomly. Really starting to make me wonder.
*more edit*
OKAY, I figured it out! I guess wall-wart selection is more important than I thought. Seems the 12v .9a I have been using doesn't have the amps to push 2 displays? *14.3v out* Tried a 5v 2.5a and it works, although 5v is 4.3 and 3.3v is 3.17-3.23. I'll test some more warts and see what I find!
*final edit*
Power supply issues confirmed. I suspect the buck regs are allowing a very quick voltage drop I'm not able to see on my slow meters. None of the wall-warts I've tried have the guts to push this board. Pulled the rack-mount out and it's supply runs the board just fine @7.5v with a peak observable draw of 175ma?*The supply is fused @750ma. I've tried 6-9v warts from 900ma to 2100ma and the only ones that "work" are "switching" 5v warts. One rated 2.5a, the other rated 2a. They boot and run programs, but I've had the occasional random reboot. I'm guessing the recommended wall-wart should be 6-9v 2A?
I tried soldering a .1uf ceramic and 10 uf to the sd card pins. Tried many wall warts. I even tried swapping a 5v linear regulator. I'm really starting to wonder what is going on.
Curious what you're using to power the boards?
*edit*
I just got a VERY interesting result when I removed the MAX chip. It looks like the 3v3 rail is sagging, during sd mount. This is (somehow) causing the MAX to pull a reset. Need to investigate further, but at least I'm getting somewhere...
*aedit*
Okay, removing the MAX2323 solved the "reset bug." As I stated, my meters are too "slow" to really "see" the spike. It seems to be the 3v3, not 5 as I had though. Propplug works just fine *if not better than the MAX3232* so this is a bonus.
After re-installing the 5v buck reg, I tested several wall-warts and they work fine with both displays installed. Not recommending the 5v "switching" supplies as the rails are too weak, seeing 4.37-4.4v and 3.21v.
Tested "working" warts have 4.85v and 3.25-3.27 respectively.
Radioshack 9v 800ma. CAT 273-1770
Panasonic 12v 0.9A Model BAD7001 *my MAIN wart, from NICAD charger.*
Cannon 8.4v 2.0A Model CA-570 *nice and lightweight, voltages seem stable?*
More testing soon!
The whole time I've been wondering the EXACT details of my reset bug. Need to dig through the data-sheets for the SIPEX SP3232ECP. Removing this chip restored stability *even the rackmount PSU started to bug*
I was going to suggest some bigger caps eg 4700uF on each of the 3V and 5V supplies. It is strange that the display on the 5V supply is upsetting something on the 3V supply.
I've pulled apart my wallwart and it has a 4700uF cap inside. It is possible that different wall warts have smaller caps inside, so maybe worth putting 4700uF across the input instead of the 470uF?
It's curious I have this issue and you do not. Perhaps the SP3232 is sensitive in a way the MAX is not? I'm fairly certain the issue involves a "saggy rail," although I'm not happy with 3.25 and 4.85 nominal voltages. IMO should be 3.31v and 5.02v to 3.28v and 4.97v. I've tried a number of warts and none could handle SD mount. I can "see" sag on my meters, but can't estimate "ACTUAL" sag. I'm going to look into the sound-card -scope programs. No substitue for good test equipment, but might help track the issue. The GB "GDT-11" is about as worthless as they come, and my analog meter is not much help either.
*edit*
Well I must have something messed up since Lorem is showing up with a "1" or "3" at the beginning?
*aedit*
About Lorem... It was indicating an error in my driver. I was aware that things were not working correctly and have solved this. Seems I tried optimizing TOO far and broke Set161... The correct version is I went back and re-compiled everything, updated SD and some things work. I think buttons has a glitch, not sure what yet. There's a few other things. Need to check your tile driver. I hope I didn't break that..
#1. More code. I have an idea that might speed things up a fraction of a MS... Moving all display commands to cog. Fill rambuffer with commands as longs, hi-word command, low-word data. Call PASM driver, which outputs command, data... until reaching command #22, *write gddr*
I've also been thinking about Ram2display and Hub2display. Before calling these commands, we must be in group2, with RS high, and the display(s) selected. Seems best to me if we only be concerned about having the proper display selected and everything else is automatic. This way if we're in group3 and the display is touched, just select the proper display and update. Then return to caller will be in group3, *or 4* just like you left.
#2. I've also been thinking about "stuffing" SPI into cog-driver. This will obviously not work for the cache driver, but could save a cog? Stuffing FATe is not a possibility.
The idea is to improve performance, increase flexibility, and not break anything in the process. I'm still not 100% sure the driver is correct. I still can't account for all of the instructions in the burst-transfers. The propeller's counters and our external 161 counters are dynamite together. Making it work properly is not so easy. I tried to import one portion at a time, checking against the other 2 for reference. The set161 bug might have a "ripple" effect, or that's what I'm afraid of. I'll revive the OTHER post on this issue as maybe one of the guru's can guide me in the right direction.
I'm still wrapping my head around the reset bug. I'll build a few more boards and see if I can find a difference. I still need to document the linear regulator mod. More photos and video will always help. The last build session was in low light and came out with a bit of video-noise. The outside portion was full of glare. A few good clips, but need more footage. I'm attaching the "fixed" touch.spin. Notice change in revision#.
There is much we can do with putting code into cogs - we haven't even started with that but hopefully with more builders others will be able to contribute.
One thing for instance is the Spin "draw" routine that sets up where to draw a picture x,y,sizex,sizey eg - for a 36 pixel tile like in pacman, the time to do the "draw" may well be taking longer than the actual outputting of the bytes.
In one sense I kind of like the idea of handing over code to other builders with 2/3 of the hub free, with most cogs free and with pasm drivers still with spare space. There were some instances a few years back with the 8080 and Z80 drivers where some of the object code came with "one long free".
I haven't had a chance to do any coding for the last few days but hopefully later this week.
Re: free hub memory... I've been thinking about this A LOT. Things like the display initialization code could be stored on the SD card to save space. Then there's the problem of what happens when something goes wrong with the SD... Not easy to diagnose. May not be worth the trouble. Other things could be done and, if worse came to worse, builders could remove unused PUBs in touch.spin. Dynamic loading could also save some memory. For instance, if ALL programs expect to be called from desktop, no need for all the initializations in the PROGRAM's touch.spin
The last thing is, thinking about expanding the desktop app. It would be interesting to be able to "add" a program to the desktop without manually editing cvs... Say open keyboard, enter command string and desktop edits CVS? Maybe change name of background file? A file browser/selection would be handy... Many things to do! Many possibilities!
I CERTAINLY want to leave builders enough room to do "useful" stuff. I don't want to "force" them to use the SRAM... And I don't think it will be necessary. A few longs in PASM will be worth the savings in SPIN, in speed and program size, IMO. Draw is the first to "go under the knife" just not sure the best way to implement the command buffer. I'm thinking of allocating 5 longs JUST BEFORE rambuffer to store draw cmds... X,Y,SizeX,SizeY, AND gddrwr... Or maybe 2 calls to PASM driver is better? I'll start writing for seperate calls since it will be the easiest to debug. I have a basic idea, now just need to flesh it out!
Oh and no, reset bug is still "buggin" me. Only 1 board built ATM and MAX circuit was removed. Must save this for another day since it's not "top of stack." The 3 sold boards will be using propPlugs for programming *I think* Still not happy with the Supply rails being as low as they are... Or am I just paranoid??
Not much goes wrong with the SD but Kye's code allows you to print debug error messages to the screen and the code for that is there for things like not finding a .bmp file.
Re adding things to the .csv, well that would be an app that we need to write. Take the keyboard app and display the .csv file in it and then allow the user to scroll up and down and insert text. The text buffer is small so plenty of room in hub to fit that, which makes coding easier.
Re the low supply rails, I'm measuring values a little higher and I did once put all my multimeters on a rail and they all disagreed but 0.1 to 0.3V.
I see on facebook you got your other half to do all the soldering. Wish my wife would learn to solder!
Not much goes wrong with the SD but Kye's code allows you to print debug error messages to the screen and the code for that is there for things like not finding a .bmp file.
Re adding things to the .csv, well that would be an app that we need to write. Take the keyboard app and display the .csv file in it and then allow the user to scroll up and down and insert text. The text buffer is small so plenty of room in hub to fit that, which makes coding easier.
Re the low supply rails, I'm measuring values a little higher and I did once put all my multimeters on a rail and they all disagreed but 0.1 to 0.3V.
I see on facebook you got your other half to do all the soldering. Wish my wife would learn to solder!
RE: sd debugging. My thought is pushing the display setups to the SD could save quite a bit of space. This means the sd card needs to mount before the display can be initialized. Perhaps we could have more than 1 version of touch.spin? One contains display inits and all code touch.spin currently has. Desktop will be compiled with this version. A "slim" version could be built for user programs that pulls all display inits from SD card. Or something like that, still need to think on it.
The idea I stated about editing the CVS is one "function" of a larger "desktop settings" program I'm thinking about. Still need to think of all the things necessary to make this work.
I have done some work on display commands in PASM. I started with draw which seems to work. Still need to experiment but the basics *for verification* This could be optimized a bit and in several ways. I'm thinking of optimizing for speed first...
Still need to work on cache driver. I'll try that later tonight.
I am VERY lucky my better half takes an interest in my hobbies. She soldered together a few of the early boards to help keep things moving. *None of this would be possible without her love and support*
*edit*
I've come up with an idea but wanted to bounce the details off of you. What I've been thinking about is trying to cut as much SPIN as possible. Also simplify the draw command so, instead of the above draw And have the cog setup the proper draw commands. This would require a command to configure the selected display? Or could we do this on INIT?
Thinking in a generic sense, what you could do is put a whole series of commands in that array and send them out. You could have a simple language for that, maybe it is a bit inefficient but if you have one long and 8 bits are for the data and one bit defines whether it is a command or data, and another bit could define if it is the end of sequence. Then you could store all the startup sequence as a series of longs. And that could be stored as a file on the SD card like you say, and save a pile of hub ram code space.
I've been pondering cache drivers in C. The fundamental problem holding this all back is that both C++ and C89 don't suit this board, because the cache driver and the code both may want to share access to external memory at the same time. I'm not sure how to explain it fully on the C threads - it is our hardware so I think we have to solve it. So - store the program on the SD card and you can't use the SD card. Store it in ram and the code can't use ram. I have an idea that you run Kye's SD driver through the Spin2C program and run it but it is not that simple.
Fundamentally, I'd like to have the C program in external ram rather than on the SD card because it is faster. I see two solutions - one uses two cogs - one running the C cache driver and one running our touchscreen driver. Between those you have a lock and control is handed back and forth between those cogs. An alternative is three cogs where one is the master cog (either running spin or pasm) which handles which cog has control of the system.
It is complicated thinking about the code needed to do a large block transfer from SD out to external ram. Such a block transfer is going to need the C code running in order for the SD code to be running. But if the C code is running, the user does not have access to the ram to do the data transfer. You end up sending the data in 512 byte chunks through hub with multiple resetting of the 161 counters rather than one smooth transfer. And yet Spin can do that transfer in one go. At the deep down fundamental level, XMM C still can't seem to replicate what Spin can do. Maybe it can - I just need to think about it some more. I think the problem is that C that fits just in hub will work, but C is bigger than Spin for given equivalent code so a realistic program won't fit in hub. So you are stuck with putting the C program in some form of external storage and that creates all the problems. Perhaps the answer is to allocate a much bigger SD buffer in hub - maybe 8k or something, and then transfer everything in 8k chunks, thus decreasing the number of swaps back and forth between the display driver and the cache driver.
I guess I have bailed out and gone back to coding everything in Spin. Solve the simple problems first. Certainly putting the draw routine in pasm will speed up pacman and other tile programs, and putting the init code on the SD card as a file will save hub space.
I should be able to have the "basic" cache driver soon. My previous attempt was foiled due to poor coding of MY touch.spin. I'm fairly sure this is fixed. The only program that highlighted the bug was Lorem. Now things run properly and BeginProgram works again. Sorry about that.
I still need to optimize touch.spin a bit more. I see quite a bit of room for improvement. I would very much like to pass draw commands as an address to a an array of 4 long, x1,x2,y1,y2 and have the cog do the rest... Quite possible, but may take a bit of self-modifying code... Not my strongest suit but it will help improve my skills. I feel the driver may be headed in 2 paths in the future. The one path mentioned previously, where the driver does not include display inits, should be named differently for reference. The other path is best for initial development of programs, containing debug code and display inits. From my point of view, most programs should be expected to run from the desktop. The desktop inits the display so there should be no need for that code in the driver... EXCEPT for initial development where program will most likely be run from unknown state. Not my favorite solution but seems better than using conditional compiles and BST. We don't need to worry about this quite yet, just something to think about.
There's quite a bit to think about, all quite possible... Just several levels of difficulty. Oh, there's 227 longs left in the RAM cog. I'll keep you updated!
PS. please test VER 0.0.8.6, I think it's okay but need a second set of eyes. The cache driver test did not show bug in old code, but when trying to run Hello.c failed. Hopefully I'll have better luck tonight.