Help Accessing Single LCD with multiple Cogs
jaws369
Posts: 6
I have been reading the forum and manual for about 5 hours trying to get a few cogs to run some simple code and each control a line in a 4x20 LCD. However, I have found I cannot seem to do it. I can get 1 line to work, but never more than that. I have simplified the code down for easy reading. Could someone please review it and let me know where I am going wrong. LINE 1 is Main Cog, Line 2 - 3 are the other cogs launched that just make some timing up and increment an integer.
Thanks so much for anyone that can spot the error of my ways with Locks.
Sean
{Object_LCDTest.spin} CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 LCD_Baud = 19_200 ' LCD Baud Rate LCD_Lines = 4 ' Parallax 4X20 Serial LCD (#27979) LCD_Pin = 0 VAR long LockNum long cog1 long cog2 long cog3 long StackSp1[20] long StackSp2[20] long StackSp3[20] OBJ LCD : "debug_lcd" PUB Main | x, Success lcd.init(LCD_Pin, LCD_Baud, LCD_Lines) lcd.backlight(1) lcd.cls lcd.str(string("Starting Test")) waitcnt(clkfreq + cnt) lcd.cls lcd.gotoxy(0,0) lcd.str(String("COG 1:")) lcd.gotoxy(8, 0) lcd.str(string("Get Lock")) ' Setup and Sign out a new LOCK ID.... LockNum := locknew waitcnt(clkfreq + cnt) lcd.gotoxy(8, 0) lcd.str(string("Locked ")) lcd.gotoxy(15, 0) lcd.dec(LockNum) waitcnt(clkfreq / 2 + cnt) ' ************* START THE NEW COGS FOR LCD TESTING ********** cog1 := Cognew(LCDTest(1, @LockNum), @StackSp1) cog2 := Cognew(LCDTest(2, @LockNum), @StackSp2) cog3 := Cognew(LCDTest(3, @LockNum), @StackSp3) repeat x++ repeat until not lockset(LockNum) 'wait until we lock the resource lcd.gotoxy(18, 0) lcd.dec(x) lockclr(LockNum) 'unlock the resource waitcnt(clkfreq / 5 + cnt) if x == 50 x :=0 PRI LCDTest(LCDBase, _LockNum) | x x := 0 lcd.init(LCD_Pin, LCD_Baud, LCD_Lines) repeat until not lockset(long[_LockNum] -1) lcd.gotoxy(0,LCDBase) lcd.str(String("Start Cog ")) lcd.dec(LCDBase) lockclr(long[_LockNum] -1) waitcnt(clkfreq / 2 + cnt) repeat x++ repeat until not lockset(long[_LockNum] -1) lcd.gotoxy(18, LCDBase) lcd.dec(x) lockclr(long[_LockNum] -1) 'unlock the resource waitcnt(clkfreq / LCDBase + cnt) if x == 300 x :=0
Thanks so much for anyone that can spot the error of my ways with Locks.
Sean
Comments
Alternatively you could just have all access to the very lowest I/O level stuff doing something similar. You could have two registers, data and control, except they are hub variables. You write what you want to them and the cog dedicated to the LCD I/O can read them and perform the low-level I/O write. Also there is never any need to read the busy flag, never, so simplify the code and cut it out, the Prop I/O and Spin are never faster then the LCD. Just observe the delays during initialization, that's all.
Can you test this.
I have also been wondering about this. Thanks for a solution!
This is simply a matter of each cog having it's own direction and output registers which is always a problem when trying to access the same I/O from different cogs as they end up as 8 sets of outputs being OR'ed together. If cog 4 had set the I/O high then there is nothing another cog can do to bring it low. But you can have pullups on the pins to keep them high and let each cog release the "high" level once it's done but this doesn't stop more than one cog trying to access it at the same time. The second method is simply to have a cog handle this I/O (and maybe others) and pass "commands" to the cog to do the work for you. In the case of an LCD you can pass characters and commands without touching any I/O but which the LCD cog then proceeds to handle.
I have tried it with small and large stack spaces, passing references and also passing the variable directly. Nothing seems to allow different cogs to gain control and start writing. I'm suspecting that the objects I am using do not support this and will have to check that next too.
IF ANYONE has a working multi-cog set of code that writes to a single LCD (you can strip it down to it's bare essentials) and are willing to share the code, I'd seriously appreciate it. I'd rather solve the issue and learn rather than create a master cog running the LCD as a work around personally. Any help is appreciated!!!
S.
Thanks however for your thoughts on it,I'll have the control cog as my backup plan...
S.
As I mentioned, it's all in the I/O and it's hard to share because of the OR'd nature of the cogs, so let one cog do the work. Look, at it's bare basics you should only really have one function that writes the data to the LCD I/O pins after setting up the RS. It's this function that really just needs to sniff for input from a hub variable and if set then it writes. The higher level code can be shared with multiple cogs but none of them should attempt to access the I/O pins themselves.
If you need some detail on how to do this then zip/archive up your project files and attach them to your post so I can see exactly what you've got as I'm not going to go searching for them and guessing. I will mod it for you (with improvements of course).
P.S. The next generation Prop chip P2 has much more flexible I/O in this regard.
S
all cogs that want to display something write into the buffer.
then there is one cog who sends the buffer-content to the LCD.
this makes sure that the data send to the LCD is not messed up at low-level.
(or'ed IO-pins)
it might happen that the content of the buffer is partly "crappy" because
cogs and start overwrite the characters.
two ideas about how to avoid this
each cog has an exclusive area on the LCD where only this cog writes new characters in the buffer
some kind of semaphores to avoid crosswriting into the buffer.
best regards
Stefan