Quote Originally Posted by HenrikOlsson View Post
Hi,
Art,
If that interpreted BASIC, whichever it is, really works like that it kind of sucks - big time IMO.
As for the rest, you're now talking about RAM and not program memory.

/Henrik.

The second part is in relation to the link posted (keeping vars in BANK0 - avoiding switch statements).

I will try to explain why it is important to put code you want to run fast at the beginning of your PBP program,
even though I was incorrect as to one of the reasons why, there are more, and PBP actually does this in the
compiled assembler program (with it's own function calls, not yours) whether you like it or not.

You want to keep most called functions (PBP routines) in the first 2K code space to avoid page switching.
You also want to keep most used variables in Bank0 to avoid bank switching (for RAM).

Say you fill up the first 2K page with code, and run into the second code page,
then introduce a serin or serout command in the second code page.
PBP doesn't put the serin command where you wrote it.
Every PBP macro command such as serial is placed at the beginning of the generated
assembler code, which kicks some of your your PBP code out of the first 2K code space.
What is placed where you wrote the serial command is a series of gosubs that pass
individual bytes to the assembler routine which has been placed at the beginning of the asm source.

You wil notice that if you use a second serial command, your code size doesn't massively increase again
because the original asm routine that was inserted by the first serial command is reused.

When you use a serin, and serout command, this is the decompiled assembler that is placed
at the beginning of your compiled code to deal with it:
Code:
SerialIN							;receive serial byte with pre-determined timeout
  movf		R6		,W				;move timeout delay to temp
  movwf		R0						;
  movf		R15		,W				;
  movwf		R9						;
  movlw		0x01						;
  movwf		R1						;set inside loop counter
  clrf		R10						;
serial_loop							;
  clrwdt							;keep watchdog timer clear
  call		SerinX						;get one bit
  btfss		status		,C				;wait for start bit
  goto		serinstart					;
  decfsz	R1		,F				;
  goto		serial_loop					;
  movlw		0xFF						;
  addwf		R10		,F				;
  btfsc		status		,C				;
  goto		serial_loop					;
  addwf		R0		,F				;
  btfss		status		,C				;
  addwf		R9		,F				;
  btfss		status		,C				;
  goto		DoneX						;time out
  movlw		0x32						;
  movwf		R1						;reset inside loop counter
  clrw								;
  movwf		R10						;
  goto		serial_loop					;
SerialIN_notimeout						;
  clrwdt							;receive byte serialy with no timeout
  call		SerinX						;get one bit
  btfsc		status		,C				;wait for start bit
  goto		SerialIN_notimeout				;
serinstart							;
  call		serialdelay					;wait 1/4 bit time
  clrf		R4						;zero parity accumulator
  movlw		0x08						;number of bits in one byte
  movwf		R10						;
serpar								;
  call		seroutdelay					;wait bit time
  call		SerinX						;get one bit
  btfsc		status		,C				;accumulate parity
  incf		R4		,F				;
  btfss		R14		,05				;if no parity...
  clrf		R4						;...keep it even
  rrf		R1		,F				;move bit into byte
  decfsz	R10		,F				;check for more bits
  goto		serpar						;
  btfsc		R14		,05				;if parity...
  bcf		R1		,07				;...clear top bit of result
  call		seroutdelay					;delay to stop bit
  bsf		status		,C				;carry shifts in clear
  movf		R1		,W				;get char to W
  return							;
SerinX								;
  movf		RR2		,W				;receive one bit for serial in
  movwf		fsr						;
  movf		RR1		,W				;
  bsf		fsr		,07				;
  iorwf		indf		,F				;
  bcf		fsr		,07				;
  andwf		indf		,W				;
  btfsc		R14		,06				;
  xorwf		RR1		,W				;
  addlw		0xFF						;
  return							;
SerialIN_skipbyte						;
  movf		R13		,W				;ignore received byte for serial in
  bsf		status		,C				;
  btfsc		status		,Z				;
  goto		DoneX						;
  call		skipX						;
  btfss		status		,C				;
  return							;
  decf		R13		,F				;
  goto		SerialIN_skipbyte				;

serialOUT							;transmit byte serialy from port pin
  movwf		R3						;save byte to send
  movf		RR2		,W				;get port to fsr
  movwf		fsr						;
  movlw		0x80						;zero parity accumulator (preserve blanking)
  andwf		RM2		,F				;
  movlw		0x08						;1 start bit + 7 data bits
  movwf		R12						;
  bcf		status		,C				;start bit low
seroutloop							;
  btfsc		status		,C				;accumulate parity bits
  incf		RM2		,F				;
  call		seroutbit					;send a bit and delay bit time
  rrf		R3		,F				;move to next bit
  decfsz	R12		,F				;do next bit, if any
  goto		seroutloop					;
  nop								;
  btfsc		R14		,05				;send parity
  rrf		RM2		,W				;get parity to carry
  call		seroutbit					;send parity or last bit and delay bit time
  call		Done						;
  bsf		status		,C				;stop bit high
  call		seroutbit					;send stop bit and delay bit time
  movf		R16		,W				;do pacing
  movwf		R10						;
  movf		R7		,W 				;
  goto		DelayX						;
seroutbit							;
  bcf		fsr		,07				;make sure we're pointing to the port
  btfss		R14		,07				;check for TRIS mode
  goto		seroutnorm					;handle normal mode
  movf		indf		,W				;get port data
  iorwf		RR1		,W				;set bit on
  btfss		R14		,06				;bit matches invert mode
  xorwf		RR1		,W				;set bit off
  movwf		indf						;write it out
  bsf		fsr		,07				;point fsr to port tris
  movf		indf		,W				;get tris data
  iorwf		RR1		,W				;make bit an input
  btfss		status		,C				;bit direction matches bit
  xorwf		RR1		,W				;make bit an output
  movwf		indf						;write it out
  goto		seroutdelay					;wait remainder of bit time
seroutnorm							;
  movf		indf		,W				;get port data
  iorwf		RR1		,W				;set bit on
  btfss		status		,C				;skip if bit should be on
  xorwf		RR1		,W				;set bit off
  btfsc		R14		,06				;invert if 'N' mode
  xorwf		RR1		,W				;flip for invert
  movwf		indf						;write it out
  bsf		fsr		,07				;point fsr to port tris
  comf		RR1		,W				;get complemented bit mask to W
  andwf		indf		,F				;clear tris bit to set output
  goto		seroutdelay					;wait remainder of bit time
serialdelay							;
  bsf		RM2		,06				;
seroutdelay							;
  movf		R14		,W				;get high baud byte
  andlw		0x1F						;mask to our bits
  addlw		0xFF						;fix baud
  movwf		R9						;save it
  movf		R5		,W				;get low baud byte
  addlw		0xF5						;
  btfsc		status		,C				;bump up high byte if low overflowed
  incf		R9		,F				;
  btfss		RM2		,06				;
  goto		pauseUSL					;
  bcf		RM2		,06				;clear short delay mark
  movwf		R0						;save low part
  movlw		0x02						;divide time by 4
  call		shiftR						;
  goto		pauseUSL					;do 1/4 delay
That's quite a lot of code asking to be placed in the first 2K code space (and kicking your code out).
The serial always appears to be placed first, then SOUND, then EEPROM, then PAUSE.

If you use any PAUSE command, this is inserted:
Code:
Delay
  clrf		R10						;delay 1
DelayX								;
  movwf		R1						;delay 2
DelayXX								;
  movlw		0xFF						;
  addwf		R1		,F				;
  btfss		status		,C				;
  addwf		R10		,F				;
  btfss		status		,C				;
  goto		DoneX						;
  movlw		0x03						;
  movwf		R9						;
  movlw		0xDF						;
  call		pauseUSL					;
  goto		DelayXX						;
  clrf		R9						;
pauseUSL							;
  addlw		0xE8						;
  movwf		R0						;
  comf		R9		,F				;
  movlw		0xFC						;
  btfss		status		,C				;
  goto		XpauseUSL					;
pauseX								;
  addwf		R0		,F				;
  btfsc		status		,C				;
  goto		pauseX						;
XpauseUSL							;
  addwf		R0		,F				;
  clrwdt							;
  incfsz	R9		,F				;
  goto		pauseX						;
  btfsc		R0		,00				;
  goto		pausedoneX					;
pausedoneX							;
  btfss		R0		,01				;
  goto		pausedone					;
  goto		Done						;
or on chip-EEPROM Read/Write:

Code:
EEPROMread							;read byte from on-chip EEPROM
  bsf		status		,rp0				;for bank 1
  movwf		EEADR						;set the EEPROM address
  bsf		EECON1		,0x0				;EECON1 in bank 3
  movf		EEDATA		,W				;read from data memory
  goto		DoneX						;done

EEPROMwrite							;write byte to on-chip EEPROM
  bsf		status		,rp0				;for EE in bank 1
  movwf		EEDATA						;set the EEPROM data
  bsf		EECON1		,02				;
  movlw		0x55						;unlock the door
  movwf		EECON2						;
  movlw		0xAA						;
  movwf		EECON2						;
  bsf		EECON1		,01				;do the write
writeloop							;
  btfsc		EECON1		,01				;wait for the write to complete
  goto		writeloop					;
  bcf		EECON1		,02				;lock up when we're done
  goto		DoneX						;
So bottom line is if you are using any of these, insert them in your code once, straight away
before bothering with timing, or determining which bank you want your variables to be in.
Then you can add additional identical commands without worrying about anything else being added.
All of these commands reuse the code from the first time they were used in a PBP program.
Cheers, Art.