mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-22 10:10:45 +00:00
Added mouse.c and examples/wgt18.c to exercise it
This commit is contained in:
parent
250fca0493
commit
95f7cc8baf
30 changed files with 827 additions and 263 deletions
|
@ -8,6 +8,9 @@ all: clean kernel8.img
|
||||||
boot/boot.o: boot/boot.S
|
boot/boot.o: boot/boot.S
|
||||||
$(LLVMPATH)/clang --target=aarch64-elf $(CLANGFLAGS) -c $< -o $@
|
$(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
|
bin/wgt1pal.o: bin/wgt1.pal
|
||||||
$(LLVMPATH)/llvm-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@
|
$(LLVMPATH)/llvm-objcopy -I binary -O elf64-littleaarch64 -B aarch64 $< $@
|
||||||
|
|
||||||
|
@ -35,8 +38,8 @@ bin/mousespr.o: bin/mouse.spr
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(LLVMPATH)/clang --target=aarch64-elf $(CLANGFLAGS) -c $< -o $@
|
$(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
|
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/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)/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
|
$(LLVMPATH)/llvm-objcopy -O binary kernel8.elf kernel8.img
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
BIN
part12-wgt/bin/BCM4345C0.hcd
Normal file
BIN
part12-wgt/bin/BCM4345C0.hcd
Normal file
Binary file not shown.
52
part12-wgt/controller/characteristic.js
Normal file
52
part12-wgt/controller/characteristic.js
Normal file
|
@ -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;
|
53
part12-wgt/controller/main.js
Normal file
53
part12-wgt/controller/main.js
Normal file
|
@ -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();
|
|
@ -20,19 +20,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -22,19 +22,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -20,19 +20,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -22,19 +22,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -22,19 +22,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -22,19 +22,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
101
part12-wgt/examples/wgt18.c
Normal file
101
part12-wgt/examples/wgt18.c
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
#include "wgt.h"
|
||||||
|
#include "include/mem.h"
|
||||||
|
#include "include/multicore.h"
|
||||||
|
|
||||||
|
// ######## REQUIRED FUNCTIONS ########
|
||||||
|
|
||||||
|
unsigned long state0 = 1000;
|
||||||
|
unsigned long state1 = 2000;
|
||||||
|
|
||||||
|
unsigned long rand(void)
|
||||||
|
{
|
||||||
|
unsigned long s1 = state0;
|
||||||
|
unsigned long s0 = state1;
|
||||||
|
|
||||||
|
state0 = s0;
|
||||||
|
s1 ^= s1 << 23;
|
||||||
|
s1 ^= s1 >> 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);
|
||||||
|
}
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
|
@ -21,19 +21,6 @@ unsigned long rand(void)
|
||||||
return state0 + state1;
|
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<t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ######## STUB FUNCTIONS ########
|
// ######## STUB FUNCTIONS ########
|
||||||
|
|
||||||
unsigned int kb = 0;
|
unsigned int kb = 0;
|
||||||
|
|
15
part12-wgt/include/bt.h
Normal file
15
part12-wgt/include/bt.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
void bt_reset();
|
||||||
|
void bt_loadfirmware();
|
||||||
|
void bt_setbaud();
|
||||||
|
void bt_setbdaddr();
|
||||||
|
void bt_getbdaddr(unsigned char *bdaddr);
|
||||||
|
void bt_init();
|
||||||
|
unsigned int bt_isReadByteReady();
|
||||||
|
unsigned char bt_readByte();
|
||||||
|
unsigned char bt_waitReadByte();
|
||||||
|
void setLEeventmask(unsigned char mask);
|
||||||
|
void startActiveScanning();
|
||||||
|
void stopScanning();
|
||||||
|
void startActiveAdvertising();
|
||||||
|
void connect(unsigned char *addr);
|
||||||
|
void sendACLsubscribe(unsigned int handle);
|
|
@ -1,5 +1,4 @@
|
||||||
#define PERIPHERAL_BASE 0xFE000000
|
#define PERIPHERAL_BASE 0xFE000000
|
||||||
#define LEGACY_BASE 0x7E000000
|
|
||||||
|
|
||||||
void uart_init();
|
void uart_init();
|
||||||
void uart_writeText(char *buffer);
|
void uart_writeText(char *buffer);
|
||||||
|
|
368
part12-wgt/lib/bt.c
Normal file
368
part12-wgt/lib/bt.c
Normal file
|
@ -0,0 +1,368 @@
|
||||||
|
#include "../include/io.h"
|
||||||
|
|
||||||
|
// UART0
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ARM_UART0_BASE = PERIPHERAL_BASE + 0x201000,
|
||||||
|
ARM_UART0_DR = ARM_UART0_BASE + 0x00,
|
||||||
|
ARM_UART0_FR = ARM_UART0_BASE + 0x18,
|
||||||
|
ARM_UART0_IBRD = ARM_UART0_BASE + 0x24,
|
||||||
|
ARM_UART0_FBRD = ARM_UART0_BASE + 0x28,
|
||||||
|
ARM_UART0_LCRH = ARM_UART0_BASE + 0x2C,
|
||||||
|
ARM_UART0_CR = ARM_UART0_BASE + 0x30,
|
||||||
|
ARM_UART0_IFLS = ARM_UART0_BASE + 0x34,
|
||||||
|
ARM_UART0_IMSC = ARM_UART0_BASE + 0x38,
|
||||||
|
ARM_UART0_RIS = ARM_UART0_BASE + 0x3C,
|
||||||
|
ARM_UART0_MIS = ARM_UART0_BASE + 0x40,
|
||||||
|
ARM_UART0_ICR = ARM_UART0_BASE + 0x44
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char lo(unsigned int val) { return (unsigned char)(val & 0xff); }
|
||||||
|
unsigned char hi(unsigned int val) { return (unsigned char)((val & 0xff00) >> 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<t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_init()
|
||||||
|
{
|
||||||
|
gpio_useAsAlt3(30);
|
||||||
|
gpio_useAsAlt3(31);
|
||||||
|
gpio_useAsAlt3(32);
|
||||||
|
gpio_useAsAlt3(33);
|
||||||
|
|
||||||
|
bt_flushrx();
|
||||||
|
|
||||||
|
mmio_write(ARM_UART0_IMSC, 0x00);
|
||||||
|
mmio_write(ARM_UART0_ICR, 0x7ff);
|
||||||
|
mmio_write(ARM_UART0_IBRD, 0x1a);
|
||||||
|
mmio_write(ARM_UART0_FBRD, 0x03);
|
||||||
|
mmio_write(ARM_UART0_IFLS, 0x08);
|
||||||
|
mmio_write(ARM_UART0_LCRH, 0x70);
|
||||||
|
mmio_write(ARM_UART0_CR, 0xB01);
|
||||||
|
mmio_write(ARM_UART0_IMSC, 0x430);
|
||||||
|
|
||||||
|
wait_msec(0x100000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HOST SETUP
|
||||||
|
|
||||||
|
enum {
|
||||||
|
OGF_HOST_CONTROL = 0x03,
|
||||||
|
OGF_LE_CONTROL = 0x08,
|
||||||
|
OGF_VENDOR = 0x3f,
|
||||||
|
|
||||||
|
COMMAND_SET_BDADDR = 0x01,
|
||||||
|
COMMAND_RESET_CHIP = 0x03,
|
||||||
|
COMMAND_SET_BAUD = 0x18,
|
||||||
|
COMMAND_LOAD_FIRMWARE = 0x2e,
|
||||||
|
|
||||||
|
HCI_COMMAND_PKT = 0x01,
|
||||||
|
HCI_ACL_PKT = 0x02,
|
||||||
|
HCI_EVENT_PKT = 0x04,
|
||||||
|
COMMAND_COMPLETE_CODE = 0x0e,
|
||||||
|
CONNECT_COMPLETE_CODE = 0x0f,
|
||||||
|
|
||||||
|
LL_SCAN_ACTIVE = 0x01,
|
||||||
|
LL_ADV_NONCONN_IND = 0x03
|
||||||
|
};
|
||||||
|
|
||||||
|
int hciCommandBytes(unsigned char *opcodebytes, volatile unsigned char *data, unsigned char length)
|
||||||
|
{
|
||||||
|
unsigned char c=0;
|
||||||
|
|
||||||
|
bt_writeByte(HCI_COMMAND_PKT);
|
||||||
|
bt_writeByte(opcodebytes[0]);
|
||||||
|
bt_writeByte(opcodebytes[1]);
|
||||||
|
bt_writeByte(length);
|
||||||
|
|
||||||
|
while (c++<length) bt_writeByte(*data++);
|
||||||
|
|
||||||
|
if (bt_waitReadByte() != HCI_EVENT_PKT) return 1;
|
||||||
|
|
||||||
|
unsigned char code = bt_waitReadByte();
|
||||||
|
if (code == CONNECT_COMPLETE_CODE) {
|
||||||
|
if (bt_waitReadByte() != 4) return 2;
|
||||||
|
|
||||||
|
unsigned char err = bt_waitReadByte();
|
||||||
|
if (err != 0) {
|
||||||
|
uart_writeText("Saw HCI COMMAND STATUS error "); uart_hex(err); uart_writeText("\n");
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bt_waitReadByte() == 0) return 3;
|
||||||
|
if (bt_waitReadByte() != opcodebytes[0]) return 4;
|
||||||
|
if (bt_waitReadByte() != opcodebytes[1]) return 5;
|
||||||
|
} else if (code == COMMAND_COMPLETE_CODE) {
|
||||||
|
if (bt_waitReadByte() != 4) return 6;
|
||||||
|
if (bt_waitReadByte() == 0) return 7;
|
||||||
|
if (bt_waitReadByte() != opcodebytes[0]) return 8;
|
||||||
|
if (bt_waitReadByte() != opcodebytes[1]) return 9;
|
||||||
|
if (bt_waitReadByte() != 0) return 10;
|
||||||
|
} else return 11;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) };
|
||||||
|
|
||||||
|
return hciCommandBytes(opcodebytes, data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_reset() {
|
||||||
|
volatile unsigned char empty[] = {};
|
||||||
|
if (hciCommand(OGF_HOST_CONTROL, COMMAND_RESET_CHIP, empty, 0)) uart_writeText("bt_reset() failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_loadfirmware()
|
||||||
|
{
|
||||||
|
volatile unsigned char empty[] = {};
|
||||||
|
if (hciCommand(OGF_VENDOR, COMMAND_LOAD_FIRMWARE, empty, 0)) uart_writeText("loadFirmware() failed\n");
|
||||||
|
|
||||||
|
extern unsigned char _binary_bin_BCM4345C0_hcd_start[];
|
||||||
|
extern unsigned char _binary_bin_BCM4345C0_hcd_size[];
|
||||||
|
|
||||||
|
unsigned int c=0;
|
||||||
|
unsigned int size = (long)&_binary_bin_BCM4345C0_hcd_size;
|
||||||
|
|
||||||
|
unsigned char opcodebytes[2];
|
||||||
|
unsigned char length;
|
||||||
|
unsigned char *data = &(_binary_bin_BCM4345C0_hcd_start[0]);
|
||||||
|
|
||||||
|
while (c < size) {
|
||||||
|
opcodebytes[0] = *data;
|
||||||
|
opcodebytes[1] = *(data+1);
|
||||||
|
length = *(data+2);
|
||||||
|
data += 3;
|
||||||
|
|
||||||
|
if (hciCommandBytes(opcodebytes, data, length)) {
|
||||||
|
uart_writeText("Firmware data load failed\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += length;
|
||||||
|
c += 3 + length;
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_msec(0x100000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_setbaud()
|
||||||
|
{
|
||||||
|
volatile unsigned char command[6] = { 0, 0, 0x00, 0xc2, 0x01, 0x00 }; // little endian, 115200
|
||||||
|
if (hciCommand(OGF_VENDOR, COMMAND_SET_BAUD, command, 6)) uart_writeText("bt_setbaud() failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_setbdaddr()
|
||||||
|
{
|
||||||
|
volatile unsigned char command[6] = { 0xee, 0xff, 0xc0, 0xee, 0xff, 0xc0 }; // reversed
|
||||||
|
if (hciCommand(OGF_VENDOR, COMMAND_SET_BDADDR, command, 6)) uart_writeText("bt_setbdaddr() failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_getbdaddr(unsigned char *bdaddr) {
|
||||||
|
bt_writeByte(HCI_COMMAND_PKT);
|
||||||
|
bt_writeByte(0x09);
|
||||||
|
bt_writeByte(0x10);
|
||||||
|
bt_writeByte(0x00);
|
||||||
|
|
||||||
|
if (bt_waitReadByte() != HCI_EVENT_PKT) return;
|
||||||
|
if (bt_waitReadByte() != COMMAND_COMPLETE_CODE) return;
|
||||||
|
if (bt_waitReadByte() != 0x0a) return;
|
||||||
|
if (bt_waitReadByte() != 1) return;
|
||||||
|
if (bt_waitReadByte() != 0x09) return;
|
||||||
|
if (bt_waitReadByte() != 0x10) return;
|
||||||
|
if (bt_waitReadByte() != 0x00) return;
|
||||||
|
|
||||||
|
for (int c=0;c<6;c++) bdaddr[c] = bt_waitReadByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendACLsubscribe(unsigned int handle)
|
||||||
|
{
|
||||||
|
bt_writeByte(HCI_ACL_PKT);
|
||||||
|
|
||||||
|
bt_writeByte(lo(handle));
|
||||||
|
bt_writeByte(hi(handle));
|
||||||
|
|
||||||
|
unsigned int length = 0x0009;
|
||||||
|
bt_writeByte(lo(length));
|
||||||
|
bt_writeByte(hi(length));
|
||||||
|
|
||||||
|
unsigned int data_length = 0x0005;
|
||||||
|
bt_writeByte(lo(data_length));
|
||||||
|
bt_writeByte(hi(data_length));
|
||||||
|
|
||||||
|
unsigned int channel = 0x0004;
|
||||||
|
bt_writeByte(lo(channel));
|
||||||
|
bt_writeByte(hi(channel));
|
||||||
|
|
||||||
|
volatile unsigned char command[5] = { 0x12, 0x2b, 0x00, 0x01, 0x00 };
|
||||||
|
|
||||||
|
unsigned int c=0;
|
||||||
|
while (c++<data_length) bt_writeByte(command[c-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLEeventmask(unsigned char mask)
|
||||||
|
{
|
||||||
|
volatile unsigned char command[8] = { 0 };
|
||||||
|
command[0] = mask;
|
||||||
|
|
||||||
|
if (hciCommand(OGF_LE_CONTROL, 0x01, command, 8)) uart_writeText("setLEeventmask failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLEscanenable(unsigned char state, unsigned char duplicates) {
|
||||||
|
volatile unsigned char command[2];
|
||||||
|
command[0] = state;
|
||||||
|
command[1] = duplicates;
|
||||||
|
if (hciCommand(OGF_LE_CONTROL, 0x0c, command, 2)) uart_writeText("setLEscanenable failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLEscanparameters(unsigned char type, unsigned char linterval, unsigned char hinterval, unsigned char lwindow, unsigned char hwindow, unsigned char own_address_type, unsigned char filter_policy) {
|
||||||
|
volatile unsigned char command[7];
|
||||||
|
command[0] = type;
|
||||||
|
command[1] = linterval;
|
||||||
|
command[2] = hinterval;
|
||||||
|
command[3] = lwindow;
|
||||||
|
command[4] = hwindow;
|
||||||
|
command[5] = own_address_type;
|
||||||
|
command[6] = filter_policy;
|
||||||
|
if (hciCommand(OGF_LE_CONTROL, 0x0b, command, 7)) uart_writeText("setLEscanparameters failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLEadvertenable(unsigned char state) {
|
||||||
|
volatile unsigned char command[1];
|
||||||
|
command[0] = state;
|
||||||
|
if (hciCommand(OGF_LE_CONTROL, 0x0a, command, 1)) uart_writeText("setLEadvertenable failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLEadvertparameters(unsigned char type, unsigned char linterval_min, unsigned char hinterval_min, unsigned char linterval_max, unsigned char hinterval_max, unsigned char own_address_type, unsigned char filter_policy) {
|
||||||
|
volatile unsigned char command[15] = { 0 };
|
||||||
|
|
||||||
|
command[0] = linterval_min;
|
||||||
|
command[1] = hinterval_min;
|
||||||
|
command[2] = linterval_max;
|
||||||
|
command[3] = hinterval_max;
|
||||||
|
command[4] = type;
|
||||||
|
command[5] = own_address_type;
|
||||||
|
command[13] = 0x07;
|
||||||
|
command[14] = filter_policy;
|
||||||
|
|
||||||
|
if (hciCommand(OGF_LE_CONTROL, 0x06, command, 15)) uart_writeText("setLEadvertparameters failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLEadvertdata() {
|
||||||
|
static unsigned char command[32] = {
|
||||||
|
0x19,
|
||||||
|
0x02, 0x01, 0x06,
|
||||||
|
0x03, 0x03, 0xAA, 0xFE,
|
||||||
|
0x11, 0x16, 0xAA, 0xFE, 0x10, 0x00, 0x03,
|
||||||
|
0x69, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x69, 0x6d,
|
||||||
|
0x2e, 0x65, 0x73,
|
||||||
|
0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (hciCommand(OGF_LE_CONTROL, 0x08, command, 32)) uart_writeText("setLEadvertdata failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopScanning() {
|
||||||
|
setLEscanenable(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopAdvertising() {
|
||||||
|
setLEadvertenable(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void startActiveScanning() {
|
||||||
|
float BleScanInterval = 60; // every 60ms
|
||||||
|
float BleScanWindow = 60;
|
||||||
|
float BleScanDivisor = 0.625;
|
||||||
|
|
||||||
|
unsigned int p = BleScanInterval / BleScanDivisor;
|
||||||
|
unsigned int q = BleScanWindow / BleScanDivisor;
|
||||||
|
|
||||||
|
setLEscanparameters(LL_SCAN_ACTIVE, lo(p), hi(p), lo(q), hi(q), 0, 0);
|
||||||
|
setLEscanenable(1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void startActiveAdvertising() {
|
||||||
|
float advertMinFreq = 100; // every 100ms
|
||||||
|
float advertMaxFreq = 100; // every 100ms
|
||||||
|
float bleGranularity = 0.625;
|
||||||
|
|
||||||
|
unsigned int min_interval = advertMinFreq / bleGranularity;
|
||||||
|
unsigned int max_interval = advertMaxFreq / bleGranularity;
|
||||||
|
|
||||||
|
setLEadvertparameters(LL_ADV_NONCONN_IND, lo(min_interval), hi(min_interval), lo(max_interval), hi(max_interval), 0, 0);
|
||||||
|
setLEadvertdata();
|
||||||
|
setLEadvertenable(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect(unsigned char *addr)
|
||||||
|
{
|
||||||
|
float BleScanInterval = 60; // every 60ms
|
||||||
|
float BleScanWindow = 60;
|
||||||
|
float BleScanDivisor = 0.625;
|
||||||
|
|
||||||
|
float connMinFreq = 30; // every 30ms
|
||||||
|
float connMaxFreq = 50; // every 50ms
|
||||||
|
float BleGranularity = 1.25;
|
||||||
|
|
||||||
|
unsigned int p = BleScanInterval / BleScanDivisor;
|
||||||
|
unsigned int q = BleScanWindow / BleScanDivisor;
|
||||||
|
|
||||||
|
unsigned int min_interval = connMinFreq / BleGranularity;
|
||||||
|
unsigned int max_interval = connMaxFreq / BleGranularity;
|
||||||
|
|
||||||
|
volatile unsigned char command[25] = { 0 };
|
||||||
|
|
||||||
|
command[0] = lo(p);
|
||||||
|
command[2] = lo(q);
|
||||||
|
command[6] = *(addr+5);
|
||||||
|
command[7] = *(addr+4);
|
||||||
|
command[8] = *(addr+3);
|
||||||
|
command[9] = *(addr+2);
|
||||||
|
command[10] = *(addr+1);
|
||||||
|
command[11] = *addr;
|
||||||
|
command[13] = lo(min_interval);
|
||||||
|
command[15] = lo(max_interval);
|
||||||
|
command[19] = 0x2a;
|
||||||
|
command[20] = 0x00;
|
||||||
|
|
||||||
|
if (hciCommand(OGF_LE_CONTROL, 0x0d, command, 25)) uart_writeText("createLEconnection failed\n");
|
||||||
|
}
|
221
part12-wgt/mouse.c
Normal file
221
part12-wgt/mouse.c
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
#include "wgt.h"
|
||||||
|
#include "include/multicore.h"
|
||||||
|
#include "include/io.h"
|
||||||
|
#include "include/bt.h"
|
||||||
|
|
||||||
|
#define MAX_MSG_LEN 50
|
||||||
|
#define MAX_READ_RUN 100
|
||||||
|
|
||||||
|
unsigned char data_buf[MAX_MSG_LEN];
|
||||||
|
unsigned int data_len;
|
||||||
|
unsigned int messages_received = 0;
|
||||||
|
unsigned int poll_state = 0;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LE_EVENT_CODE = 0x3e,
|
||||||
|
LE_CONNECT_CODE = 0x01,
|
||||||
|
LE_ADREPORT_CODE = 0x02,
|
||||||
|
HCI_ACL_PKT = 0x02,
|
||||||
|
HCI_EVENT_PKT = 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
volatile unsigned int comms_up = 0;
|
||||||
|
|
||||||
|
/* Mouse variables */
|
||||||
|
int but;
|
||||||
|
int mx;
|
||||||
|
int my;
|
||||||
|
|
||||||
|
void hci_poll2(unsigned char byte)
|
||||||
|
{
|
||||||
|
switch (poll_state) {
|
||||||
|
case 0:
|
||||||
|
if (byte != HCI_EVENT_PKT) poll_state = 0;
|
||||||
|
else poll_state = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (byte != LE_EVENT_CODE) poll_state = 0;
|
||||||
|
else poll_state = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (byte > 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<ad_len - 1) {
|
||||||
|
remote_name[d] = buf[bufindex + d];
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
if (!memcmp(remote_name,"echo",4)) {
|
||||||
|
got_echo_name = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bufindex += ad_len - 1;
|
||||||
|
} while (bufindex < data_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_conn()
|
||||||
|
{
|
||||||
|
unsigned char *buf;
|
||||||
|
|
||||||
|
while ( (buf = hci_poll()) ) {
|
||||||
|
if (!connected && data_len >= 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<length;i++) bt_waitReadByte();
|
||||||
|
} else if (byte == HCI_ACL_PKT) {
|
||||||
|
unsigned char h1 = bt_waitReadByte(); // handle1
|
||||||
|
unsigned char h2 = bt_waitReadByte(); // handle2
|
||||||
|
unsigned char thandle = h1 | (h2 << 8);
|
||||||
|
|
||||||
|
unsigned char d1 = bt_waitReadByte();
|
||||||
|
unsigned char d2 = bt_waitReadByte();
|
||||||
|
|
||||||
|
unsigned int dlen = d1 | (d2 << 8);
|
||||||
|
unsigned char data[dlen];
|
||||||
|
|
||||||
|
if (dlen > 7) {
|
||||||
|
for (int i=0;i<dlen;i++) data[i] = bt_waitReadByte();
|
||||||
|
|
||||||
|
unsigned int length = data[0] | (data[1] << 8);
|
||||||
|
unsigned int channel = data[2] | (data[3] << 8);
|
||||||
|
unsigned char opcode = data[4];
|
||||||
|
|
||||||
|
if (thandle == connection_handle && length == 4 && opcode == 0x1b) {
|
||||||
|
if (channel == 4 && data[5] == 0x2a && data[6] == 0x00) {
|
||||||
|
mx = data[7] * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mdeinit()
|
||||||
|
{
|
||||||
|
comms_up = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void minit()
|
||||||
|
{
|
||||||
|
clear_core2();
|
||||||
|
|
||||||
|
// Initialise the UART
|
||||||
|
uart_init();
|
||||||
|
|
||||||
|
// Initialise the Bluetooth
|
||||||
|
bt_init();
|
||||||
|
bt_reset();
|
||||||
|
bt_loadfirmware();
|
||||||
|
bt_setbaud();
|
||||||
|
bt_setbdaddr();
|
||||||
|
|
||||||
|
// Start scanning
|
||||||
|
setLEeventmask(0xff);
|
||||||
|
startActiveScanning();
|
||||||
|
|
||||||
|
// Search for the echo
|
||||||
|
while (!(got_echo_sid && got_echo_name)) bt_search();
|
||||||
|
stopScanning();
|
||||||
|
|
||||||
|
// Connecting to echo
|
||||||
|
connect(echo_addr);
|
||||||
|
while (!(connected && connection_handle)) bt_conn();
|
||||||
|
|
||||||
|
// Subscribe to updates
|
||||||
|
sendACLsubscribe(connection_handle);
|
||||||
|
|
||||||
|
mx = 160;
|
||||||
|
my = 100;
|
||||||
|
but = 0;
|
||||||
|
|
||||||
|
comms_up = 1;
|
||||||
|
while (comms_up) acl_poll();
|
||||||
|
}
|
|
@ -64,6 +64,15 @@ typedef struct
|
||||||
#define CLOSED_POLY 0
|
#define CLOSED_POLY 0
|
||||||
#define OPEN_POLY 1
|
#define OPEN_POLY 1
|
||||||
|
|
||||||
|
/* Mouse variables */
|
||||||
|
extern int but;
|
||||||
|
extern int mx;
|
||||||
|
extern int my;
|
||||||
|
|
||||||
|
/* Bluetooth control */
|
||||||
|
extern volatile unsigned int comms_up;
|
||||||
|
void comms_core(void);
|
||||||
|
|
||||||
// ######## HELPER FUNCTIONS ########
|
// ######## HELPER FUNCTIONS ########
|
||||||
|
|
||||||
void *memset(void *dest, unsigned int val, unsigned len);
|
void *memset(void *dest, unsigned int val, unsigned len);
|
||||||
|
@ -83,6 +92,7 @@ void debugch(unsigned char b);
|
||||||
void debughex(unsigned int d);
|
void debughex(unsigned int d);
|
||||||
|
|
||||||
void delay(unsigned int n);
|
void delay(unsigned int n);
|
||||||
|
void wait_msec(unsigned int n);
|
||||||
|
|
||||||
void vga256(void);
|
void vga256(void);
|
||||||
void wsetcolor (unsigned int col);
|
void wsetcolor (unsigned int col);
|
||||||
|
@ -142,3 +152,5 @@ void wresize_column (short x, short y, short y2, block image, short column, shor
|
||||||
void wsolidpoly (tpolypoint *vertexlist, short numvertex, short x, short y, void (*customline)(short, short, short));
|
void wsolidpoly (tpolypoint *vertexlist, short numvertex, short x, short y, void (*customline)(short, short, short));
|
||||||
void whollowpoly(tpolypoint *vertexlist, short numvertex, short x, short y, short closemode);
|
void whollowpoly(tpolypoint *vertexlist, short numvertex, short x, short y, short closemode);
|
||||||
void wbezier (tpolypoint *rawpts, short numraw, tpolypoint *curvepts, short numcurve);
|
void wbezier (tpolypoint *rawpts, short numraw, tpolypoint *curvepts, short numcurve);
|
||||||
|
void minit();
|
||||||
|
void mdeinit();
|
||||||
|
|
Loading…
Reference in a new issue