#Slot 1
SerTxd( "In slot 1", CR, LF )
Pause 1000
SerTxd( "Pass control to slot 0 ...", CR, LF )
Run 0
#Slot 0
SerTxd( "In slot 0", CR, LF )
Pause 1000
SerTxd( "Pass control to slot 1 ...", CR, LF )
Run 1
Yes--this is to my mind exactly the most useful power of slots. It does take some organizing to work with the "always start from the beginning" aspect--especially with regard to slot 0. For additional slots, I begin (in slot 0) by setting a variable (variables are preserved between slots), and then (at the beginning of SLOT n) use a SELECT to jump to the desired routine:Hmmm, OK, so besides the memory advantage of using slots, does this mean the other advantage is that very LONG code could be restructured in a way that we can break the code up into 4 slots (40X2) instead of running out of code space in slot 0.
select slot1Routine
case slot1_displaySlotNo gosub displaySlotNo
case slot1_printTemplate gosub printTemplate
case slot1_printData gosub printData
case slot1_printDataAddresses gosub printDataAddresses
case slot1_PrintDiagnostics ' print diagnostics
case slot1_updateData
gosub setOutputs
gosub updateData
case slot1_getChartAddress gosub getChartAddress
else gosub displaySlotNo
endselect
#include "c:\dl\picaxe\20htmlServer_includes.bas"
#slot 1
PSEUDO-ROM UTILITIES Ver. 2.01a
Modified for 32K NVM
0_ Install a ROM
1_ Remove a ROM
2_ Insert a ROM
3_ Clear ROM
4_ Partition ROM.... F800H
5_ Reset Options
6_ Hex Loader
7_ Hex Dump
8_ Display Memory
9_ Quit
Select 0..9 NVM Protect ON
Choosing option 5 allows selecting baud, Boot ROM, etc.
0_ Exit
1_ PROG1..(Save Baud Rate)
2_ PROG2..(Save Baud Rate RUN ROM1 on Reset)
3_ PROG3..(Save Baud Rate/MTOP)
4_ PROG4..(Save Baud Rate/MTOP RUN ROM1 on Reset)
5_ PROG5..(Save Baud Rate/MTOP)
If (on Reset) XBY(5FH)=0A5H None of Memory is Cleared.
If (on Reset) XBY(5EH)=034H RUN Prog. in RAM (Trap Mode)
6_ PROG6..(Same Options as PROG5) Plus Options Below
MUST put Assembly Language Prog. at 4039H
3 Options Exist on Return from 4039H
1- If Carry = 0 Enter Auto-Baud Routine
2- If Carry = 1 and A Reg.(bit 0) = 0 Use Saved Baud Rate
3- If Carry = 1 and A Reg.(bit 0) = 1 then RUN ROM1
7_ Select Boot Rom
8_ Clear Reset Options
Select 0...8
;# what boot manager does on startup...
10 ON X-2 GOTO 22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42
22 RROM2
23 RROM3
24 RROM4
25 RROM5
26 RROM6
27 RROM7
28 RROM8
29 RROM9
30 RROM10
31 RROM11
32 RROM12
33 RROM13
34 RROM14
35 RROM15
36 RROM16
37 RROM17
38 RROM18
39 RROM19
40 RROM20
41 RROM21
42 RROM22
etc...
# EEPROM Board Config Registers
# 8000h = after programming by PROG/FPROG (PROG1 = 31h...PROG6 = 36h etc.)
# 8001h = baud rate hi-byte RCAP2H (used by PROG1/FPROG1...6)
# 8002h = baud rate lo-byte RCAP2L (used by PROG1/FPROG1...6)
# 8003h = mtop hi-byte (used by PROG3/FPROG3...6)
# 8004h = mtop lo-byte (used by PROG3/FPROG3...6)
# Since 8005h..800Fh (reserved for MCS-BASIC although not used)
# Use these locations for other stuff (e.g. 8005h = Remote #, 8006h = sware version, etc.)
# 8005h = Assigned Remote # (allows host to know what board it’s working with)
# Remote 0 should always be the host, 255 means unassigned.
# 8006h = software version
# 8007h = hardware version
# 8008h = bindcode (hi-byte) \ i.e. a "password" that may be used
# 8009h = bindcode (lo-byte) / to allow access 0...65535
# 800Ah = ?
# 800Bh = ?
# 800Ch = NVM partition (BASIC/Assembly) e.g. A0h = 0A000h, F8h = 0F800h, etc.
# 800Dh = Xtal Value in MHZ e.g. 242 would be 24.2 MHz etc. (if 0 or 255 use 11.0592 MHz)
# 800Eh = ROM to run on Reset (i.e. Boot Rom)
# 800Fh = Reserved for checking if NVM is Open or Closed
# 8010h = start of ROM1
Doubling chip memory is the best reason to use PE6 yet.To have access to program the second memory slot In M2 parts also requires the use of PE6.
Hi @lbenson,You may need to include some routines in both (all) slots.Code:#include "c:\dl\picaxe\20htmlServer_includes.bas" #slot 1
In slot 0, in the initialization code, I set a flag; upon entering or re-entering slot 0, I check that flag (and perhaps other flags) to determine where to jump to to resume execution.
OLDmarty, anIs the included file (whatever we choose to name it, e.g. "included.bas") simply just full of all the symbol definitions and/or anything else that is needed to be shared across all 2 (or 4) slots???
Do we absolutely have to define (for example) "symbol dog = b0" into our "included.bas" file, instead of just defining "symbol dog = b0" into each of our slot codes?
include
file is just a way to move code out of the programming environment to make writing code easier. You don't have to scroll through it all the time. When you are writing code for slots
, the advantage is that the code for each slot has to have the same exact symbol
definitions because your variables are shared between all slots
. It is very convenient not to have to go to each slot
code to adjust/add a variable name.It is as Tex says--an include file is useful when you have slots so that all your symbol and constant definitions and other shared code is consistent between slots. There's no rule that says you have to do this, but if your program is big enough to require slots to fit in the memory, then it is probable that using an include file will save you some hair-pulling.Hi @@lbenson,
Is there anything 'different' we need to know about the contents of your "20htmlServer_includes.bas"?
Basically, yes.OLDmarty said:Is the included file (whatever we choose to name it, e.g. "included.bas") simply just full of all the symbol definitions and/or anything else that is needed to be shared across all 2 (or 4) slots???
You can define symbols identically (or differently) in each slot separately without an include file.OLDmarty said:Do we absolutely have to define (for example) "symbol dog = b0" into our "included.bas" file, instead of just defining "symbol dog = b0" into each of our slot codes?
Byte and word variables (e.g., b0, w7) are transparent (available in all slots) and refer to the same values. Symbols referring to those variables must be defined in each slot so the PE editor/interpreter knows which byte and word variable tokens to substitute for the symbols when the tokenized code is downloaded to the picaxe.OLDmarty said:Are you saying that the slots may not have variables that are transparent to each other unless the "included.bas" exists with all the variables defined in that 1 file?
Yep, making multiple assignments to a "hard" register can lead to a world of confusion.Please note that if you use different names for the same variable in the same or different slots it is VERY easy to get mixed up and have one part of your program mess up other parts inadvertently...
; simple EXAMPLE of Reusable Code Module:
; word.toAscii_Convert -- (v1.00a by M. Ballew 04-06-2019)
; convert XW to ascii characters
;
; Status: (works ok)
;
; Revisions:
; none
;
; Arguments:
; XW
;
; Results:
; XW -> tenthousands thousands hundreds tens ones (ascii chars)
; (XW not altered)
;
; Example:
; gosub word.toAscii_Convert ; XW -> tenthousands thousands hundreds tens ones (ascii chars)
;
word.toAscii_Convert:
bintoascii XW, tenthousands, thousands, hundreds, tens, ones
return
That is why you will see the following at the beginning of code that I post:
;---------------------- VERY IMPORTANT ------------------------------------
; NEED TO ASSIGN variable usage as follows:
; w0 = b0 (bit0...bit7) general-purpose bit registers
; b1 (bit8...bit15) general-purpose bit registers
; w1 = b2 (bit16...bit23) general-purpose bit registers
; b3 (bit24...bit31) general-purpose bit registers
;
; NOTE: always use the general-purpose alias registers inside procs (except linearConversion)
; w2 = b4 b5 general-purpose word/byte registers (XW XL XH)
; w3 = b6 b7 general-purpose word/byte registers (YW YL YH)
; w4 = b8 b9 general-purpose word/byte registers (ZW ZL ZH)
; w5 = b10 b11 general-purpose word/byte registers (UW UL UH)
; w6 = b12 b13 general-purpose word/byte registers (VW VL VH)
; w7 = b14 b15 general-purpose word/byte registers (WW WL WH)
; the U V W X Y Z alias registers are used to avoid hard register assignments
; since remembering the 2 bytes comprising a word can be confusing (e.g. w2 is b4b5),
; it is easier to know what byte registers are part of what word registers as follows:
; e.g. pseudo-variable (i.e. alias) X can be any of w0...w13
; albeit w0 & w1 are usually reserved as both are bit addressable
; XW = variable X word value, XL = lo-byte of variable X, XH = hi-byte of variable X
symbol XW = w2 ; alias register for w2 word value
symbol XL = b4 ; alias register for w2 lo-byte value
symbol XH = b5 ; alias register for w2 hi-byte value
symbol YW = w3 ; alias register for w3 word value
symbol YL = b6 ; alias register for w3 lo-byte value
symbol YH = b7 ; alias register for w3 hi-byte value
symbol ZW = w4 ; alias register for w4 word value
symbol ZL = b8 ; alias register for w4 lo-byte value
symbol ZH = b9 ; alias register for w4 hi-byte value
symbol UW = w5 ; alias register for w5 word value
symbol UL = b10 ; alias register for w5 lo-byte value
symbol UH = b11 ; alias register for w5 hi-byte value
symbol VW = w6 ; alias register for w6 word value
symbol VL = b12 ; alias register for w6 lo-byte value
symbol VH = b13 ; alias register for w6 hi-byte value
symbol WW = w7 ; alias register for w7 word value
symbol WL = b14 ; alias register for w7 lo-byte value
symbol WH = b15 ; alias register for w7 hi-byte value
; symbol w8 = ?? ; unassigned (use as alias regs if needed)
; Following Reserved for Doing Scale Conversions :
symbol scale1Lo = w9 ; place to put "from" scale bottom
symbol outValue = w9 ; place to put output value (result of conversion)
symbol outValueLo = b18 ; lo-byte of w9 output value (result of conversion)
symbol outValueHi = b19 ; hi-byte of w9 output value (result of conversion)
symbol scale1Hi = w10 ; place to put "from" scale top
symbol span1 = w10 ; place to put "from" scale span
symbol roundoff = w10 ; place to put value to be rounded off
symbol scale2Lo = w11 ; place to put "to" scale bottom
symbol remainder = w11 ; place to put remainder of conversion
symbol scale2Hi = w12 ; place to put "to" scale top
symbol span2 = w12 ; place to put "to" scale span
symbol scale1Val = w13 ; place to put input value (value to be converted)
; Note: following regs (w10 w11 w12 w13) also used by linearConversion proc
symbol tenmillions = b20 ; holds ascii 10000000s value (0..9) (w10 = b20 b21)
symbol millions = b21 ; holds ascii 1000000s value (0..9)
symbol hunthousands = b22 ; holds ascii 100000s value (0..9) (w11 = b22 b23)
symbol tenthousands = b23 ; holds ascii 10000s value (0..9)
symbol thousands = b24 ; holds ascii 1000s value (0..9) (w12 = b24 b25)
symbol hundreds = b25 ; holds ascii 100s value (0..9)
symbol tens = b26 ; holds ascii 10s value (0..9) (w13 = b26 b27)
symbol ones = b27 ; holds ascii 1s value (0..9)
#Picaxe 18M2
#Terminal 4800
#No_Data
Symbol counter = w5
#IfDef SLOT_1
#Slot 1
#Else
Main:
Pause 1000
counter = counter + 1
Run 1
#EndIf
#Define SLOT_1
#Include "Slot0.bas"
SerTxd( "Counter = ", #counter, CR, LF )
Run 0
#Picaxe 18M2
#Terminal 4800
#No_Data
Symbol counter = w5
#IfDef SLOT_1
#Slot 1
#Else
Main:
Pause 1000
counter = counter + 1
b0 = 0 : Gosub DebugDump
Run 1
#EndIf
CommonSubroutines:
Goto EndofCommonSubroutines
DebugDump:
SerTxd("In DebugDump. Called from Slot ", #b0, CR, LF )
Return
EndofCommonSubroutines:
#Define SLOT_1
#Include "Slot0.bas"
b0 = 1 : Gosub DebugDump
SerTxd( "Counter = ", #counter, CR, LF )
Run 0