diff --git a/part2-building/Makefile b/part2-building/Makefile index 89235e9..86c7420 100644 --- a/part2-building/Makefile +++ b/part2-building/Makefile @@ -1,19 +1,19 @@ CFILES = $(wildcard *.c) OFILES = $(CFILES:.c=.o) -GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin +LLVMPATH = /opt/homebrew/opt/llvm/bin +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -mcpu=cortex-a72+nosimd all: clean kernel8.img boot.o: boot.S - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + clang --target=aarch64-elf $(GCCFLAGS) -c boot.S -o boot.o %.o: %.c - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + clang --target=aarch64-elf $(GCCFLAGS) -c $< -o $@ kernel8.img: boot.o $(OFILES) - $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf - $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + $(LLVMPATH)/ld.lld -m aarch64elf -nostdlib boot.o $(OFILES) -T link.ld -o kernel8.elf + $(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img clean: /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part2-building/Makefile.gcc b/part2-building/Makefile.gcc new file mode 100644 index 0000000..89235e9 --- /dev/null +++ b/part2-building/Makefile.gcc @@ -0,0 +1,19 @@ +CFILES = $(wildcard *.c) +OFILES = $(CFILES:.c=.o) +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles +GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin + +all: clean kernel8.img + +boot.o: boot.S + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + +%.o: %.c + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + +kernel8.img: boot.o $(OFILES) + $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf + $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + +clean: + /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part3-helloworld/Makefile b/part3-helloworld/Makefile index 89235e9..86c7420 100644 --- a/part3-helloworld/Makefile +++ b/part3-helloworld/Makefile @@ -1,19 +1,19 @@ CFILES = $(wildcard *.c) OFILES = $(CFILES:.c=.o) -GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin +LLVMPATH = /opt/homebrew/opt/llvm/bin +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -mcpu=cortex-a72+nosimd all: clean kernel8.img boot.o: boot.S - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + clang --target=aarch64-elf $(GCCFLAGS) -c boot.S -o boot.o %.o: %.c - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + clang --target=aarch64-elf $(GCCFLAGS) -c $< -o $@ kernel8.img: boot.o $(OFILES) - $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf - $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + $(LLVMPATH)/ld.lld -m aarch64elf -nostdlib boot.o $(OFILES) -T link.ld -o kernel8.elf + $(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img clean: /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part3-helloworld/Makefile.gcc b/part3-helloworld/Makefile.gcc new file mode 100644 index 0000000..89235e9 --- /dev/null +++ b/part3-helloworld/Makefile.gcc @@ -0,0 +1,19 @@ +CFILES = $(wildcard *.c) +OFILES = $(CFILES:.c=.o) +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles +GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin + +all: clean kernel8.img + +boot.o: boot.S + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + +%.o: %.c + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + +kernel8.img: boot.o $(OFILES) + $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf + $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + +clean: + /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part4-miniuart/Makefile b/part4-miniuart/Makefile index 89235e9..86c7420 100644 --- a/part4-miniuart/Makefile +++ b/part4-miniuart/Makefile @@ -1,19 +1,19 @@ CFILES = $(wildcard *.c) OFILES = $(CFILES:.c=.o) -GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin +LLVMPATH = /opt/homebrew/opt/llvm/bin +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -mcpu=cortex-a72+nosimd all: clean kernel8.img boot.o: boot.S - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + clang --target=aarch64-elf $(GCCFLAGS) -c boot.S -o boot.o %.o: %.c - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + clang --target=aarch64-elf $(GCCFLAGS) -c $< -o $@ kernel8.img: boot.o $(OFILES) - $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf - $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + $(LLVMPATH)/ld.lld -m aarch64elf -nostdlib boot.o $(OFILES) -T link.ld -o kernel8.elf + $(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img clean: /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part4-miniuart/Makefile.gcc b/part4-miniuart/Makefile.gcc new file mode 100644 index 0000000..89235e9 --- /dev/null +++ b/part4-miniuart/Makefile.gcc @@ -0,0 +1,19 @@ +CFILES = $(wildcard *.c) +OFILES = $(CFILES:.c=.o) +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles +GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin + +all: clean kernel8.img + +boot.o: boot.S + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + +%.o: %.c + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + +kernel8.img: boot.o $(OFILES) + $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf + $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + +clean: + /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part5-framebuffer/Makefile b/part5-framebuffer/Makefile index 89235e9..86c7420 100644 --- a/part5-framebuffer/Makefile +++ b/part5-framebuffer/Makefile @@ -1,19 +1,19 @@ CFILES = $(wildcard *.c) OFILES = $(CFILES:.c=.o) -GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin +LLVMPATH = /opt/homebrew/opt/llvm/bin +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -mcpu=cortex-a72+nosimd all: clean kernel8.img boot.o: boot.S - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + clang --target=aarch64-elf $(GCCFLAGS) -c boot.S -o boot.o %.o: %.c - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + clang --target=aarch64-elf $(GCCFLAGS) -c $< -o $@ kernel8.img: boot.o $(OFILES) - $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf - $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + $(LLVMPATH)/ld.lld -m aarch64elf -nostdlib boot.o $(OFILES) -T link.ld -o kernel8.elf + $(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img clean: /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part5-framebuffer/Makefile.gcc b/part5-framebuffer/Makefile.gcc new file mode 100644 index 0000000..89235e9 --- /dev/null +++ b/part5-framebuffer/Makefile.gcc @@ -0,0 +1,19 @@ +CFILES = $(wildcard *.c) +OFILES = $(CFILES:.c=.o) +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles +GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin + +all: clean kernel8.img + +boot.o: boot.S + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + +%.o: %.c + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + +kernel8.img: boot.o $(OFILES) + $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf + $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + +clean: + /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part6-breakout/Makefile b/part6-breakout/Makefile index 89235e9..86c7420 100644 --- a/part6-breakout/Makefile +++ b/part6-breakout/Makefile @@ -1,19 +1,19 @@ CFILES = $(wildcard *.c) OFILES = $(CFILES:.c=.o) -GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin +LLVMPATH = /opt/homebrew/opt/llvm/bin +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -mcpu=cortex-a72+nosimd all: clean kernel8.img boot.o: boot.S - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + clang --target=aarch64-elf $(GCCFLAGS) -c boot.S -o boot.o %.o: %.c - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + clang --target=aarch64-elf $(GCCFLAGS) -c $< -o $@ kernel8.img: boot.o $(OFILES) - $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf - $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + $(LLVMPATH)/ld.lld -m aarch64elf -nostdlib boot.o $(OFILES) -T link.ld -o kernel8.elf + $(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img clean: /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part6-breakout/Makefile.gcc b/part6-breakout/Makefile.gcc new file mode 100644 index 0000000..89235e9 --- /dev/null +++ b/part6-breakout/Makefile.gcc @@ -0,0 +1,19 @@ +CFILES = $(wildcard *.c) +OFILES = $(CFILES:.c=.o) +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles +GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin + +all: clean kernel8.img + +boot.o: boot.S + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + +%.o: %.c + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + +kernel8.img: boot.o $(OFILES) + $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) -T link.ld -o kernel8.elf + $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + +clean: + /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part6-breakout/io.c b/part6-breakout/io.c index e8af328..e06b64d 100644 --- a/part6-breakout/io.c +++ b/part6-breakout/io.c @@ -147,8 +147,8 @@ void uart_writeByteBlocking(unsigned char ch) { void uart_writeText(char *buffer) { while (*buffer) { - if (*buffer == '\n') uart_writeByteBlocking('\r'); - uart_writeByteBlocking(*buffer++); + if (*buffer == '\n') uart_writeByteBlockingActual('\r'); + uart_writeByteBlockingActual(*buffer++); } } diff --git a/part6-breakout/kernel.c b/part6-breakout/kernel.c index 930e2f0..6c972e9 100644 --- a/part6-breakout/kernel.c +++ b/part6-breakout/kernel.c @@ -35,8 +35,10 @@ enum { OBJ_BALL = 3 }; +#define OBJS_ADDRESS 0x02100000 // Somewhere safe to store a lot of data + unsigned int numobjs = 0; -struct Object objects[(ROWS * COLS) + (2 * NUM_LIVES)]; +struct Object *objects = (struct Object *)OBJS_ADDRESS; struct Object *ball; struct Object *paddle; @@ -87,7 +89,7 @@ void initBricks() int brickwidth = 32; int brickheight = 8; int brickspacer = 20; - int brickcols[5] = { 0x11, 0x22, 0xEE, 0x44, 0x66 }; + static int brickcols[] = { 0x11, 0x22, 0xEE, 0x44, 0x66 }; int ybrick = MARGIN + brickheight; @@ -149,13 +151,10 @@ void drawScoreboard(int score, int lives) char tens = score / 10; score -= (10 * tens); char ones = score; - char string[] = "Score: 0xx Lives: x\0\0"; - - string[8] = tens + 0x30; - string[9] = ones + 0x30; - string[20] = (char)lives + 0x30; - - drawString((WIDTH/2)-252, MARGIN-25, string, 0x0f, 3); + drawString((WIDTH/2)-252, MARGIN-25, "Score: 0 Lives: ", 0x0f, 3); + drawChar(tens + 0x30, (WIDTH/2)-252 + (8*8*3), MARGIN-25, 0x0f, 3); + drawChar(ones + 0x30, (WIDTH/2)-252 + (8*9*3), MARGIN-25, 0x0f, 3); + drawChar((char)lives + 0x30, (WIDTH/2)-252 + (8*20*3), MARGIN-25, 0x0f, 3); } void main() diff --git a/part7-bluetooth/Makefile b/part7-bluetooth/Makefile index 3ecc081..143c51b 100644 --- a/part7-bluetooth/Makefile +++ b/part7-bluetooth/Makefile @@ -1,22 +1,22 @@ CFILES = $(wildcard *.c) OFILES = $(CFILES:.c=.o) -GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin +LLVMPATH = /opt/homebrew/opt/llvm/bin +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -mcpu=cortex-a72+nosimd all: clean kernel8.img boot.o: boot.S - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + clang --target=aarch64-elf $(GCCFLAGS) -c boot.S -o boot.o BCM4345C0.o : BCM4345C0.hcd - $(GCCPATH)/aarch64-none-elf-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@ + $(LLVMPATH)/llvm-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@ %.o: %.c - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + clang --target=aarch64-elf $(GCCFLAGS) -c $< -o $@ kernel8.img: boot.o $(OFILES) BCM4345C0.o - $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) BCM4345C0.o -T link.ld -o kernel8.elf - $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + $(LLVMPATH)/ld.lld -m aarch64elf -nostdlib boot.o $(OFILES) BCM4345C0.o -T link.ld -o kernel8.elf + $(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img clean: /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part7-bluetooth/Makefile.gcc b/part7-bluetooth/Makefile.gcc new file mode 100644 index 0000000..3ecc081 --- /dev/null +++ b/part7-bluetooth/Makefile.gcc @@ -0,0 +1,22 @@ +CFILES = $(wildcard *.c) +OFILES = $(CFILES:.c=.o) +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles +GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin + +all: clean kernel8.img + +boot.o: boot.S + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + +BCM4345C0.o : BCM4345C0.hcd + $(GCCPATH)/aarch64-none-elf-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@ + +%.o: %.c + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + +kernel8.img: boot.o $(OFILES) BCM4345C0.o + $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) BCM4345C0.o -T link.ld -o kernel8.elf + $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + +clean: + /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part7-bluetooth/bt.c b/part7-bluetooth/bt.c index c91c854..800f5b4 100644 --- a/part7-bluetooth/bt.c +++ b/part7-bluetooth/bt.c @@ -1,6 +1,8 @@ #include "io.h" #include "fb.h" +volatile unsigned char *params = (unsigned char *)SAFE_ADDRESS; + // UART0 enum { @@ -91,7 +93,7 @@ enum { unsigned char empty[] = {}; -int hciCommandBytes(unsigned char *opcodebytes, unsigned char *data, unsigned char length) +int hciCommandBytes(volatile unsigned char *opcodebytes, volatile unsigned char *data, unsigned char length) { unsigned char c=0; @@ -128,7 +130,7 @@ int hciCommandBytes(unsigned char *opcodebytes, unsigned char *data, unsigned ch return 0; } -int hciCommand(unsigned short ogf, unsigned short ocf, unsigned char *data, unsigned char length) +int hciCommand(unsigned short ogf, unsigned short ocf, volatile unsigned char *data, unsigned char length) { unsigned short opcode = ogf << 10 | ocf; unsigned char opcodebytes[2] = { lo(opcode), hi(opcode) }; @@ -151,11 +153,12 @@ void bt_loadfirmware() unsigned int size = (long)&_binary_BCM4345C0_hcd_size; while (c < size) { - unsigned char opcodebytes[] = { _binary_BCM4345C0_hcd_start[c], _binary_BCM4345C0_hcd_start[c+1] }; + params[0] = _binary_BCM4345C0_hcd_start[c]; + params[1] = _binary_BCM4345C0_hcd_start[c+1]; unsigned char length = _binary_BCM4345C0_hcd_start[c+2]; unsigned char *data = &(_binary_BCM4345C0_hcd_start[c+3]); - if (hciCommandBytes(opcodebytes, data, length)) { + if (hciCommandBytes(params, data, length)) { uart_writeText("Firmware data load failed\n"); break; } @@ -167,13 +170,23 @@ void bt_loadfirmware() void bt_setbaud() { - static unsigned char params[] = { 0, 0, 0x00, 0xc2, 0x01, 0x00 }; // little endian, 115200 + params[0] = 0; + params[1] = 0; + params[2] = 0x00; + params[3] = 0xc2; + params[4] = 0x01; + params[5] = 0x00; // little endian, 115200 if (hciCommand(OGF_VENDOR, COMMAND_SET_BAUD, params, 6)) uart_writeText("bt_setbaud() failed\n"); } void bt_setbdaddr() { - static unsigned char params[] = { 0xee, 0xff, 0xc0, 0xee, 0xff, 0xc0 }; // reversed + params[0] = 0xee; + params[1] = 0xff; + params[2] = 0xc0; + params[3] = 0xee; + params[4] = 0xff; + params[5] = 0xc0; // reversed if (hciCommand(OGF_VENDOR, COMMAND_SET_BDADDR, params, 6)) uart_writeText("bt_setbdaddr() failed\n"); } @@ -213,7 +226,11 @@ void sendACLsubscribe(unsigned int handle) bt_writeByte(lo(channel)); bt_writeByte(hi(channel)); - unsigned char params[] = { 0x12, 0x2b, 0x00, 0x01, 0x00 }; + params[0] = 0x12; + params[1] = 0x2b; + params[2] = 0x00; + params[3] = 0x01; + params[4] = 0x00; unsigned int c=0; while (c++= 1920) { + curx = 0; cury += 8; + } + if (cury + 8 >= 1080) { + cury = 0; + } + drawString(curx, cury, str, 0x0f, 1); + curx += (strlen(str) * 8); +} + +void debugcrlf(void) { + curx = 0; cury += 8; +} + +void debugch(unsigned char b) { + unsigned int n; + int c; + for(c=4;c>=0;c-=4) { + n=(b>>c)&0xF; + n+=n>9?0x37:0x30; + debugstr((char *)&n); + } + debugstr(" "); +} + +void debughex(unsigned int d) { + unsigned int n; + int c; + for(c=28;c>=0;c-=4) { + n=(d>>c)&0xF; + n+=n>9?0x37:0x30; + debugstr((char *)&n); + } + debugstr(" "); +} diff --git a/part7-bluetooth/fb.h b/part7-bluetooth/fb.h index 6163d77..8beda43 100644 --- a/part7-bluetooth/fb.h +++ b/part7-bluetooth/fb.h @@ -7,3 +7,7 @@ void drawCircle(int x0, int y0, int radius, unsigned char attr, int fill); void drawLine(int x1, int y1, int x2, int y2, unsigned char attr); void moveRect(int oldx, int oldy, int width, int height, int shiftx, int shifty, unsigned char attr); void wait_msec(unsigned int n); +void debugstr(char *str); +void debugcrlf(void); +void debugch(unsigned char b); +void debughex(unsigned int d); diff --git a/part7-bluetooth/io.h b/part7-bluetooth/io.h index 8547cc0..b2f483e 100644 --- a/part7-bluetooth/io.h +++ b/part7-bluetooth/io.h @@ -1,4 +1,5 @@ #define PERIPHERAL_BASE 0xFE000000 +#define SAFE_ADDRESS 0x00210000 // Somewhere safe to store a lot of data void uart_init(); void uart_writeText(char *buffer); diff --git a/part7-bluetooth/kernel.c b/part7-bluetooth/kernel.c index cf64621..e5e2066 100644 --- a/part7-bluetooth/kernel.c +++ b/part7-bluetooth/kernel.c @@ -1,7 +1,6 @@ #include "io.h" #include "bt.h" - -#define memcmp __builtin_memcmp +#include "fb.h" #define MAX_MSG_LEN 50 #define MAX_READ_RUN 100 @@ -26,6 +25,16 @@ unsigned char echo_addr[6]; unsigned int connected = 0; unsigned int connection_handle = 0; +int memcmp(const char *str1, const char *str2, int count) { + const char *s1 = (const char*)str1; + const char *s2 = (const char*)str2; + + while (count-- > 0) { + if (*s1++ != *s2++) return s1[-1] < s2[-1] ? -1 : 1; + } + return 0; +} + void hci_poll2(unsigned char byte) { switch (poll_state) { @@ -71,62 +80,51 @@ unsigned char *hci_poll() return 0; } -void bt_search() -{ +void bt_search(void) { unsigned char *buf; while ( (buf = hci_poll()) ) { if (data_len >= 2) { if (buf[0] == LE_ADREPORT_CODE) { - unsigned char numreports = buf[1]; - - if (numreports == 1) { - unsigned char event_type = buf[2]; - - if (event_type == 0x00) { - unsigned char buf_len = buf[10]; + if (buf[1] == 1) { // num_reports + if (buf[2] == 0) { // event_type + int bufindex = 0; unsigned char ad_len = buf[11]; - if (ad_len < data_len && buf_len + 11 == data_len - 1) { - for (int c=9;c>=4;c--) echo_addr[9-c] = buf[c]; - buf += 11; + for (int c=9;c>=4;c--) echo_addr[9-c] = buf[bufindex + c]; // save the mac address + bufindex += 11; - got_echo_sid = 0; got_echo_name = 0; // Reset the search state machine - do { - ad_len = buf[0]; - unsigned char ad_type = buf[1]; - buf += 2; + got_echo_sid = 0; got_echo_name = 0; // Reset the search state machine + do { + ad_len = buf[bufindex]; + unsigned char ad_type = buf[bufindex + 1]; + bufindex += 2; - if (ad_len >= 2) { - if (ad_type == 0x03) { - unsigned int sid=0; + if (ad_len >= 2) { + if (ad_type == 0x03) { + unsigned int sid = buf[bufindex] | (buf[bufindex + 1] << 8); + if (sid == 0xEC00) { + got_echo_sid = 1; + debugstr("got sid... "); + } + } else if (ad_type == 0x09) { + char remote_name[ad_len - 1]; + unsigned int d=0; - for (int d=0;d= 2) { if (buf[0] == LE_CONNECT_CODE && !connected) { connected = !buf[1]; - uart_hex(connected); uart_writeText(" "); + debughex(connected); debugstr(" "); connection_handle = buf[2] | (buf[3] << 8); - uart_hex(connection_handle); uart_writeText(" "); + debughex(connection_handle); debugstr(" "); } } } @@ -155,80 +153,109 @@ void acl_poll() unsigned char byte = bt_readByte(); if (byte == HCI_EVENT_PKT) { - unsigned char opcode = bt_waitReadByte(); + bt_waitReadByte(); // opcode unsigned char length = bt_waitReadByte(); for (int i=0;i> 4; + unsigned int dlen = h1 | (h2 << 8); + unsigned char data[dlen]; - h1 = bt_waitReadByte(); - h2 = bt_waitReadByte(); + if (dlen > 7) { + for (int i=0;i=0;c--) uart_byte(local_addr[c]); - uart_writeText("\n"); - - // Start scanning for echo +void run_search(void) { + // Start scanning + debugstr("Setting event mask... "); setLEeventmask(0xff); + debugstr("Starting scanning... "); startActiveScanning(); - uart_writeText("Waiting for echo: "); + + // Search for the echo + debugstr("Waiting..."); + debugcrlf(); while (!(got_echo_sid && got_echo_name)) bt_search(); stopScanning(); - for (int c=0;c<=5;c++) uart_byte(echo_addr[c]); - uart_writeText("\n"); + for (int c=0;c<=5;c++) debugch(echo_addr[c]); + debugcrlf(); - // Ask to connect to the echo - uart_writeText("Connecting to echo: "); + // Connecting to echo + debugstr("Connecting to echo: "); connect(echo_addr); while (!connected) bt_conn(); - uart_writeText("\n"); + debugstr("Connected!"); + debugcrlf(); // Get the characteristic value - uart_writeText("Sending read request: "); - uart_hex(connection_handle); uart_writeText("\n"); + debugstr("Sending read request: "); + debughex(connection_handle); debugcrlf(); sendACLsubscribe(connection_handle); - // Into the main infinite loop - uart_writeText("Waiting for input...\n"); + // Enter an infinite loop + debugstr("Going loopy..."); while (1) { acl_poll(); uart_update(); } } + +void run_eddystone(void) { + // Start advertising + debugstr("Setting event mask... "); + setLEeventmask(0xff); + debugstr("Starting advertsing... "); + startActiveAdvertising(); + + // Enter an infinite loop + debugstr("Going loopy..."); + while (1) { + uart_update(); + } +} + +void main() +{ + fb_init(); + uart_init(); + bt_init(); + + debugstr("Initialising Bluetooth: "); + debugstr(">> reset: "); + bt_reset(); + debugstr(">> firmware load: "); + bt_loadfirmware(); + debugstr(">> set baud: "); + bt_setbaud(); + debugstr(">> set bdaddr: "); + bt_setbdaddr(); + + // Print the BD_ADDR + unsigned char local_addr[6]; + bt_getbdaddr(local_addr); + for (int c=5;c>=0;c--) debugch(local_addr[c]); + debugcrlf(); + + // Test out the scanning + run_search(); +} diff --git a/part8-breakout-ble/Makefile b/part8-breakout-ble/Makefile index 3ecc081..143c51b 100644 --- a/part8-breakout-ble/Makefile +++ b/part8-breakout-ble/Makefile @@ -1,22 +1,22 @@ CFILES = $(wildcard *.c) OFILES = $(CFILES:.c=.o) -GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin +LLVMPATH = /opt/homebrew/opt/llvm/bin +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -mcpu=cortex-a72+nosimd all: clean kernel8.img boot.o: boot.S - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + clang --target=aarch64-elf $(GCCFLAGS) -c boot.S -o boot.o BCM4345C0.o : BCM4345C0.hcd - $(GCCPATH)/aarch64-none-elf-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@ + $(LLVMPATH)/llvm-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@ %.o: %.c - $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + clang --target=aarch64-elf $(GCCFLAGS) -c $< -o $@ kernel8.img: boot.o $(OFILES) BCM4345C0.o - $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) BCM4345C0.o -T link.ld -o kernel8.elf - $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + $(LLVMPATH)/ld.lld -m aarch64elf -nostdlib boot.o $(OFILES) BCM4345C0.o -T link.ld -o kernel8.elf + $(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img clean: /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part8-breakout-ble/Makefile.gcc b/part8-breakout-ble/Makefile.gcc new file mode 100644 index 0000000..3ecc081 --- /dev/null +++ b/part8-breakout-ble/Makefile.gcc @@ -0,0 +1,22 @@ +CFILES = $(wildcard *.c) +OFILES = $(CFILES:.c=.o) +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles +GCCPATH = ../../gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin + +all: clean kernel8.img + +boot.o: boot.S + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + +BCM4345C0.o : BCM4345C0.hcd + $(GCCPATH)/aarch64-none-elf-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@ + +%.o: %.c + $(GCCPATH)/aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + +kernel8.img: boot.o $(OFILES) BCM4345C0.o + $(GCCPATH)/aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) BCM4345C0.o -T link.ld -o kernel8.elf + $(GCCPATH)/aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + +clean: + /bin/rm kernel8.elf *.o *.img > /dev/null 2> /dev/null || true diff --git a/part8-breakout-ble/Makefile.gcc.windows b/part8-breakout-ble/Makefile.gcc.windows new file mode 100644 index 0000000..349a29b --- /dev/null +++ b/part8-breakout-ble/Makefile.gcc.windows @@ -0,0 +1,22 @@ +CFILES = $(wildcard *.c) +OFILES = $(CFILES:.c=.o) +GCCFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles +GCCPATH = ..\..\gcc-arm-10.2-2020.11-mingw-w64-i686-aarch64-none-elf\bin + +all: clean kernel8.img + +boot.o: boot.S + $(GCCPATH)\aarch64-none-elf-gcc $(GCCFLAGS) -c boot.S -o boot.o + +BCM4345C0.o : BCM4345C0.hcd + $(GCCPATH)\aarch64-none-elf-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@ + +%.o: %.c + $(GCCPATH)\aarch64-none-elf-gcc $(GCCFLAGS) -c $< -o $@ + +kernel8.img: boot.o $(OFILES) BCM4345C0.o + $(GCCPATH)\aarch64-none-elf-ld -nostdlib -nostartfiles boot.o $(OFILES) BCM4345C0.o -T link.ld -o kernel8.elf + $(GCCPATH)\aarch64-none-elf-objcopy -O binary kernel8.elf kernel8.img + +clean: + del kernel8.elf *.o *.img diff --git a/part8-breakout-ble/bt.c b/part8-breakout-ble/bt.c index c91c854..5fbf048 100644 --- a/part8-breakout-ble/bt.c +++ b/part8-breakout-ble/bt.c @@ -1,6 +1,8 @@ #include "io.h" #include "fb.h" +volatile unsigned char *params = (unsigned char *)SAFE_ADDRESS; + // UART0 enum { @@ -91,7 +93,7 @@ enum { unsigned char empty[] = {}; -int hciCommandBytes(unsigned char *opcodebytes, unsigned char *data, unsigned char length) +int hciCommandBytes(volatile unsigned char *opcodebytes, volatile unsigned char *data, unsigned char length) { unsigned char c=0; @@ -128,7 +130,7 @@ int hciCommandBytes(unsigned char *opcodebytes, unsigned char *data, unsigned ch return 0; } -int hciCommand(unsigned short ogf, unsigned short ocf, unsigned char *data, unsigned char length) +int hciCommand(unsigned short ogf, unsigned short ocf, volatile unsigned char *data, unsigned char length) { unsigned short opcode = ogf << 10 | ocf; unsigned char opcodebytes[2] = { lo(opcode), hi(opcode) }; @@ -151,11 +153,12 @@ void bt_loadfirmware() unsigned int size = (long)&_binary_BCM4345C0_hcd_size; while (c < size) { - unsigned char opcodebytes[] = { _binary_BCM4345C0_hcd_start[c], _binary_BCM4345C0_hcd_start[c+1] }; + params[0] = _binary_BCM4345C0_hcd_start[c]; + params[1] = _binary_BCM4345C0_hcd_start[c+1]; unsigned char length = _binary_BCM4345C0_hcd_start[c+2]; unsigned char *data = &(_binary_BCM4345C0_hcd_start[c+3]); - if (hciCommandBytes(opcodebytes, data, length)) { + if (hciCommandBytes(params, data, length)) { uart_writeText("Firmware data load failed\n"); break; } @@ -167,13 +170,23 @@ void bt_loadfirmware() void bt_setbaud() { - static unsigned char params[] = { 0, 0, 0x00, 0xc2, 0x01, 0x00 }; // little endian, 115200 + params[0] = 0; + params[1] = 0; + params[2] = 0x00; + params[3] = 0xc2; + params[4] = 0x01; + params[5] = 0x00; // little endian, 115200 if (hciCommand(OGF_VENDOR, COMMAND_SET_BAUD, params, 6)) uart_writeText("bt_setbaud() failed\n"); } void bt_setbdaddr() { - static unsigned char params[] = { 0xee, 0xff, 0xc0, 0xee, 0xff, 0xc0 }; // reversed + params[0] = 0xee; + params[1] = 0xff; + params[2] = 0xc0; + params[3] = 0xee; + params[4] = 0xff; + params[5] = 0xc0; // reversed if (hciCommand(OGF_VENDOR, COMMAND_SET_BDADDR, params, 6)) uart_writeText("bt_setbdaddr() failed\n"); } @@ -213,59 +226,87 @@ void sendACLsubscribe(unsigned int handle) bt_writeByte(lo(channel)); bt_writeByte(hi(channel)); - unsigned char params[] = { 0x12, 0x2b, 0x00, 0x01, 0x00 }; + params[0] = 0x12; + params[1] = 0x2b; + params[2] = 0x00; + params[3] = 0x01; + params[4] = 0x00; unsigned int c=0; + while (c++ { diff --git a/part8-breakout-ble/fb.c b/part8-breakout-ble/fb.c index 8996bba..5085c8f 100644 --- a/part8-breakout-ble/fb.c +++ b/part8-breakout-ble/fb.c @@ -2,9 +2,14 @@ #include "mb.h" #include "terminal.h" +#define DEBUG 1 + unsigned int width, height, pitch, isrgb; unsigned char *fb; +int curx = 0; +int cury = 0; + void fb_init() { mbox[0] = 35*4; // Length of message in bytes @@ -210,3 +215,47 @@ void wait_msec(unsigned int n) t+=((f/1000)*n)/1000; do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(r= 1920) { + curx = 0; cury += 8; + } + if (cury + 8 >= 1080) { + cury = 0; + } + if (DEBUG == 1) drawString(curx, cury, str, 0x0f, 1); + curx += (strlen(str) * 8); +} + +void debugcrlf(void) { + curx = 0; cury += 8; +} + +void debugch(unsigned char b) { + unsigned int n; + int c; + for(c=4;c>=0;c-=4) { + n=(b>>c)&0xF; + n+=n>9?0x37:0x30; + debugstr((char *)&n); + } + debugstr(" "); +} + +void debughex(unsigned int d) { + unsigned int n; + int c; + for(c=28;c>=0;c-=4) { + n=(d>>c)&0xF; + n+=n>9?0x37:0x30; + debugstr((char *)&n); + } + debugstr(" "); +} diff --git a/part8-breakout-ble/fb.h b/part8-breakout-ble/fb.h index 7fc550f..8899bb9 100644 --- a/part8-breakout-ble/fb.h +++ b/part8-breakout-ble/fb.h @@ -7,3 +7,7 @@ void drawCircle(int x0, int y0, int radius, unsigned char attr, int fill); void drawLine(int x1, int y1, int x2, int y2, unsigned char attr); void moveRectAbs(int oldx, int oldy, int width, int height, int newx, int newy, unsigned char attr); void wait_msec(unsigned int n); +void debugstr(char *str); +void debugcrlf(void); +void debugch(unsigned char b); +void debughex(unsigned int d); diff --git a/part8-breakout-ble/io.h b/part8-breakout-ble/io.h index 8547cc0..b2f483e 100644 --- a/part8-breakout-ble/io.h +++ b/part8-breakout-ble/io.h @@ -1,4 +1,5 @@ #define PERIPHERAL_BASE 0xFE000000 +#define SAFE_ADDRESS 0x00210000 // Somewhere safe to store a lot of data void uart_init(); void uart_writeText(char *buffer); diff --git a/part8-breakout-ble/kernel.c b/part8-breakout-ble/kernel.c index bbc4e70..f143fe6 100644 --- a/part8-breakout-ble/kernel.c +++ b/part8-breakout-ble/kernel.c @@ -1,9 +1,7 @@ -#include "fb.h" #include "io.h" #include "bt.h" +#include "fb.h" -// The BLE stuff -#define memcmp __builtin_memcmp #define MAX_MSG_LEN 50 #define MAX_READ_RUN 100 @@ -23,10 +21,22 @@ enum { unsigned int got_echo_sid = 0; unsigned int got_echo_name = 0; unsigned char echo_addr[6]; + unsigned int connected = 0; unsigned int connection_handle = 0; + unsigned char dir = 50; +int memcmp(const char *str1, const char *str2, int count) { + const char *s1 = (const char*)str1; + const char *s2 = (const char*)str2; + + while (count-- > 0) { + if (*s1++ != *s2++) return s1[-1] < s2[-1] ? -1 : 1; + } + return 0; +} + void hci_poll2(unsigned char byte) { switch (poll_state) { @@ -72,62 +82,51 @@ unsigned char *hci_poll() return 0; } -void bt_search() -{ +void bt_search(void) { unsigned char *buf; while ( (buf = hci_poll()) ) { if (data_len >= 2) { if (buf[0] == LE_ADREPORT_CODE) { - unsigned char numreports = buf[1]; - - if (numreports == 1) { - unsigned char event_type = buf[2]; - - if (event_type == 0x00) { - unsigned char buf_len = buf[10]; + if (buf[1] == 1) { // num_reports + if (buf[2] == 0) { // event_type + int bufindex = 0; unsigned char ad_len = buf[11]; - if (ad_len < data_len && buf_len + 11 == data_len - 1) { - for (int c=9;c>=4;c--) echo_addr[9-c] = buf[c]; - buf += 11; + for (int c=9;c>=4;c--) echo_addr[9-c] = buf[bufindex + c]; // save the mac address + bufindex += 11; - got_echo_sid = 0; got_echo_name = 0; // Reset the search state machine - do { - ad_len = buf[0]; - unsigned char ad_type = buf[1]; - buf += 2; + got_echo_sid = 0; got_echo_name = 0; // Reset the search state machine + do { + ad_len = buf[bufindex]; + unsigned char ad_type = buf[bufindex + 1]; + bufindex += 2; - if (ad_len >= 2) { - if (ad_type == 0x03) { - unsigned int sid=0; + if (ad_len >= 2) { + if (ad_type == 0x03) { + unsigned int sid = buf[bufindex] | (buf[bufindex + 1] << 8); + if (sid == 0xEC00) { + got_echo_sid = 1; + debugstr("got sid... "); + } + } else if (ad_type == 0x09) { + char remote_name[ad_len - 1]; + unsigned int d=0; - for (int d=0;d= 2) { if (buf[0] == LE_CONNECT_CODE && !connected) { connected = !buf[1]; - uart_hex(connected); uart_writeText(" "); + debughex(connected); debugstr(" "); connection_handle = buf[2] | (buf[3] << 8); - uart_hex(connection_handle); uart_writeText(" "); + debughex(connection_handle); debugstr(" "); } } } @@ -183,8 +182,10 @@ enum { OBJ_BALL = 3 }; +#define OBJS_ADDRESS 0x02200000 // Somewhere safe to store a lot of data + unsigned int numobjs = 0; -struct Object objects[(ROWS * COLS) + (2 * NUM_LIVES)]; +struct Object *objects = (struct Object *)OBJS_ADDRESS; struct Object *ball; struct Object *paddle; int paddlewidth = 80; @@ -226,7 +227,7 @@ void initBricks() int brickwidth = 32; int brickheight = 8; int brickspacer = 20; - int brickcols[5] = { 0x11, 0x22, 0xEE, 0x44, 0x66 }; + static int brickcols[] = { 0x11, 0x22, 0xEE, 0x44, 0x66 }; int ybrick = MARGIN + brickheight; @@ -288,13 +289,10 @@ void drawScoreboard(int score, int lives) char tens = score / 10; score -= (10 * tens); char ones = score; - char string[] = "Score: 0xx Lives: x\0\0"; - - string[8] = tens + 0x30; - string[9] = ones + 0x30; - string[20] = (char)lives + 0x30; - - drawString((WIDTH/2)-252, MARGIN-25, string, 0x0f, 3); + drawString((WIDTH/2)-252, MARGIN-25, "Score: 0 Lives: ", 0x0f, 3); + drawChar(tens + 0x30, (WIDTH/2)-252 + (8*8*3), MARGIN-25, 0x0f, 3); + drawChar(ones + 0x30, (WIDTH/2)-252 + (8*9*3), MARGIN-25, 0x0f, 3); + drawChar((char)lives + 0x30, (WIDTH/2)-252 + (8*20*3), MARGIN-25, 0x0f, 3); } void acl_poll() @@ -407,45 +405,55 @@ void breakout() void main() { + fb_init(); uart_init(); - bt_init(); - uart_writeText("Initialising Bluetooth: "); + + debugstr("Initialising Bluetooth: "); + debugstr(">> reset: "); bt_reset(); + debugstr(">> firmware load: "); bt_loadfirmware(); + debugstr(">> set baud: "); bt_setbaud(); + debugstr(">> set bdaddr: "); bt_setbdaddr(); // Print the BD_ADDR unsigned char local_addr[6]; bt_getbdaddr(local_addr); - for (int c=5;c>=0;c--) uart_byte(local_addr[c]); - uart_writeText("\n"); + for (int c=5;c>=0;c--) debugch(local_addr[c]); + debugcrlf(); - // Start scanning for echo + // Start scanning + debugstr("Setting event mask... "); setLEeventmask(0xff); + debugstr("Starting scanning... "); startActiveScanning(); - uart_writeText("Waiting for echo: "); + + // Search for the echo + debugstr("Waiting..."); + debugcrlf(); while (!(got_echo_sid && got_echo_name)) bt_search(); stopScanning(); - for (int c=0;c<=5;c++) uart_byte(echo_addr[c]); - uart_writeText("\n"); + for (int c=0;c<=5;c++) debugch(echo_addr[c]); + debugcrlf(); - // Ask to connect to the echo - uart_writeText("Connecting to echo: "); + // Connecting to echo + debugstr("Connecting to echo: "); connect(echo_addr); while (!connected) bt_conn(); - uart_writeText("\n"); + debugstr("Connected!"); + debugcrlf(); // Subscribe to updates - uart_writeText("Sending subscribe request: "); - uart_hex(connection_handle); uart_writeText("\n"); + debugstr("Sending read request: "); + debughex(connection_handle); debugcrlf(); sendACLsubscribe(connection_handle); // Begin the game - uart_writeText("Let the game commence...\n"); + debugstr("Let the game commence...\n"); wait_msec(0x100000); // Wait a second - fb_init(); while (1) breakout(); }