diff --git a/part12-wgt/Makefile b/part12-wgt/Makefile index 8cf1829..b8af9fd 100644 --- a/part12-wgt/Makefile +++ b/part12-wgt/Makefile @@ -8,6 +8,9 @@ all: clean kernel8.img boot/boot.o: boot/boot.S $(LLVMPATH)/clang --target=aarch64-elf $(CLANGFLAGS) -c $< -o $@ +bin/BCM4345C0.o : bin/BCM4345C0.hcd + $(LLVMPATH)/llvm-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@ + bin/wgt1pal.o: bin/wgt1.pal $(LLVMPATH)/llvm-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@ @@ -35,8 +38,8 @@ bin/mousespr.o: bin/mouse.spr %.o: %.c $(LLVMPATH)/clang --target=aarch64-elf $(CLANGFLAGS) -c $< -o $@ -kernel8.img: boot/boot.o $(OFILES) bin/wgt1pal.o bin/wgt1blk.o bin/wgt2blk.o bin/lettersspr.o bin/spacespr.o bin/invaderspr.o bin/mousespr.o bin/breakspr.o - $(LLVMPATH)/ld.lld -m aarch64elf -nostdlib boot/boot.o $(OFILES) bin/wgt1pal.o bin/wgt1blk.o bin/wgt2blk.o bin/lettersspr.o bin/spacespr.o bin/invaderspr.o bin/mousespr.o bin/breakspr.o -T boot/link.ld -o kernel8.elf +kernel8.img: boot/boot.o $(OFILES) bin/BCM4345C0.o bin/wgt1pal.o bin/wgt1blk.o bin/wgt2blk.o bin/lettersspr.o bin/spacespr.o bin/invaderspr.o bin/mousespr.o bin/breakspr.o + $(LLVMPATH)/ld.lld -m aarch64elf -nostdlib boot/boot.o $(OFILES) bin/BCM4345C0.o bin/wgt1pal.o bin/wgt1blk.o bin/wgt2blk.o bin/lettersspr.o bin/spacespr.o bin/invaderspr.o bin/mousespr.o bin/breakspr.o -T boot/link.ld -o kernel8.elf $(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img clean: diff --git a/part12-wgt/bin/BCM4345C0.hcd b/part12-wgt/bin/BCM4345C0.hcd new file mode 100644 index 0000000..f4b2438 Binary files /dev/null and b/part12-wgt/bin/BCM4345C0.hcd differ diff --git a/part12-wgt/controller/characteristic.js b/part12-wgt/controller/characteristic.js new file mode 100644 index 0000000..d898536 --- /dev/null +++ b/part12-wgt/controller/characteristic.js @@ -0,0 +1,52 @@ +var util = require('util'); + +var bleno = require('bleno-mac'); + +var BlenoCharacteristic = bleno.Characteristic; + +var EchoCharacteristic = function() { + EchoCharacteristic.super_.call(this, { + uuid: 'ec0e', + properties: ['read', 'write', 'notify'], + value: null + }); + + this._value = new Buffer(0); + this._updateValueCallback = null; +}; + +util.inherits(EchoCharacteristic, BlenoCharacteristic); + +EchoCharacteristic.prototype.onReadRequest = function(offset, callback) { + console.log('EchoCharacteristic - onReadRequest: value = ' + this._value.toString('hex')); + + callback(this.RESULT_SUCCESS, this._value); +}; + +EchoCharacteristic.prototype.onWriteRequest = function(data, offset, withoutResponse, callback) { + this._value = data; + + console.log('EchoCharacteristic - onWriteRequest: value = ' + this._value.toString('hex')); + + if (this._updateValueCallback) { + console.log('EchoCharacteristic - onWriteRequest: notifying'); + + this._updateValueCallback(this._value); + } + + callback(this.RESULT_SUCCESS); +}; + +EchoCharacteristic.prototype.onSubscribe = function(maxValueSize, updateValueCallback) { + console.log('EchoCharacteristic - onSubscribe'); + + this._updateValueCallback = updateValueCallback; +}; + +EchoCharacteristic.prototype.onUnsubscribe = function() { + console.log('EchoCharacteristic - onUnsubscribe'); + + this._updateValueCallback = null; +}; + +module.exports = EchoCharacteristic; diff --git a/part12-wgt/controller/main.js b/part12-wgt/controller/main.js new file mode 100644 index 0000000..d2b03a3 --- /dev/null +++ b/part12-wgt/controller/main.js @@ -0,0 +1,53 @@ +var bleno = require('bleno-mac'); + +var BlenoPrimaryService = bleno.PrimaryService; + +var EchoCharacteristic = require('./characteristic'); + +console.log('bleno - echo'); + +var e = new EchoCharacteristic(); + +bleno.on('stateChange', function(state) { + console.log('on -> stateChange: ' + state); + + if (state === 'poweredOn') { + bleno.startAdvertising('echo', ['ec00']); + } else { + bleno.stopAdvertising(); + } +}); + +bleno.on('advertisingStart', function(error) { + console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success')); + + if (!error) { + bleno.setServices([ + new BlenoPrimaryService({ + uuid: 'ec00', + characteristics: [ + e + ] + }) + ]); + } +}); + +var ioHook = require('iohook'); + +var buf = Buffer.allocUnsafe(1); +var obuf = Buffer.allocUnsafe(1); +const scrwidth = 1440; +const divisor = scrwidth / 160; + +ioHook.on( 'mousemove', event => { + buf.writeUInt8(Math.round(event.x / divisor), 0); + + if (Buffer.compare(buf, obuf)) { + e._value = buf; + if (e._updateValueCallback) e._updateValueCallback(e._value); + buf.copy(obuf); + } +}); + +ioHook.start(); diff --git a/part12-wgt/examples/wgt02.c b/part12-wgt/examples/wgt02.c index b102638..4ab17e3 100644 --- a/part12-wgt/examples/wgt02.c +++ b/part12-wgt/examples/wgt02.c @@ -20,19 +20,6 @@ unsigned long rand(void) return state0 + state1; } -void wait_msec(unsigned int n) -{ - register unsigned long f, t, r; - - // Get the current counter frequency - asm volatile ("mrs %0, cntfrq_el0" : "=r"(f)); - // Read the current counter - asm volatile ("mrs %0, cntpct_el0" : "=r"(t)); - // Calculate expire value for counter - t+=((f/1000)*n)/1000; - do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(r> 17; + s1 ^= s0; + s1 ^= s0 >> 26; + state1 = s1; + + return state0 + state1; +} + +// ######## STUB FUNCTIONS ######## + +unsigned int kb = 0; + +unsigned int kbhit(void) { + kb++; + return kb / 500; +} + +void getch(void) { + wait_msec(0x500000); + kb = 0; +} + +// ######## WGT EXAMPLES ######## + +void wgt18() +{ + block screen1; /* one virtual screen */ + block circ[4]; /* and four circle images */ + short y; + + set_clock_rate(get_max_clock()); + mem_init(); + vga256 (); + + start_core2(minit); // Start the comms engine (core 2) + while (!comms_up); // Wait for comms up + + screen1 = wnewblock (0, 0, 319, 199); + + for (y = 0; y < 4; y++) + { + wsetcolor (vgapal[40 + y * 5]); + wfill_circle (30, 30, 20 + y * 4); + /* draw a circle with a box cut out in middle */ + /* Note that the circle turns into a square when we increase the radius + because I'm still grabbing the same area from the wnewblock... */ + + wsetcolor (vgapal[0]); + wbar (20, 20, 40, 40); + circ[y] = wnewblock (10, 10, 50, 50); /* get the sprite */ + } + + wsetscreen (screen1); + + do { + for (y = 0; y < 200; y++) + { + wsetcolor (vgapal[y]); + wline (0, y, 319, y); /* clear the screen by drawing horz lines (fast) */ + } + + wputblock (mx, my, circ[0], 1); + wputblock (279 - mx, my, circ[1], 1); + wputblock (mx, 159 - my, circ[2], 1); + wputblock (279 - mx, 159 - my, circ[3], 1); + /* Put four blocks on the screen depending on where the mouse is. */ + /* The first one displayed is the one in the back. */ + + wcopyscreen (0, 0, 319, 199, screen1, 0, 0, NULL); + /* copy the whole screen */ + /* notice how we never use wnormscreen at all! */ + + } while (1); + + mdeinit(); + wfreeblock (screen1); + for (y = 0; y < 4; y ++) + wfreeblock (circ[y]); +} + +void main() +{ + wgt18(); + while (1); +} diff --git a/part12-wgt/examples/wgt21.c b/part12-wgt/examples/wgt21.c index 8dddc18..7827c7b 100644 --- a/part12-wgt/examples/wgt21.c +++ b/part12-wgt/examples/wgt21.c @@ -21,19 +21,6 @@ unsigned long rand(void) return state0 + state1; } -void wait_msec(unsigned int n) -{ - register unsigned long f, t, r; - - // Get the current counter frequency - asm volatile ("mrs %0, cntfrq_el0" : "=r"(f)); - // Read the current counter - asm volatile ("mrs %0, cntpct_el0" : "=r"(t)); - // Calculate expire value for counter - t+=((f/1000)*n)/1000; - do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(r> 8); } + +unsigned int bt_isReadByteReady() { return (!(mmio_read(ARM_UART0_FR) & 0x10)); } + +unsigned char bt_readByte() +{ + unsigned char ch = lo(mmio_read(ARM_UART0_DR)); + return ch; +} + +unsigned char bt_waitReadByte() +{ + while (!bt_isReadByteReady()); + return bt_readByte(); +} + +void bt_writeByte(char byte) +{ + while ((mmio_read(ARM_UART0_FR) & 0x20) != 0); + mmio_write(ARM_UART0_DR, (unsigned int)byte); +} + +void bt_flushrx() +{ + while (bt_isReadByteReady()) bt_readByte(); +} + +void wait_msec(unsigned int n) +{ + register unsigned long f, t, r; + + // Get the current counter frequency + asm volatile ("mrs %0, cntfrq_el0" : "=r"(f)); + // Read the current counter + asm volatile ("mrs %0, cntpct_el0" : "=r"(t)); + // Calculate expire value for counter + t+=((f/1000)*n)/1000; + do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(r MAX_MSG_LEN) poll_state = 0; + else { + poll_state = 3; + data_len = byte; + } + break; + default: + data_buf[poll_state - 3] = byte; + if (poll_state == data_len + 3 - 1) { + messages_received++; + poll_state = 0; + } else poll_state++; + } +} + +unsigned char *hci_poll() +{ + unsigned int goal = messages_received + 1; + + if (bt_isReadByteReady()) { + unsigned int run = 0; + + while (run < MAX_READ_RUN && messages_received < goal && bt_isReadByteReady()) { + unsigned char byte = bt_readByte(); + hci_poll2(byte); + run++; + } + if (run == MAX_READ_RUN) return 0; + else return data_buf; + } + return 0; +} + +void bt_search(void) { + unsigned char *buf; + + while ( (buf = hci_poll()) ) { + if (data_len >= 2) { + if (buf[0] == LE_ADREPORT_CODE) { + if (buf[1] == 1) { // num_reports + if (buf[2] == 0) { // event_type + int bufindex = 0; + unsigned char ad_len = 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[bufindex]; + unsigned char ad_type = buf[bufindex + 1]; + bufindex += 2; + + if (ad_len >= 2) { + if (ad_type == 0x03) { + unsigned int sid = buf[bufindex] | (buf[bufindex + 1] << 8); + if (sid == 0xEC00) { + got_echo_sid = 1; + } + } else if (ad_type == 0x09) { + char remote_name[ad_len - 1]; + unsigned int d=0; + + while (d= 2 && buf[0] == LE_CONNECT_CODE) { + connected = !*(buf+1); + connection_handle = *(buf+2) | (*(buf+3) << 8); + + if (connection_handle == 0) delay(1); + } + } +} + +void acl_poll() +{ + while (bt_isReadByteReady()) { + unsigned char byte = bt_waitReadByte(); + + if (byte == HCI_EVENT_PKT) { + bt_waitReadByte(); // opcode + unsigned char length = bt_waitReadByte(); + for (int i=0;i 7) { + for (int i=0;i