diff --git a/part7-bluetooth/bt.h b/part7-bluetooth/bt.h index 192fdb5..21340ed 100644 --- a/part7-bluetooth/bt.h +++ b/part7-bluetooth/bt.h @@ -12,5 +12,4 @@ void startActiveScanning(); void stopScanning(); void startActiveAdvertising(); void connect(unsigned char *addr); -void bt_flushrx(); void sendACLsubscribe(unsigned int handle); diff --git a/part8-breakout-ble/Makefile b/part8-breakout-ble/Makefile index 3ecc081..44bd023 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 -O0 -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/bt.c b/part8-breakout-ble/bt.c index c91c854..7d148fe 100644 --- a/part8-breakout-ble/bt.c +++ b/part8-breakout-ble/bt.c @@ -1,6 +1,8 @@ #include "io.h" #include "fb.h" +unsigned char *params = (unsigned char *)SAFE_ADDRESS; + // UART0 enum { @@ -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++ { diff --git a/part8-breakout-ble/fb.c b/part8-breakout-ble/fb.c index 8996bba..020dcae 100644 --- a/part8-breakout-ble/fb.c +++ b/part8-breakout-ble/fb.c @@ -5,6 +5,9 @@ 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 +213,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; + } + 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..c2c76f3 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,11 @@ 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 +228,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 +290,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() @@ -370,7 +369,7 @@ void breakout() } } - wait_msec(0x186A); + //wait_msec(0x186A); moveObjectAbs(ball, ball->x + velocity_x, ball->y + velocity_y); // Check we're in the game arena still @@ -407,45 +406,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(); }