Atom Pro IDE 8.0.1.8 bug list

Big news! Nathan from Basic Micro has been working on the Atom Pro IDE. 8)

www.basicmicro.com/downloads/software/B … p_8018.exe

Fixed from 8.0.1.7
Bug in COS when used with negative numbers.
Bug in NAP.

New features
He’s implemented most of the experimental efficiency changes in an easier manner so a lot of commands should run significantly faster. Also code space should on average be a bit smaller. He also implemented an ASM{} block command. Any asm code can be placed between the {} braces even macro definitions and assembler directives.

The efficiency changes also remove the need to periodically disable interrupts. It’s possible some glitching could have been caused by this. This is now resolved.

He also wanted me to mention that if you are using interrupts while sleeping or napping, each time an interrupt trips one of the sleep/nap loops it will exit immediately. This means you can lose up to 2ms from the delay of the sleep/nap each time an int triggers while sleeping/napping. That applies to hservo interrupts as well. So when doing hservo or any other interrupt heavy code sleep and nap are going to give odd results.

Sounds Great!

I downloaded it and will try it out!. I sure wish there was some form of readme file that describes all of the differences, from release to release.

Here are a few first impressions and wish list items.

  1. Still have Vista problem, where Vista will complain every time you run the IDE. I am not defending Vista here, but a lot of people will probably be running it…

  2. The manual still looks like the one from 8.0.0.0…

  3. Not sure which to choose AtomPro28 or AtomPro28P. Detect finds AtomPro28 so that is what I choose…

Which EXP features were added? Was the HTIMER stuff added that was in the earlier EXP versions?

Thanks
Kurt

  1. I’ll have to get my dev environment on Vista before I can fix this.

  2. The manual is still the same old one. We such at writing manuals. We’ve got a new writer working on stuff. Manual rewrites will be coming but for now we are starting with some app notes to break him in.

  3. AtomPro28 for the current original AtomPro28. The AtomPro28P is a new product we haven’t released yet. It’s a 20mhz version of the AtomPro28. If you choose the 28P the compiler will compile for a 20mhz processor so your 16mhz AtomPro will run slower than expected in some situations if you choose wrong. I recommend you use the “Auto” option if you are not sure which you have.

AtomPro 24 = 24pin 16mhz H8-3694 processor
AtomPro 24P = 24pin 20mhz H8-3694 processor
AtomPro 28 = 28pin 16mhz H8-3694 processor
AtomPro 28P = 28pin 20mhz H8-3694 processor

AtomPro40 and AtomPro40P is still in flux. We’ve had a hard time finding lead frames to fit an H8-3687 on the 40pin module but I think we may finally have it. So for now ignore these part numbers

AtomPro DIP is for backwards compatibility with some very old boards and the old DIP interpreter chips which are all discontinued but still supported.

AtomPro SMT is for 16mhz H8-3694 surface mount interpreter chips
AtomPro-P SMT is for 20mhz H8-3694 surface mount interpreter chips
AtomPro-PE SMT is for 20mhz H8-3687 surface mount interpreter chips

All Interpreter chips come in 1 and 2 wire communications versions.

The EXP features added is just the efficiency change. All the new H commands are still EXP and not in this release. This release is primarily to get everyone upto date with the latest fixes and get the improved token handler(which gives the speed increase and reduces code size slightly) along with the new ASM{} block support which really makes coding inline assembly very easy(you can do anything in an ASM{} that you can do in straight assembly). Same rules as other inline assembly code still applies when switching from basic to asm and back to basic.

Nathan, thanks for the update.

Does the new version now have the defines for the 3694 instead of the 3664 for the AtomPro28?

Thanks
Kurt

It has both. The differences from the 3664 to 3694 are mostly in the I2C hardware registers but their memory locations don’t over lap so there shouldn’t be a problem. The enable/disable commands fail but I’m in the process of fixing them(they fail because I renamed the 3664 hardware i2c registers so the names wouldn’t conflict with the 3694 registers and the enable/disable commands reference one of those registers). I should have that fixed over the long weekend. Also I’m adding specific basic interrupt handlers for I2C hardware interrupts on the 3694. 3664 only had one, 3694 has five. Also I found a bug tonight that would enable global interrupts always in all releases upto and including the 8018. I’ve fixed it, so in the next release if you are using ONASMINTERRUPT handlers you need to use the enable command which enables the gloabl interrupt flag while enabling the specified interrupt flag or manually enable the global interrupt flag(its in the CCR register and can only be set or cleared using the special CCR specific asm commands). In previous releases the CCR interrupt enable flag was always being set. Since the individual interrupt handlers were still being set or cleared correctly it was never noticable before but I found an instance today that finally showed the problem.

I’m uploading a small update to 8018. No change in the name or version number. If you downloaded 8018 before the time and date on this post you need to redownload and install this release.

  1. Fixed an invalid label in the enable command when used with the IICINT. Was referencing ICCR which is now called ICCR_OLD. The 3664 I2C registers all had the _OLD added to their names so they won’t conflict with the 3694 I2C registers.

  2. Added new interrupt handlers for I2C hardware on 3694. used just like any of the other basic interrupts with ONINTERRUPT.
    IICINT_TDRE
    IICINT_TEND
    IICINT_RDRF
    IICINT_NACKF
    IICINT_STOP

Note that if using a 3664 based module only ONINTERRUPT IICINT is available because it’s i2c hardware does not support the extended interrupts for I2C. Also if using ONASMINTERRUPT use IICINT for both 3664 and 3694 and as usual with ASM interrupts you have to handle all the flag processing.

  1. Fixed so global interrupts are NOT enabled by default(this is the I flag of the CCR register for those that care). To enable/disable global interrupts you MUST use enable/disable without arguments.

  2. Added checks for the specific interrupt being enabled on all multi flag interrupts in Basic. For example when using the WKP interrupts all 6 WKP pins interrupt through the same single interrupt so if WKP0 was not currently enabled but was defined(eg had an ONINTERRUPT handler) but WKP1 was enabled and both WKP0 and WKP1 had been flagged because of their pin states changed then when the interrupt triggered instead of WKP1s handler being called WKP0s handler would be called even though it was currently disabled. No a check is made to make sure the interrupt is in fact enabled before processing the handler.

I thought I would try it out. One problem I am having is that the IDE does not install any documention for the assembler or compilers. However since I have an AVR setup (WINAVR) it does have some documentation. So I am assuming the assembler has the format as described in those documents. Things like: .macro .endm.

The first problem I have run into is that I am not sure about the constraints on using the ASM{} code. My first attempt had the ASM{ followed by several lines of assmbly language then a line with } It was followed by Basic program lines. The code alway appears to generate an error message on the next line after the }. It does appear to work if the } is the last line of code…

Kurt

I found that problem yesterady.(after the } in an ASM{} block an error is thrown in most situations). I’ve fixed it and will upload a new version tomorrow. The assembler used is the GNU AS assembler. The macro syntax is:

.macro label arguments ...asm code... .endm

Thanks,

I also found the syntax of the macro as part of the binutil documentation that was downloaded as part of the WINAVR download (GCC for AVR). It may be a different version, but the document does have a section for the H8, so should be reasonably close.

I started playing with maybe writing a version of the PS2 input code in assembly language to try to make use of the ACK line. My first version started off with coding specifically for the IO lines I was using. It started out looking like:

[code]ps2Input:

' Ok First lets initialize all of the underlying IO lines for the PS2 controller.
' BUGBUG:: Should use PORTTABLE or equivlent to make it easier to change which IO lines
' we are using...

mov.l	#PS2DAT, er0		; lets try mapping R12 (DAT) through port table
shll	er0
mov.w	@(_PORTTABLE, er0), r2
mov.b	r2h,r3l
mov.b	#0xff,r2h
bclr	r3l,@er2

bclr.b	#4,@PCR8		; make sure DAT is input
bset.b	#5,@PCR8		; set CMD to output
bset.b	#6,@PCR8		; SET SEL to output
bset.b	#7,@PCR8		; set CLK to output

bclr.b	#0,@PCR8		; set Ack to input P80
bclr.b	#5,@PCR1		; 	note BAP P8 has two 3694 pins connected P80 and P15.  P15 has pull-up
bset.b	#5,@PUCR1		; 	So try to use it pull up the ACK line without having to add external pull-up

; now lets try a simple query
mov.l	#PS2QCMD,er0	; point to the standard output command table
mov.b	#2, r2l			; We want to output 2 bytes
mov.l	#DUALSHOCK, er1 ; point to where we want the output to go
mov.b	#9, r2h			; We want to read in 9 bytes

' Now lets set the select to low
bclr.b	#6,@PDR8		; Set SEL to low

' now lets 

_PS2_SETUP_NEXT_BYTE:
or.b r2l, r2l ; check to see if we have any more bytes to output
bne #_PS2_YES_MORE:8
xor r3l, r3l ; no more
bra #_PS2_C1:8
_PS2_YES_MORE:
mov.b @er0+, r3l ; get the next byte from the input string.
dec.b r2l ; decrement our count

_PS2_C1:
xor.b r3h, r3h ; setup for the next byte
mov.b #8, r4l ; We need to do 8 bits.

_PS2_BIT_LOOP:
shlr.b r3l ; ok shift the low bit into the carry bit
bst #5,@PDR8 ; Set CMD bit
bclr.b #7,@PDR8 ; clear the clock
nop ; some delay for the clock
nop
nop
nop
nop
nop
nop
nop
bset.b #7,@PDR8 ; now set the clock high again
bld.b #4,@PDR8 ; now lets see what is in the DAT bit
rotxr.b r3h ; and rotate it into our input byte we are building
dec.b r4l ; decrement our loop counter
bne #_PS2_BIT_LOOP:8 ; and go to the next bit if we have not done all of them

mov.b	r3h, @er1		; save away the byte that we retrieved.
inc.l	#1, er1			; increment the address.

xor.w	r3,r3			; lets have some form of counter so we can time out of waiting for ACK to happen...

_PS2_WAIT_FOR_ACK:
bld.b #0,@PDR8 ; look at the ACK
bcc #_PS2_HAVE_ACK:8
dec.w #1,r3 ; dont have ack, but lets try up to 65536 times until we give up
bne #_PS2_WAIT_FOR_ACK:8 ; [/code]
But since I now have macros available, I thougt I would try using them and maybe write the code to make it easier to use other IO pins. (slower and bigger…) So the first attempt is now looking like:

[code]s2Input:

asm{
; This macro maps a BAP IO port to the DATA bit port address plus bit number
.macro MAP_PRO_PIN_TO_PORT_PIN pin
mov.l #\pin, er0
shll er0
mov.w @(_PORTTABLE, er0), r1
mov.b r1h,r2l
xor.w e1,e1
mov.b #0xff,r1h
.endm
.macro SET_PIN_AS_INPUT pin
MAP_PRO_PIN_TO_PORT_PIN \pin
add.b #0x10:8, r1l ; map from the data register to the control register
bclr r2l,@er1
.endm

.macro SET_PIN_AS_OUTPUT pin
MAP_PRO_PIN_TO_PORT_PIN \pin
add.b #0x10:8, r1l ; map from the data register to the control register
bset r2l,@er1
.endm

.macro SET_PIN_HIGH pin
MAP_PRO_PIN_TO_PORT_PIN \pin
bset r2l,@er1
.endm

.macro SET_PIN_LOW pin
MAP_PRO_PIN_TO_PORT_PIN \pin
bclr r2l,@er1
.endm

SET_PIN_AS_INPUT PS2DAT
SET_PIN_AS_OUTPUT PS2CMD
SET_PIN_AS_OUTPUT PS2SEL
SET_PIN_AS_OUTPUT PS2CLK
SET_PIN_AS_INPUT PS2ACK

; BUGBUG - Hack to know that our ACK pin as also on P15 which has pull-up...	
bclr.b	#5,@PCR1		; 	note BAP P8 has two 3694 pins connected P80 and P15.  P15 has pull-up
bset.b	#5,@PUCR1		; 	So try to use it pull up the ACK line without having to add external pull-up

; now lets try a simple query
mov.l	#PS2QCMD,er4	; point to the standard output command table
mov.b	#2, r6l			; We want to output 2 bytes
mov.l	#DUALSHOCK, er5 ; point to where we want the output to go
mov.b	#9, r6h			; We want to read in 9 bytes

; Now lets set the select to low
SET_PIN_LOW PS2SEL

; now lets 

_PS2_SETUP_NEXT_BYTE:
or.b r6l, r6l ; check to see if we have any more bytes to output
bne #_PS2_YES_MORE:8
xor r3l, r3l ; no more
bra #_PS2_C1:8
_PS2_YES_MORE:
mov.b @er4+, r3l ; get the next byte from the input string.
dec.b r6l ; decrement our count

_PS2_C1:
xor.b r3h, r3h ; setup for the next byte
mov.w #8, e3 ; We need to do 8 bits.

_PS2_BIT_LOOP:

; map the CMD pin to the right port/pin and then store the next bit into it.
MAP_PRO_PIN_TO_PORT_PIN PS2CMD
shlr.b	r3l				; ok shift the low bit into the carry bit
bcc		#_PS2_SET_CMD_LOW:8
bset	r2l,@er1		; Ok so save the bit value into the CMD
bra		#_PS2_SET_CLK_LOW:8

_PS2_SET_CMD_LOW:
bclr r2l,@er1 ;

_PS2_SET_CLK_LOW:
SET_PIN_LOW PS2CLK
nop ; some delay for the clock
nop
nop
nop
nop
nop
nop
nop
SET_PIN_HIGH PS2CLK ; set it back high, could have used old mapping…

MAP_PRO_PIN_TO_PORT_PIN PS2DAT
shlr	r3h				; rotate the old data down
btst	r2l,@er1		; get the status of the DAT pin
beq		_PS2_DAT_LOW	; the dat is low
or.b	#0x80,r3h		; set the high bit...

_PS2_DAT_LOW:
dec.w #1,e3 ; decrement our loop counter
bne #_PS2_BIT_LOOP:16 ; and go to the next bit if we have not done all of them

mov.b	r3h, @er5		; save away the byte that we retrieved.
inc.l	#1, er5			; increment the address.

xor.w	e3,e3			; lets have some form of counter so we can time out of waiting for ACK to happen...
MAP_PRO_PIN_TO_PORT_PIN PS2ACK

_PS2_WAIT_FOR_ACK:
btst r2l,@er1 ; get the status of the ACK
beq #_PS2_HAVE_ACK:8
dec.w #1,e3 ; dont have ack, but lets try up to 65536 times until we give up
bne #_PS2_WAIT_FOR_ACK:8 ;

_PS2_HAVE_ACK:
dec.b r6h ; decrement how many bytes we are going to input and if not zero go to process next byte
bne _PS2_SETUP_NEXT_BYTE:16

SET_PIN_HIGH PS2SEL		; set the select back h[/code]

Note this is not complete yet nor have I debugged it to see if any of it works. But it is fun… Doing it with mapping the IO ports I found that some of the instructions I used such as BLD, BST only work with constant bit numbers and not with a register holding which bit…

More later after I have had a chance to complete and debug!

Kurt

Looks good. I’m uploading the asm{} fixed setup file now. Should be up in an about half an hour.

Also here are some already defined macros you can use:

[code].macro _ints_enable
bset #0,@SYSF:8
andc #0x7F,ccr
.endm

.macro _ints_disable
bclr #0,@SYSF:8
orc #0x80,ccr
.endm

.macro _ints_save_enable
andc #0x7F,ccr ;2
.endm

.macro _ints_save_disable
orc #0x80,ccr ;2
.endm

.macro _ints_restore
orc #0x80,ccr ;2 Disable ints
btst #0,@SYSF:8 ;6
beq .+4:8 ;4 If clear then dont enable ints
andc #0x7F,ccr ;2(14) Enable ints
.endm

.macro _ratedelay rate,offset
.ifdef _DEF20MHZ
delay = (20000000/\rate)
temp1 = 20000000/delay
temp2 = 20000000/(delay+1)
.else
delay = (16000000/\rate)
temp1 = 16000000/delay
temp2 = 16000000/(delay+1)
.endif
temp3 = \rate - temp1
temp4 = \rate - temp2
.if temp3 < 0
temp3 = temp3 * -1
.endif
.if temp4 < 0
temp4 = temp4 * -1
.endif
.if temp4 < temp3
delay = delay + 1
.endif
delay = delay - \offset
.if delay >= 4
delay = delay - 6
count = delay / 8
mov.l #count,er4 ;6
.if count > 0
nop ;2
dec.l #1,er4 ;2
bne .-4:8 ;4(8 clks)
.endif
.endif
rem = delay % 8
.if rem == 1
nop ;2
.endif
.if rem == 2
nop ;2
.endif
.if rem == 3
mov.b #TCRV0,r4l ;3
.endif
.if rem == 4
nop ;2
nop ;2(4)
.endif
.if rem == 5
mov.b #TCRV0,r4l ;3
nop ;2(5)
.endif
.if rem == 6
nop ;2
nop ;2
nop ;2(6)
.endif
.if rem == 7
mov.b #TCRV0,r4l ;3
nop ;2
nop ;2(7)
.endif
.endm

.macro _cycledelay delay
tdelay = \delay
.if tdelay >= 6
tdelay = tdelay - 6
count = tdelay / 8
mov.l #count,er4 ;6
.if count > 0
nop ;2
dec.l #1,er4 ;2
bne .-4:8 ;4(8 clks)
.endif
.endif
rem = tdelay % 8
.if rem == 1
nop ;2
.endif
.if rem == 2
nop ;2
.endif
.if rem == 3
mov.b #TCRV0,r4l ;3
.endif
.if rem == 4
nop ;2
nop ;2(4)
.endif
.if rem == 5
mov.b #TCRV0,r4l ;3
nop ;2(5)
.endif
.if rem == 6
nop ;2
nop ;2
nop ;2(6)
.endif
.if rem == 7
mov.b #TCRV0,r4l ;3
nop ;2
nop ;2(7)
.endif
.endm

.macro _usdelay delay,offset
.ifdef _DEF20MHZ
tdelay = (\delay * 20)-\offset
.else
tdelay = (\delay * 16)-\offset
.endif
.if tdelay >= 6
tdelay = tdelay - 6
count = tdelay / 8
mov.l #count,er4 ;6
.if count > 0
nop ;2
dec.l #1,er4 ;2
bne .-4:8 ;4(8 clks)
.endif
.endif
rem = tdelay % 8
.if rem == 1
nop ;2
.endif
.if rem == 2
nop ;2
.endif
.if rem == 3
mov.b #TCRV0,r4l ;3
.endif
.if rem == 4
nop ;2
nop ;2(4)
.endif
.if rem == 5
mov.b #TCRV0,r4l ;3
nop ;2(5)
.endif
.if rem == 6
nop ;2
nop ;2
nop ;2(6)
.endif
.if rem == 7
mov.b #TCRV0,r4l ;3
nop ;2
nop ;2(7)
.endif
.endm

.macro _msdelay delay,offset
.ifdef _DEF20MHZ
tdelay = (\delay * 20000)-\offset
.else
tdelay = (\delay * 16000)-\offset
.endif
.if tdelay >= 6
tdelay = tdelay - 6
count = tdelay / 8
mov.l #count,er4 ;6
.if tdelay >= 8
nop ;2
dec.l #1,er4 ;2
bne .-4:8 ;4(8 clks)
.endif
.endif
rem = tdelay % 8
.if rem == 1
nop ;2
.endif
.if rem == 2
nop ;2
.endif
.if rem == 3
mov.b #TCRV0,r4l ;3
.endif
.if rem == 4
nop ;2
nop ;2(4)
.endif
.if rem == 5
mov.b #TCRV0,r4l ;3
nop ;2(5)
.endif
.if rem == 6
nop ;2
nop ;2
nop ;2(6)
.endif
.if rem == 7
mov.b #TCRV0,r4l ;3
nop ;2
nop ;2(7)
.endif
.endm

;********************************
; Getpin
;********************************
;R0L = Pin number
;********************************
;ER1 = WORK
;R2 = PORT
;R3L = BIT
;********************************
.macro _GETPINMAC
.equ _DEFGETPIN,0
;One table GETPIN macro ;(18)
and.w #0x3F,r0 ;4
shll.l er0 ;2
mov.w @(_PORTTABLE:16,er0),r2 ;6
shlr.l er0 ;2 Restore pin number
mov.b r2h,r3l ;2
mov.b #0xFF,r2h ;2
.endm

;********************************
; GetDirMac
;********************************
;R0L = Pin number
;********************************
.macro _GETDIRMAC ;(14)
xor.b r1h,r1h ;2 Clear Mask
bset r3l,r1h ;2 Set Mask
mov.b @(0x70-0xD0,er2),r1l ;6 Get PCRS value
and.b r1h,r1l ;2 Isolate BIT
add.b #0xFF,r1l ;2 Move to CARRY
.endm

;********************************
; SetDirMac
;********************************
;R0L = Pin number
;********************************
.macro _SETDIRMAC ;(30)
mov.b @(0x70-0xD0,er2),r1l ;6 Get PCRS value
bcs .+4:8 ;4
bclr r3l,r1l ;2 Clear PCR bit
bcc .+4:8 ;4
bset r3l,r1l ;2 Set PCR bit
mov.b r1l,@(0x70-0xD0,er2) ;6 Save PCRS
mov.b r1l,@(0x10,er2) ;6 Set PCR
.endm

;********************************
; GetStateMac
;********************************
;R0L = Pin number
;********************************
.macro _GETSTATEMAC ;(12)
xor.b r1h,r1h ;2 Clear Mask
bset r3l,r1h ;2 Set Mask
mov.b @er2,r1l ;4 Get PORT
and.b r1h,r1l ;2 Isolate BIT
add.b #0xFF,r1l ;2 Move to CARRY
.endm

;********************************
; SetStateMac
;********************************
;R0L = Pin number
;********************************
.macro _SETSTATEMAC ;(24)
bcc .+6:8 ;4
bset r3l,@er2 ;8
bcs .+6:8 ;4
bclr r3l,@er2 ;8
.endm

;********************************
; HighFuncMac
;********************************
;R0L = Pin number
;********************************
.macro _HIGHFUNCMAC ;(46)
_GETPINMAC ;18
bset r3l,@er2 ;8 Set PDR bit
mov.b @(0x70-0xD0,er2),r1l ;6 Get PCRS value
bset r3l,r1l ;2 Set PCR bit
mov.b r1l,@(0x70-0xD0,er2) ;6 Save PCRS
mov.b r1l,@(0x10,er2) ;6 Set PCR
.endm

;********************************
; HighFastFuncMac
;********************************
;R0L = Pin number
;********************************
.macro _HIGHFASTFUNCMAC ;(26)
_GETPINMAC ;18
bset r3l,@er2 ;8
.endm

;********************************
; LowFuncMac
;********************************
;R0L = Pin number
;********************************
.macro _LOWFUNCMAC ;(46)
_GETPINMAC ;18
bclr r3l,@er2 ;8 Set PDR bit
mov.b @(0x70-0xD0,er2),r1l ;6 Get PCRS value
bset r3l,r1l ;2 Set PCR bit
mov.b r1l,@(0x70-0xD0,er2) ;6 Save PCRS
mov.b r1l,@(0x10,er2) ;6 Set PCR
.endm

;********************************
; LowFastFuncMac
;********************************
;R0L = Pin number
;********************************
.macro _LOWFASTFUNCMAC ;(26)
_GETPINMAC ;18
bclr r3l,@er2 ;8
.endm

;********************************
; ToggleFuncMac
;********************************
;R0L = Pin number
;********************************
.macro _TOGGLEFUNCMAC ;(46)
_GETPINMAC ;18
bnot r3l,@er2 ;8
mov.b @(0x70-0xD0,er2),r1l ;6 Get PCRS value
bset r3l,r1l ;2 Set PCR bit
mov.b r1l,@(0x70-0xD0,er2) ;6 Save PCRS
mov.b r1l,@(0x10,er2) ;6 Set PCR
.endm

;********************************
; ToggleFastFuncMac
;********************************
;R0L = Pin number
;********************************
.macro _TOGGLEFASTFUNCMAC ;(26)
_GETPINMAC ;18
bnot r3l,@er2 ;8
.endm

;********************************
; InputFuncMac
;********************************
;R0L = Pin number
;********************************
.macro _INPUTFUNCMAC ;(38)
_GETPINMAC ;18
mov.b @(0x70-0xD0,er2),r1l ;6 Get PCRS value
bclr r3l,r1l ;2 Clear PCR bit
mov.b r1l,@(0x70-0xD0,er2) ;6 Save PCRS
mov.b r1l,@(0x10,er2) ;6 Set PCR
.endm

;********************************
; OutputFuncMac
;********************************
;R0L = Pin number
;********************************
.macro _OUTPUTFUNCMAC ;(38)
_GETPINMAC ;18
mov.b @(0x70-0xD0,er2),r1l ;6 Get PCRS value
bset r3l,r1l ;2 Set PCR bit
mov.b r1l,@(0x70-0xD0,er2) ;6 Save PCRS
mov.b r1l,@(0x10,er2) ;6 Set PCR
.endm

;********************************
; ReverseFuncMac
;********************************
;R0L = Pin number
;********************************
.macro _REVERSEFUNCMAC ;(38)
_GETPINMAC ;18
mov.b @(0x70-0xD0,er2),r1l ;6 Get PCRS value
bnot r3l,r1l ;2 Toggle PCR bit
mov.b r1l,@(0x70-0xD0,er2) ;6 Save PCRS
mov.b r1l,@(0x10,er2) ;6 Set PCR
.endm

;********************************
; InputStaicMac
;********************************
;R0L = Pin number
;********************************
.macro _INPUTSTATICMAC pin ;(20)
mov.b @0x70-0xD0+(\pin&0xFF):8,r1l ;6 Get PCRS value
bclr #(\pin>>8),r1l ;2 Clear PCR bit
mov.b r1l,@0x70-0xD0+(\pin&0xFF):8 ;6 Save PCRS
mov.b r1l,@0x10+(\pin&0xFF):8 ;6 Set PCR
.endm

;********************************
; OutputStaticMac
;********************************
;R0L = Pin number
;********************************
.macro _OUTPUTSTATICMAC pin ;(20)
mov.b @0x70-0xD0+(\pin&0xFF):8,r1l ;6 Get PCRS value
bset #(\pin>>8),r1l ;2 Set PCR bit
mov.b r1l,@0x70-0xD0+(\pin&0xFF):8 ;6 Save PCRS
mov.b r1l,@0x10+(\pin&0xFF):8 ;6 Set PCR
.endm

;********************************
; ReverseStaticMac
;********************************
;R0L = Pin number
;********************************
.macro _REVERSESTATICMAC pin ;(20)
mov.b @0x70-0xD0+(\pin&0xFF):8,r1l ;6 Get PCRS value
bnot #(\pin>>8),r1l ;2 Reverse PCR bit
mov.b r1l,@0x70-0xD0+(\pin&0xFF):8 ;6 Save PCRS
mov.b r1l,@0x10+(\pin&0xFF):8 ;6 Set PCR
.endm[/code]

Thanks, I will try to convert over to your macros as to make it easier to share and to avoid some errors.

As for a somewhat side question. Have you found a reasonable way to debug your assembly code on the H8? I assume I can not easily single step through the code or the like. So far I have resorted to saving stuff away in temps and printing them, setting or clearing LEDS and the like. Are there any ways to set breakpoints in assembly from the IDE? Or Set Address Breaks? Inbed some form of Interrupt???

I will probably also hook up my parallax oscilloscope, which is very limited, but does help sometimes to see what I am inputting or getting back…

You may be able to add calls to the debug handler inside your asm code so that the debugger can break at or step to that point. I’ll have to look at the code tomorrow. The way it currently works is the debugger is called(_DEBUGEX) before every basic command token is processed. However I beleive I used a goto _DEBUGEX and then a goto _DEBUGEXRETURN label to reduce the processing over head by a couple clock cycles. if so you won’t be able to call the _DEBUGEX fucntion from anywhere but the command processing loop. If that is they way I’m doing it I’ll see if I can change it to a bsr/rts call instead so you can call it from inside your asm code. I should be able to have the compiler automatically add the bsr _DEBUGEX:16 between every line of user asm code when in debug mode.

Hi Nathan,

I started looking over your macros. Some of them make total sense to me, and others I wonder if they are setup to manipulate the actual H8 IO registers or are they setup to manipulate some shadow registers.

For example: GetPin
makes total sense. It sets up the appropriate address and mask to manipulate the PDRx and Bit for the input pin number.

But GetDir does not make sense to me. At first I thought it was going to try to set the appropriate IO control register PCRx to make it Input or Output, but it looks like it is taking the address calculated from GetPin (example FFDB or pdr8) and then converting the address to FF7B which is below the IO registers, where as pcr8 is FFEB.

Is this something we should take offline?

EDIT: I am pretty sure this is your shadow registers. I will go ahead and use these to keep your shadow registers in sync. Do I need to preload e2 with some specific value?

Kurt

Remeber you can’t read the PCR registers. They always return 0xFF, so yes, whenever I have to get the current state of a PCR register I read the shadow register instead. Also, when I modify a PCR register I copy the modification to the PCR shadow register as well. I call my PCR shadow registers PCRS in my code comments. Below are the defines I use for the 3687 and 3694 PCR shadow registers:

;3687
.equ SYS0,		0xFF70
.equ SYS1,		0xFF71
.equ SYS2,		0xFF72
.equ SYS3,		0xFF73
.equ PCRS1, 	0xFF74
.equ PCRS2, 	0xFF75
.equ PCRS3, 	0xFF76
.equ SYS7,		0xFF77
.equ PCRS5, 	0xFF78
.equ PCRS6, 	0xFF79
.equ PCRS7, 	0xFF7A
.equ PCRS8, 	0xFF7B
.equ SYSC,	0xFF7C
.equ SYSD,	0xFF7D
.equ SYSE,		0xFF7E
.equ SYSF,		0xFF7F

.equ SYS0,	0xFF70
.equ SYS1,	0xFF71
.equ SYS2,	0xFF72
.equ SYS3,	0xFF73
.equ PCRS1, 0xFF74
.equ PCRS2, 0xFF75
.equ SYS6,	0xFF76
.equ SYS7,	0xFF77
.equ PCRS5, 0xFF78
.equ SYS9,	0xFF79
.equ PCRS7, 0xFF7A
.equ PCRS8, 0xFF7B
.equ SYSC,	0xFF7C
.equ SYSD,	0xFF7D
.equ SYSE,	0xFF7E
.equ SYSF,	0xFF7F

Currentyl I only use the PCR shadow registers and the SYSF register but I may use any of the other SYS# registers at any time so it would not be a good idea to try to use them for anything important.

Also, I just uploaded a new 8018. Download and try it out. Added ASM debugging support.

Also added an ADIN16 command. Works like the one on regular BasicATOMs. Read 64 A/D readings in a row and adds them together to get a 16bit value. Works pretty good with a pot. Don’t know about real world though.

Hi Nathan,

Thought I would try out the debug support as I am playing around with the PS2 controller code in ASM and I am detecting a timeout on the ACK line and want to see where, so I thought I would recompile and got several errors:

c:\users\kurt\desktop\lynxmotion\test ps2.asm:3892: Error: Symbol _LN00000_00384 already defined. c:\users\kurt\desktop\lynxmotion\test ps2.asm:3892: Error: Symbol _LN00000_00385 already defined. ...
There are many pages of these. A lot of them appear to revolve around the macro: _GETPINMAC. Maybe it has to do with the .equ _DEFGETPIN,0
line. Will try commenting that line out and see what happens… Or maybe it has to do with macros in general. Will experiment some.

EDIT: commenting out the EQU did not help. I think it is the expansion of each of the macros is causing duplicate labels to be generated…

Kurt

Hmm. I see the problem. When debuging I add a label and a .stabn with the label line number for each line of asm code so the debuger can get the information out of the bin file generated. But when using .macros you will get duplicate labels when debugging because the labels added between the .macro code lines will get duplicated after you use that macro a second time in your code. Looks like I will have to add parsing for the .macro and .endm directives or figure out some other way to calculate the .stabn for each line of asm. That will take some time. If until then you want to debug you will have to forgo using macros in your asm code.

Not familliar with the particulars of your compiler/assembler, however other assemblers have the capability for macro definitions to generate unique labels within the macro definition. Typically the labels start with a constant part but end with a symbol of some sort and an index count so you can differentiate between labels within the macro. If your assembler has the capability perhas you can apply it to your label definitions with the line numbers.

Yes, the assembler can do this but the compiler uses compiler defined labels when generating the debugger information which means I either need to parse the asm code for .macro and .endm directives or I need to find a way to use assembler defined labels instead of compiler defined labels to generate the .stab debugger code. I’m leaning toward the assembler defined labels so I don’t have to parse the asm code in the compiler but I may not have a choice.

Ok. I’ve switched to assembler defined labels for the .stabn definitions to store the debug information. Asm code inline and in ASM{} blocks as well as .macros should all debug properly now. When the debugger enters a .macro call the .macro code will be stepped through on screen.

I’m playing with some ideas about the debugger. I think adding the ability to specify what code to allow debugging(via special labels like the BEGINASMSUB and ENDASMSUB ones already used) into and whether interrupts will be processed while waiting in the debugger would be a good addition to the current system.

Currently the debugger when sitting paused doesn’t process interrupts and even when it’s running it takes so long to process the debug handlers that most interrupts will simply constantly fire never allowing normal code to run.

This sounds great! As I mentioned in some other threads, I usually avoid debug on any programs with interrupts for those very reasons. Should be fun to try out!

Kurt