uzem says it's running at 30 MHz, and Wait100ns in uzeboxCore.c just runs the 3 cycle lpm instruction, which also suggests 30 MHz. At 60 fields per second, that suggests each field should have 500000 cycles available, right? Of course, much of that will be consumed from outputting the video signal and sound processing. But I don't think that should consume anywhere near as many cycles as I'm measuring.
Here's my code:
Code: Select all
#include <avr/pgmspace.h>
#include <uzebox.h>
u32 wait_vsync(void);
int main(void) {
ClearVram();
SetFontTilesIndex(32);
SetBorderColor(0x52U);
while (true) {
u32 cycles = wait_vsync();
PrintLong(10, 5, cycles);
PrintHexLong(12, 5, cycles);
}
}
Code: Select all
#include <defines.h>
.global wait_vsync
.section .text
;;; ================================================================================
;;; Wait until next vsync, and return the number of cycles that passed.
;;;
;;; C-callable
;;; returns: (u32)
.section .text.wait_vsync
wait_vsync:
clr r1 ; note r1 is assumed by C code to be 0, but better safe
clr r22
clr r23
clr r24
clr r25
1:
;; See uzeboxVideoEngineCore.s:GetVsyncFlag
lds r18, sync_flags ;2 cycles
andi r18, SYNC_FLAG_VSYNC ;1 cycle
ldi r20, 11 ;1 cycle
add r22, r20 ;1 cycle
adc r23, r1 ;1 cycle
adc r24, r1 ;1 cycle
adc r25, r1 ;1 cycle
cpi r18, 0 ;1 cycle
breq 1b ;2 cycles when true, 1 when false
;; See uzeboxVideoEngineCore.s:ClearVsyncFlag
;; Copying because we already copied GetVsyncFlag right here and this
;; shaves off a few extra cycles
lds r18,sync_flags
andi r18,~SYNC_FLAG_VSYNC
sts sync_flags,r18
ret
.size wait_vsync, . - wait_vsync
Code: Select all
$ make
mkdir .bin
mkdir .obj
mkdir .gen
avr-gcc -I"../../uzebox/kernel" -mmcu=atmega644 -mmcu=atmega644 -Wall -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -fno-toplevel-reorder -DVIDEO_MODE=41 -DM40_IBM_ASCII=1 -DINTRO_LOGO=0 -DENABLE_MIXER=0 -fshort-enums -g3 -gdwarf-2 -x assembler-with-cpp -c ../../uzebox/kernel/uzeboxVideoEngineCore.s -o .obj/uzeboxVideoEngineCore.o
avr-gcc -I"../../uzebox/kernel" -mmcu=atmega644 -mmcu=atmega644 -Wall -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -fno-toplevel-reorder -DVIDEO_MODE=41 -DM40_IBM_ASCII=1 -DINTRO_LOGO=0 -DENABLE_MIXER=0 -fshort-enums -g3 -gdwarf-2 -x assembler-with-cpp -c ../../uzebox/kernel/uzeboxSoundEngineCore.s -o .obj/uzeboxSoundEngineCore.o
avr-gcc -I"../../uzebox/kernel" -mmcu=atmega644 -Wall -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -fno-toplevel-reorder -DVIDEO_MODE=41 -DM40_IBM_ASCII=1 -DINTRO_LOGO=0 -DENABLE_MIXER=0 -fshort-enums -g3 -gdwarf-2 -c ../../uzebox/kernel/uzeboxCore.c -o .obj/uzeboxCore.o
avr-gcc -I"../../uzebox/kernel" -mmcu=atmega644 -Wall -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -fno-toplevel-reorder -DVIDEO_MODE=41 -DM40_IBM_ASCII=1 -DINTRO_LOGO=0 -DENABLE_MIXER=0 -fshort-enums -g3 -gdwarf-2 -c ../../uzebox/kernel/uzeboxSoundEngine.c -o .obj/uzeboxSoundEngine.o
avr-gcc -I"../../uzebox/kernel" -mmcu=atmega644 -Wall -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -fno-toplevel-reorder -DVIDEO_MODE=41 -DM40_IBM_ASCII=1 -DINTRO_LOGO=0 -DENABLE_MIXER=0 -fshort-enums -g3 -gdwarf-2 -c ../../uzebox/kernel/uzeboxVideoEngine.c -o .obj/uzeboxVideoEngine.o
avr-gcc -I"../../uzebox/kernel" -mmcu=atmega644 -Wall -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -fno-toplevel-reorder -DVIDEO_MODE=41 -DM40_IBM_ASCII=1 -DINTRO_LOGO=0 -DENABLE_MIXER=0 -fshort-enums -g3 -gdwarf-2 -c main.c -o .obj/main.o
avr-gcc -I"../../uzebox/kernel" -mmcu=atmega644 -mmcu=atmega644 -Wall -std=gnu99 -DF_CPU=28636360UL -Os -fsigned-char -ffunction-sections -fno-toplevel-reorder -DVIDEO_MODE=41 -DM40_IBM_ASCII=1 -DINTRO_LOGO=0 -DENABLE_MIXER=0 -fshort-enums -g3 -gdwarf-2 -x assembler-with-cpp -c asm.s -o .obj/asm.o
avr-gcc -mmcu=atmega644 -Wl,-Map=.obj/test41.map -Wl,-gc-sections .obj/uzeboxVideoEngineCore.o .obj/uzeboxSoundEngineCore.o .obj/uzeboxCore.o .obj/uzeboxSoundEngine.o .obj/uzeboxVideoEngine.o .obj/main.o .obj/asm.o -o .bin/test41.elf
avr-objcopy -O ihex -R .eeprom .bin/test41.elf .bin/test41.hex
When I run this in uzem and cuzebox, it prints 66737 = 0x104b1 free cycles per vsync. This is clearly nowhere near 500000. As you can see, I have -DENABLE_MIXER=0, so sound processing shouldn't be consuming any cycles. I can't imagine that mode 41 consumes 430000 cycles per field, so I figure I must have made a mistake somewhere else.
Is my wait_vsync bad? Did I pass some bad compiler argument, or not pass one I should? Do PrintLong or PrintHexLong take a really long time? Is something other than mode 41's video processing running during interrupts? Was my estimate of 500000 cycles per field wrong?
I've really been scratching my head trying to figure out where these cycles are going, to be honest. Any help is appreciated! Thanks!