I'm glad that's straightened out, but now the example hardly seems to be about indirect JMP at all. Perhaps it would be more compelling if it used an explicit state variable?
Init MOV State,#State1
' NOP <- no longer needed, I guessJMP State
State1 do state1 stuff
..
Common common post-state code
..
JMP State
State RES1
Yeah, I thought about that, too, as I was posting the error correction. But I was in such a hurry just to fix it that I didn't follow through with the tighter, more illustrative code. That has now been remedied.
One more thing while I have your attention: The last trick, on sign-extension, says
In Spin, do this:
Value := Value << 24 ~> 24
Wouldn't it be more idiomatic to do this instead:
~Value
I know the trick is about sign-extending from any bit, but using a byte as an example made me half expect that the trick would be the ~ operator. (Of course, for C/C++ guys, this meaning of ~ may be more of a trap than a trick.)
Perhaps the text could mention the two sign-extension operators ~ and ~~, then describe the left/right shifty trick for arbitrary sign bit positions, with an example that uses an oddball shift count rather than 24 or 16. It could also mention that execution time is independent of shift count, assuming that's the case, which I believe it is.
'Another good suggestion, which I've now incorporated.
You're right about the execution time of the shifts. The Propeller uses a barrel shifter, rather than an incremental one. However, since this is neither a trick nor a trap, there wasn't a good place to incorporate such info in the document.
A trick suggestion: I thought the use of jmpret as a task dispatcher in tv_drv was pretty darn clever. Some coroutine action going on there.
A trap suggestion: Square brackets mean array indexing -- except when they don't. After INA, DIRA, etc., they are pin specifiers. I just find that sort of special-case hijinx annoying (probably just me).
mpark said...
....·Square brackets mean array indexing -- except when they don't. ...
A nice list would summarize all the various parentheticals (and where they are used) be they (), [noparse]/noparse or what have you. The compiler sure does (expletive) obscurely when you·get them wrong...
The COGNEW/COGINIT Spin statements allow an arbitrary Spin method call as the first parameter including a call of a method in another object (like foobah.myMethod). This is accepted by the compiler without comment, but will not be executed properly. The method must be one in the same object as the COGNEW/COGINIT call.
values in DAT section byte etc. are not range checked (1.05.5):
DATbyte$555
will silently fail, and it's equivalent to byte $55.
EDIT: I couldn't replicate the following trap when I tried with simple code...
x := 1 + y
will first write 1 into x, then add y to that.
So if you have an assembly driver polling for that location, it will see it when it's 1. eg. I had hard time debugging the following code:
s_ras_cmd := const#CMD_SAVE_MAP + p_tilemap_index
The following works:
x := const#CMD_SAVE_MAP + p_tilemap_index
s_ras_cmd := x
Your code has a bug, rdlong RA, opflag WZ reads address 0 in hub ram. you should pass a pointer of opflag in PAR etc. EDIT: A post got deleted between my messages.
I wrote some test code, but now I can't even replicate the bug myself... but the temporary variable really solved the problem
Sorry, Jasper, I was unsure for a second.. No, my program is fine But I cannot produce your bug
{
Exploring JASPER's Bug v04
2007 deSilva
}CON_clkmode = xtal1 + pll8x_xinfreq = 10_000_000OBJ
pc : "PC_Interface"' Ariba's PropTerminalPUBmain
pc.start(31,30)
alarm := @alarm
opflag := @opflag
cognew(@asm,0)
repeat
pc.out(0)
pc.str(string("checking JASPER's trap ...press any key"))
if alarm
pc.str(string(13, "There's a fly in the ointment"))
waitcnt(clkfreq+cnt)
alarm := 0if pc.gotKey ' press a key to show the bug (?)
pc.clearKeys
' according to the report, first 0 should be written to opflag
opflag := 0 + takeYourTime
waitcnt(clkfreq/20+cnt)
pritakeYourTimewaitcnt(clkfreq/1000+cnt)
return1' change this to 0 and the programm will trigger...DATorg0
asm
' Wait for opflag ==0rdlong RA, opflag WZif_Zwrlong opflag, alarm 'write any value as long as its not 0 jmp #asm
RA long0
alarm long0
opflag long0
A trick for saving stack space is to use the 'result' variable associated with each method, whether it returns a result or not. A benefit is that unlike other local variables it is zeroed on entry to the method.
If using a variable named 'result' isn't appealing, it can be renamed as the return variable ...
I've corrected an error on page 8, where it stated that bits 31..2 are passed to the PAR register by COGNEW. Actually it's bits 15..2. My thanks to Rayman and BradC for pointing this out!
At some point I need to collect and filter the latest batch of user-contributed material for inclusion. I haven't forgotten, and thanks for all the input!
-Phil
Post Edited (Phil Pilgrim (PhiPi)) : 9/28/2007 7:29:43 PM GMT
I was talking with Chip about the Turboprop and ran into something new.(I think)
My discussion was in “What would you want more of, cogs or RAM?” starting on page 25.
I'm still looking to see if all 512 COG RAM location are indeed filled with HUB data during initialization.
This would be the easiest way to get code/data into the 'Shadow Registers'.
LewisD
Chip said...
Cog RAM is read directly for instructions, not special 'source' registers such as PAR, CNT, etc. So, you could write a JMP instruction into the PAR register ($1F0) and have it execute, not having to consider what PAR would return as a 'source'. In other words, the large-model would work fine by reading eight contiguous hub longs into $1E8-$1EF and then JMPing to $1E8, and then having a JMP back execute from RAM (not PAR) at $1F0.
Chip how many of the registers are like that?(all?)
Yes, all. Some registers like PAR, CNT, INA, etc. have special mux's for reading live states when accessed as source registers. All instructions and destination registers are read from RAM, though - not mux's.
A SPIN REPEAT trap, well known, but sometimes forgotten...
st := 0REPEAT i FROM st TO1' executed twice (i = 0,1)
st := 2REPEAT i FROM st TO1'also executed twice (i = 2,1)
SPIN evaluates both limits in the beginning and decides whether to run the loop forward or backward. This is a great feature, but extremely surprising for experienced programmers.
Excellent suggestion Beau! I think I will use this method in the future. Not only does it eliminate some variables, but it also saves the execution time where other routines do the calculation each time to determine the correct delay length.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter tdswieter.com
One little spark of imagination is all it takes for an idea to explode
It would be nicer if the Propeller Tool could (1) create a _CLKFREQ or _XINFREQ based on the other (2) allow both _CLKFREQ and _XINFREQ and produce an error only if the two do not match up using the _CLKMODE setting.
Trap AND Trick: Not sure how well this was known before:
The compiler remembers the size of a label in the DAT section according to the size identifier after this label.
Example:
DAT
lo LONG10,20,30
by BYTE"ABC",0
However a "standalone label" is always considered as a LONG:
Example:
byBYTE"ABC",0
is no longer correctly addressable by by[noparse][[/noparse]...]
There is a work around as follows
byBYTEBYTE"ABC",0
A size identifier without preset does not allocate space but assigns the correct attribute to the label only!
It most likely also aligns for WORD and LONG, but I have not checked it.
Post Edited (deSilva) : 10/27/2007 10:37:32 AM GMT
I shall investigate a little bit deeper.. Alas, I do no longer read the Hydra threads..
But I already can assure you it is not BYTE a standalone label defaults to...
I wasn't disagreeing with you, just adding an additional quirk, but on digging a little deeper it appears that the rules for standalone labels are:
a. The last size identifier preceding a standalone label determines its "type".
b. If there is no preceding size identifier, a standalone label defaults to BYTE.
Here is a cool trick using the muxc command to self modify the instruction bits of another command, thus changing the command entirely....
The example uses this technique to Bit-Bang data to an I/O port with 50nS output transitions (20MHz).
Enjoy!
[b]CON[/b]
[b]_clkmode[/b] = [b]xtal[/b]1 + [b]pll[/b]16x
[b]_xinfreq[/b] = 5_000_000
OutputPin = 0
DataOut = %1000_1111_0000_1010_1010_1001_1001_1011'<- Data to send
[b]PUB[/b] ASM_FAST_BitBang_DEMO
[b]cognew[/b](@FAST_BitBang,0)
[b]DAT[/b]
FAST_BitBang [b]org[/b] 0
[b]mov[/b] OutputPinMask, #1'' Create Pin Mask for Output pin
[b]shl[/b] OutputPinMask, #OutputPin
[b]mov[/b] LoopCounts, #32'Self Modifying Bit-Bang Code
Loop [b]ror[/b] Buff, #1 [b]wc[/b]
BitIndex [b]muxc[/b] Bit0, instr_mux
[b]add[/b] BitIndex, dest_inc
[b]djnz[/b] LoopCounts, #Loop
'This section of code self modifies the code below,'so that each of the bits can transition in only 50nS.'It does this by MUXing the "C" flag into the instruction'location of the muxz commands below.'By default, the way that the muxz is used, it will make'output Pin LOW. When the instruction location is changed...'...from 011110 to 011111 (<-Notice only one bit difference)'...in this section of the code via the muxc instruction, 'muxz below effectively becomes a muxnz. Cool Huh!?
[b]or[/b] [b]dira[/b], OutputPinMask 'Make Pin an Output
[b]mov[/b] [b]outa[/b], #1 [b]nr[/b],[b]wz[/b] 'Clear Z flag for TRUE data' [b]mov[/b] [b]outa[/b], #0 [b]nr[/b],[b]wz[/b] 'Set Z flag for INVERTED data
The following MUX commands use the "Z" flag set above
Bit0 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Self Modified Code to Bit Bang at 20MHz
Bit1 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit2 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW The lines above that read...
Bit3 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit4 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW muxc {Bit#}, instr_mux
Bit5 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit6 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW ...self modify the instruction bits
Bit7 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW of the lines that read...
Bit8 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit9 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW {Bit#} muxz outa, OutputPinMask
Bit10 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit11 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW ...so that when the BIT in Buff is
Bit12 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW a "1", the lines that did read...
Bit13 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit14 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW {Bit#} muxz outa, OutputPinMask
Bit15 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit16 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW ...now function as if they read...
Bit17 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit18 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW {Bit#} muxnz outa, OutputPinMask
Bit19 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit20 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW ...with 'muxz' the output pin is made
Bit21 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW LOW ... with 'muxnz' the output pin
Bit22 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW is made HIGH. This is so that a pin
Bit23 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW can transition in 4 Clocks or 50nS rather
Bit24 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW than 8 Clocks or 100nS. This makes it twice
Bit25 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW as fast.
Bit26 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit27 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit28 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit29 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit30 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
Bit31 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW
instr_mux [b]long[/b] $0400_0000
dest_inc [b]long[/b] $0000_0200
Buff [b]long[/b] DataOut
OutputPinMask [b]long[/b] 0
LoopCounts [b]long[/b] 0
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 11/20/2007 6:26:56 PM GMT
Comments
Thanks!
Phil
Init MOV State,#State1 ' NOP <- no longer needed, I guess JMP State State1 do state1 stuff .. Common common post-state code .. JMP State State RES 1
Post Edited (mpark) : 6/20/2007 2:22:00 PM GMT
Thanks for the prodding!
-Phil
In Spin, do this:
Value := Value << 24 ~> 24
Wouldn't it be more idiomatic to do this instead:
~Value
I know the trick is about sign-extending from any bit, but using a byte as an example made me half expect that the trick would be the ~ operator. (Of course, for C/C++ guys, this meaning of ~ may be more of a trap than a trick.)
Perhaps the text could mention the two sign-extension operators ~ and ~~, then describe the left/right shifty trick for arbitrary sign bit positions, with an example that uses an oddball shift count rather than 24 or 16. It could also mention that execution time is independent of shift count, assuming that's the case, which I believe it is.
You're right about the execution time of the shifts. The Propeller uses a barrel shifter, rather than an incremental one. However, since this is neither a trick nor a trap, there wasn't a good place to incorporate such info in the document.
Thanks,
Phil
A trap suggestion: Square brackets mean array indexing -- except when they don't. After INA, DIRA, etc., they are pin specifiers. I just find that sort of special-case hijinx annoying (probably just me).
values in DAT section byte etc. are not range checked (1.05.5):
DAT byte $555
will silently fail, and it's equivalent to byte $55.
EDIT: I couldn't replicate the following trap when I tried with simple code...
x := 1 + y
will first write 1 into x, then add y to that.
So if you have an assembly driver polling for that location, it will see it when it's 1. eg. I had hard time debugging the following code:
s_ras_cmd := const#CMD_SAVE_MAP + p_tilemap_index
The following works:
x := const#CMD_SAVE_MAP + p_tilemap_index s_ras_cmd := x
Post Edited (Jasper_M) : 8/25/2007 5:51:06 PM GMT
I wrote some test code, but now I can't even replicate the bug myself... but the temporary variable really solved the problem
{ Exploring JASPER's Bug v04 2007 deSilva } CON _clkmode = xtal1 + pll8x _xinfreq = 10_000_000 OBJ pc : "PC_Interface" ' Ariba's PropTerminal PUB main pc.start(31,30) alarm := @alarm opflag := @opflag cognew(@asm,0) repeat pc.out(0) pc.str(string("checking JASPER's trap ...press any key")) if alarm pc.str(string(13, "There's a fly in the ointment")) waitcnt(clkfreq+cnt) alarm := 0 if pc.gotKey ' press a key to show the bug (?) pc.clearKeys ' according to the report, first 0 should be written to opflag opflag := 0 + takeYourTime waitcnt(clkfreq/20+cnt) pri takeYourTime waitcnt(clkfreq/1000+cnt) return 1 ' change this to 0 and the programm will trigger... DAT org 0 asm ' Wait for opflag ==0 rdlong RA, opflag WZ if_Z wrlong opflag, alarm 'write any value as long as its not 0 jmp #asm RA long 0 alarm long 0 opflag long 0
Post Edited (deSilva) : 8/25/2007 11:45:37 PM GMT
Post Edited (Jasper_M) : 8/25/2007 8:34:02 PM GMT
if pc.gotKey ' press a key to show program works pc.clearKeys ' countercheck opflag := 0 opflag := 1
... and I finally found the "bug" in it: It has to be "ointment" not "oinment" - idiot that I am.
Post Edited (deSilva) : 8/25/2007 11:43:10 PM GMT
If using a variable named 'result' isn't appealing, it can be renamed as the return variable ...
PRI MySub : tmp
At some point I need to collect and filter the latest batch of user-contributed material for inclusion. I haven't forgotten, and thanks for all the input!
-Phil
Post Edited (Phil Pilgrim (PhiPi)) : 9/28/2007 7:29:43 PM GMT
I was talking with Chip about the Turboprop and ran into something new.(I think)
My discussion was in “What would you want more of, cogs or RAM?” starting on page 25.
I'm still looking to see if all 512 COG RAM location are indeed filled with HUB data during initialization.
This would be the easiest way to get code/data into the 'Shadow Registers'.
LewisD
st := 0 REPEAT i FROM st TO 1 ' executed twice (i = 0,1) st := 2 REPEAT i FROM st TO 1 'also executed twice (i = 2,1)
SPIN evaluates both limits in the beginning and decides whether to run the loop forward or backward. This is a great feature, but extremely surprising for experienced programmers.
Post Edited (deSilva) : 10/17/2007 5:39:23 PM GMT
Here is a trick that·allows you to·calculate·_CLKFREQ·within the CON block while·using _XINFREQ...
[b]CON[/b] [b]_CLKMODE[/b] = [b]XTAL1[/b] + [b]PLL16X[/b] [b]_XINFREQ[/b] = 5_000_000 clockfreq = (([b]_CLKMODE [/b]- [b]XTAL1[/b]) >> 6) * [b]_XINFREQ[/b]
Likewise, here is how you can calculate·_XINFREQ within the CON block while using _CLKFREQ...
[b]CON[/b] [b]_CLKMODE[/b] = [b]XTAL1[/b] + [b]PLL16X[/b] [b]_CLKFREQ[/b] = 80_000_000 Xinfreq = [b]_CLKFREQ[/b] / (([b]_CLKMODE [/b]- [b]XTAL1[/b]) >> 6)
A situation where this might be useful would be to setup timing constants within the CON block without resorting to using any variables.
[b][b]CON[/b] [b]_CLKMODE[/b] = [b]XTAL1[/b] + [b]PLL16X[/b] [b]_XINFREQ[/b] = 5_000_000 clockfreq = (([b]_CLKMODE [/b]- [b]XTAL1[/b]) >> 6) * [b]_XINFREQ[/b] [/b] _1uS = clockfreq / 1_000_000 'Divisor for 1 uS _10uS = clockfreq / 100_000 'Divisor for 10 uS _1mS = clockfreq / 1_000 'Divisor for 1 mS _1S = clockfreq / 1 'Divisor for 1 S
[b]PUB[/b] Pause_1uS(Period) '1 uS [b]waitcnt[/b](_1uS * Period + [b]cnt[/b])
[b]PUB[/b] Pause_10uS(Period) '10 uS [b]waitcnt[/b](_10uS * Period + [b]cnt[/b])
[b]PUB[/b] Pause_1mS(Period) '1 mS [b]waitcnt[/b](_1mS * Period + [b]cnt[/b])
[b]PUB[/b] Pause_1S(Period) '1 S [b]waitcnt[/b](_1S * Period + [b]cnt[/b])
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 10/20/2007 8:32:11 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter
tdswieter.com
One little spark of imagination is all it takes for an idea to explode
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The more I know, the more I know I don't know.· Is this what they call Wisdom?
The compiler remembers the size of a label in the DAT section according to the size identifier after this label.
Example:
DAT lo LONG 10,20,30 by BYTE "ABC",0
However a "standalone label" is always considered as a LONG:
Example:
by BYTE "ABC",0
is no longer correctly addressable by by[noparse][[/noparse]...]
There is a work around as follows
by BYTE BYTE "ABC",0
A size identifier without preset does not allocate space but assigns the correct attribute to the label only!
It most likely also aligns for WORD and LONG, but I have not checked it.
Post Edited (deSilva) : 10/27/2007 10:37:32 AM GMT
But, strangely enough, the compiler complains if you say "standaloneLabel.long[noparse][[/noparse]...]"
(See also http://forums.parallax.com/showthread.php?p=682286.)
But I already can assure you it is not BYTE a standalone label defaults to...
a. The last size identifier preceding a standalone label determines its "type".
b. If there is no preceding size identifier, a standalone label defaults to BYTE.
E.g.:
DAT long0 ' defaults to BYTE long $1234, $abcd PUB Start | ch tv.start( 24 ) tv.hex( long0, 8 ) ' 00000034 tv.out( 13 ) tv.hex( long0[noparse][[/noparse] 1], 8 ) ' 00000012 tv.out( 13 ) tv.hex( word0, 8 ) ' 20012000 tv.out( 13 ) tv.hex( word0[noparse][[/noparse] 1], 8 ) ' 13121110 tv.out( 13 ) tv.hex( byte0, 8 ) ' 00001110 tv.out( 13 ) tv.hex( byte0[noparse][[/noparse] 1], 8 ) ' 00001312 tv.out( 13 ) tv.hex( long1, 8 ) ' 00000078 tv.out( 13 ) tv.hex( long1[noparse][[/noparse] 1], 8 ) ' 00000056 tv.out( 13 ) DAT word0 ' LONG because of LONG in previous DAT section word $2000, $2001 byte0 ' WORD byte $10, $11, $12, $13 long1 ' BYTE long $12345678
Post Edited (mpark) : 10/27/2007 4:45:36 PM GMT
-Phil
The example uses this technique to Bit-Bang data to an I/O port with 50nS output transitions (20MHz).
Enjoy!
[b]CON[/b] [b]_clkmode[/b] = [b]xtal[/b]1 + [b]pll[/b]16x [b]_xinfreq[/b] = 5_000_000 OutputPin = 0 DataOut = %1000_1111_0000_1010_1010_1001_1001_1011 '<- Data to send [b]PUB[/b] ASM_FAST_BitBang_DEMO [b]cognew[/b](@FAST_BitBang,0) [b]DAT[/b] FAST_BitBang [b]org[/b] 0 [b]mov[/b] OutputPinMask, #1 '' Create Pin Mask for Output pin [b]shl[/b] OutputPinMask, #OutputPin [b]mov[/b] LoopCounts, #32 'Self Modifying Bit-Bang Code Loop [b]ror[/b] Buff, #1 [b]wc[/b] BitIndex [b]muxc[/b] Bit0, instr_mux [b]add[/b] BitIndex, dest_inc [b]djnz[/b] LoopCounts, #Loop 'This section of code self modifies the code below, 'so that each of the bits can transition in only 50nS. 'It does this by MUXing the "C" flag into the instruction 'location of the muxz commands below. 'By default, the way that the muxz is used, it will make 'output Pin LOW. When the instruction location is changed... '...from 011110 to 011111 (<-Notice only one bit difference) '...in this section of the code via the muxc instruction, 'muxz below effectively becomes a muxnz. Cool Huh!? [b]or[/b] [b]dira[/b], OutputPinMask 'Make Pin an Output [b]mov[/b] [b]outa[/b], #1 [b]nr[/b],[b]wz[/b] 'Clear Z flag for TRUE data ' [b]mov[/b] [b]outa[/b], #0 [b]nr[/b],[b]wz[/b] 'Set Z flag for INVERTED data The following MUX commands use the "Z" flag set above Bit0 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Self Modified Code to Bit Bang at 20MHz Bit1 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit2 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW The lines above that read... Bit3 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit4 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW muxc {Bit#}, instr_mux Bit5 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit6 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW ...self modify the instruction bits Bit7 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW of the lines that read... Bit8 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit9 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW {Bit#} muxz outa, OutputPinMask Bit10 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit11 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW ...so that when the BIT in Buff is Bit12 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW a "1", the lines that did read... Bit13 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit14 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW {Bit#} muxz outa, OutputPinMask Bit15 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit16 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW ...now function as if they read... Bit17 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit18 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW {Bit#} muxnz outa, OutputPinMask Bit19 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit20 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW ...with 'muxz' the output pin is made Bit21 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW LOW ... with 'muxnz' the output pin Bit22 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW is made HIGH. This is so that a pin Bit23 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW can transition in 4 Clocks or 50nS rather Bit24 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW than 8 Clocks or 100nS. This makes it twice Bit25 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW as fast. Bit26 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit27 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit28 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit29 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit30 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW Bit31 [b]muxz[/b] [b]outa[/b], OutputPinMask 'Default LOW instr_mux [b]long[/b] $0400_0000 dest_inc [b]long[/b] $0000_0200 Buff [b]long[/b] DataOut OutputPinMask [b]long[/b] 0 LoopCounts [b]long[/b] 0
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 11/20/2007 6:26:56 PM GMT