Free Running Timer in the Spin Interpreter Cog
JonnyMac
Posts: 9,104
The great thing about the Propeller is generally not needing interrupts, but the P2 allows them, and Chip added a neat feature that lets us install interrupt-driven code into the cog that is running the interpreter. This is pretty cool, and that I -- a person who doesn't generally relish coding in PASM -- can pull this off with just a little effort goes to show how nice PASM2 is.
During the Early Adopter meeting Chip explained that hub longs 0..15 are not used and available for our apps. In my case, the long at address 0 holds the timer registers: 1/100ths seconds, seconds, minutes, and hours (bytes 0..3). The long at address 4 is the control value: 0 to reset and stop the timer, 1 to hold the timer at its current value; any other value lets the timer run.
Okay, okay, it's a timer. But the ability to do this within the Spin interpreter cog is making me smile. This is what gets installed in the interpreter cog:
Update: There was a bug in my HOLD state; that's fixed now. I also added a variation that is a running milliseconds timer, like with the Arduino ecosystem. The advantage of this one is that it can be reset, put on hold, and modified.
During the Early Adopter meeting Chip explained that hub longs 0..15 are not used and available for our apps. In my case, the long at address 0 holds the timer registers: 1/100ths seconds, seconds, minutes, and hours (bytes 0..3). The long at address 4 is the control value: 0 to reset and stop the timer, 1 to hold the timer at its current value; any other value lets the timer run.
Okay, okay, it's a timer. But the ability to do this within the Spin interpreter cog is making me smile. This is what gets installed in the interpreter cog:
Update: There was a bug in my HOLD state; that's fixed now. I also added a variation that is a running milliseconds timer, like with the Arduino ecosystem. The advantage of this one is that it can be reset, put on hold, and modified.
dat { timer isr } timer word start, finish-start-1 ' define chunk start and size-1 org $110 ' org can be $000..$130-size start mov ijmp1, #isr ' set int1 vector setint1 #1 ' set int1 to ct-passed-ct1 event getct pr0 ' get ct _ret_ addct1 pr0, ##clkfreq_/100 ' set initial ct1 target, return to Spin2 isr rdlong work, #TMR_CTRL wz ' hub $0000_0004 is control if_z mov tregs, #0 ' reset clock if_z jmp #update cmp work, #TMR_HOLD wcz ' hold with current value (fixed) if_e jmp #exit ' if long[TMR_CTRL] not 0 or 1, let the timer run adj_timer rdlong tregs, #TMR_REGS ' hub $0000_0000 is timer regs getbyte work, tregs, #0 ' 1/100ths incmod work, #99 wc ' increment with rollover setbyte tregs, work, #0 ' put it back if_nc jmp #update ' if no rollover, update and exit getbyte work, tregs, #1 ' seconds incmod work, #59 wc setbyte tregs, work, #1 if_nc jmp #update getbyte work, tregs, #2 ' minutes incmod work, #59 wc setbyte tregs, work, #2 if_nc jmp #update getbyte work, tregs, #3 ' hours incmod work, #23 wc setbyte tregs, work, #3 update wrlong tregs, #TMR_REGS ' update the timer exit addct1 pr0, ##clkfreq_/100 reti1 ' return from interrupt tregs long 0 work long 0 finish ' 32 longs
Comments
Any guidance on the BCD increment with roll-over? We don't have a digit carry like some processors, so this was the only way I could think of to handle this. Can this be smaller/faster?
And, yes, I pushed for getms() because I will use it. This is a programming exercise, but does have some utility. I have a few P1 programs that run a soft RTC in another cog; I can save the cog using this code in the P2.
I agree, I like what you've done.
This is a nice complement to the Propeller 2 Instructions spreadsheet, which I have been spending some time into. There are certain conventions in the description column of the spreadsheet that I haven't figure out yet but examples like this and the Propeller 1 manual help a lot.