Skip to content

Commit

Permalink
use history in packet to prevent lost events
Browse files Browse the repository at this point in the history
  • Loading branch information
markfirmware committed Sep 12, 2018
1 parent 78a1c12 commit e69f5a8
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 57 deletions.
66 changes: 37 additions & 29 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ MicroBit uBit;
const int8_t CALIBRATED_POWERS[] = {-49, -37, -33, -28, -25, -20, -15, -10};
uint8_t advertising = 0;
uint8_t tx_power_level = 6;
uint8_t AdvData [] = {0xff, 0xff,
0x55, 0x97,
'0', '0',
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.'};
uint8_t AdvData [26] = {0xff, 0xff,
0x55, 0x98,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t buttonsState = 0;
uint8_t eventCounter = 0;

char digit(uint8_t n)
{
{
return '0' + n;
}
}

void startAdvertising() {
void startAdvertising()
{
int connectable = 0;
int interval = 160;
uBit.bleManager.setTransmitPower(tx_power_level);
Expand All @@ -25,34 +26,34 @@ void startAdvertising() {
uBit.bleManager.ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
uBit.bleManager.ble->accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, AdvData, sizeof(AdvData));
uBit.bleManager.ble->startAdvertising();
uBit.display.printAsync("ULTIBO", 200);
uBit.display.printAsync("ULTIBO 98", 200);
advertising = 1;
}
}

void updatePayload ()
{
{
uBit.bleManager.ble->clearAdvertisingPayload();
uBit.bleManager.ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
AdvData [4] = digit (eventCounter / 10);
AdvData [5] = digit (eventCounter % 10);
for (int i = 19; i >= 1; i--)
{
AdvData [i + 6] = AdvData [i + 6 - 1];
}
AdvData [6] = buttonsState + '0';
AdvData [4] = eventCounter;
for (int i = 20; i >= 1; i--)
{
AdvData [i + 5] = AdvData [i + 5 - 1];
}
AdvData [5] = (buttonsState << 6);
uBit.bleManager.ble->accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, AdvData, sizeof(AdvData));
}
}

void stopAdvertising() {
void stopAdvertising()
{
uBit.bleManager.stopAdvertising();
uBit.display.scroll("OFF");
advertising = 0;
}
}

char text[] = "?";

void onButton(MicroBitEvent e)
{
{
uint8_t mask;
uint8_t prev = buttonsState;
if (e.source == MICROBIT_ID_BUTTON_A)
Expand Down Expand Up @@ -80,10 +81,17 @@ void onButton(MicroBitEvent e)
buttonsState &= ~mask;

if (buttonsState != prev)
{
eventCounter = (eventCounter + 1) % 100;
switch (buttonsState)
{
if (eventCounter == 255)
{
eventCounter = 128;
}
else
{
eventCounter = eventCounter + 1;
}
switch (buttonsState)
{
case 0: text [0] = ' ';
break;
case 1: text [0] = 'A';
Expand All @@ -93,10 +101,10 @@ void onButton(MicroBitEvent e)
case 3: text [0] = '2';
break;
default: text [0] = '?';
}
}
uBit.display.printAsync (text);
updatePayload ();
}
}

// if (e.value == MICROBIT_BUTTON_EVT_CLICK)
// uBit.serial.printf("CLICK");
Expand All @@ -111,13 +119,13 @@ void onButton(MicroBitEvent e)
// uBit.serial.printf("DOUBLE_CLICK");
//
// uBit.serial.printf("\r\n");
}
}

int main()
{
{
uBit.init();
uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, onButton);
uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, onButton);
startAdvertising();
release_fiber();
}
}
121 changes: 94 additions & 27 deletions microbitdemo.lpr
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,15 @@

type
TArrayOfByte = Array of Byte;
PMicroBitPeripheral = ^TMicroBitPeripheral;
TMicroBitPeripheral = record
AddressString:String;
ButtonCounter:Integer;
ButtonChordStarted:Boolean;
end;

var
MicroBitPeripherals:Array of TMicroBitPeripheral;
ScanRxCount:Integer;
BluetoothUartDeviceDescription:String;
ScanCycleCounter:LongWord;
Expand All @@ -69,8 +76,6 @@
UART0:PSerialDevice = Nil;
KeyboardLoopHandle:TThreadHandle = INVALID_HANDLE_VALUE;
ReadByteCounter:Integer;
ButtonCounter:Integer;
ButtonChordStarted:Boolean;

function ReadByte:Byte; forward;

Expand Down Expand Up @@ -255,20 +260,6 @@ procedure HciCommand(OGF:byte; OCF:Word; Params:array of byte);
HciCommand((OGF shl 10) or OCF,Params);
end;

procedure SetLEScanResponseData(Data:array of byte);
var
Params:array of byte;
Len:byte;
i:integer;
begin
Len:=Min(Length(Data),31);
SetLength(Params,Len + 1);
Params[0]:=Len;
for i:=0 to Len - 1 do
Params[i + 1]:=Data[i];
HciCommand(OGF_LE_CONTROL,$09,Params);
end;

function EventReadFirstByte:Byte;
var
c:LongWord;
Expand Down Expand Up @@ -564,7 +555,7 @@ function KeyboardLoop(Parameter:Pointer):PtrInt;
'Q' : SystemRestart(0);
'R' :
begin
RestoreBootFile('bluetooth-dev-bluetoothtest','config.txt');
RestoreBootFile('microbitdemo','config.txt');
SystemRestart(0);
end;
end;
Expand Down Expand Up @@ -599,6 +590,29 @@ function AsWord(Hi,Lo:Integer):Word;
Result:=(Hi shl 8) or Lo;
end;

function FindOrMakeMicroBitPeripheral(NewAddressString:String):PMicroBitPeripheral;
var
I:Integer;
begin
Result:=Nil;
for I:= 0 to High(MicroBitPeripherals) do
if MicroBitPeripherals[I].AddressString = NewAddressString then
Result:=@MicroBitPeripherals[I];
if Result = nil then
begin
SetLength(MicroBitPeripherals,Length(MicroBitPeripherals) + 1);
Result:=@MicroBitPeripherals[High(MicroBitPeripherals)];
with Result^ do
begin
AddressString:=NewAddressString;
ButtonCounter:=0;
ButtonChordStarted:=False;
end;
Log('');
Log(Format('detected new micro:bit peripheral %s',[NewAddressString]));
end;
end;

procedure ParseEvent;
var
I:Integer;
Expand All @@ -613,6 +627,10 @@ procedure ParseEvent;
LeEventType:Byte;
NewButtonCounter:Integer;
ButtonMessage:String;
CounterByte:Byte;
MicroEventIndex:Integer;
MicroEvent:Byte;
MicroBitPeripheral:PMicroBitPeripheral;
function GetByte:Byte;
begin
Result:=Event[GetByteIndex];
Expand Down Expand Up @@ -675,8 +693,9 @@ function GetByte:Byte;
MfrHi:=GetByte;
SignatureLo:=GetByte;
SignatureHi:=GetByte;
if (MainType = $ff) and (AsWord(MfrHi,MfrLo) = Word(ManufacturerTesting)) and (SignatureLo = $55) and (SignatureHi = $97) then
if (MainType = $ff) and (AsWord(MfrHi,MfrLo) = Word(ManufacturerTesting)) and (AsWord(SignatureHi,Signaturelo) = $9755) then
begin
MicroBitPeripheral:=FindOrMakeMicroBitPeripheral(AddressString);
GetByteIndex:=20;
NewButtonCounter:=(GetByte - Ord('0'))*10;
NewButtonCounter:=NewButtonCounter + (GetByte - Ord('0'));
Expand All @@ -685,28 +704,77 @@ function GetByte:Byte;
begin
S:=S + Char(GetByte);
end;
if NewButtonCounter <> ButtonCounter then
if NewButtonCounter <> MicroBitPeripheral^.ButtonCounter then
begin
ButtonCounter:=NewButtonCounter;
if not ButtonChordStarted then
MicroBitPeripheral^.ButtonCounter:=NewButtonCounter;
if not MicroBitPeripheral^.ButtonChordStarted then
begin
LoggingOutput('');
ButtonChordStarted:=True;
MicroBitPeripheral^.ButtonChordStarted:=True;
end;
case S[1] of
'0':
begin
ButtonMessage:='Released ';
ButtonChordStarted:=False;
MicroBitPeripheral^.ButtonChordStarted:=False;
end;
'1': ButtonMessage:='A down ';
'2': ButtonMessage:='B down ';
'3': ButtonMessage:='A and B down';
else ButtonMessage:='????????????';
end;
LoggingOutput(Format('micro:bit addr %s %s - %02.2d events, history: %s',[AddressString,ButtonMessage,ButtonCounter,S]));
LoggingOutput(Format('micro:bit addr %s %s - %02.2d events, history: %s',[AddressString,ButtonMessage,MicroBitPeripheral^.ButtonCounter,S]));
end;
end;
end
else if (MainType = $ff) and (AsWord(MfrHi,MfrLo) = Word(ManufacturerTesting)) and (AsWord(SignatureHi,SignatureLo) = $9855) then
begin
MicroBitPeripheral:=FindOrMakeMicroBitPeripheral(AddressString);
GetByteIndex:=20;
CounterByte:=GetByte;
NewbuttonCounter:=CounterByte and $7f;
S:='';
while GetByteIndex <= High(Event) do
S:=S + Char(Ord('0') + (GetByte shr 6));
while (MicroBitPeripheral^.ButtonCounter mod 128) <> NewButtonCounter do
begin
Inc(MicroBitPeripheral^.ButtonCounter);
MicroEventIndex:=NewButtonCounter - (MicroBitPeripheral^.ButtonCounter mod 128);
// Log(Format('counter %d new %d index %d %s',[MicroBitPeripheral^.ButtonCounter,NewButtonCounter,MicroEventIndex,S]));
if MicroEventIndex < 0 then
Inc(MicroEventIndex,128);
if MicroEventIndex >= 21 then
begin
Log(Format('unable to reconstruct event %d index %d from %d %s',[MicroBitPeripheral^.ButtonCounter,MicroEventIndex,NewButtonCounter,S]));
if (CounterByte and $80) = 0 then
begin
MicroBitPeripheral^.ButtonCounter:=NewButtonCounter;
Log('the micro:bit seems to have restarted');
end;
end
else
begin
GetByteIndex:=21 + MicroEventIndex;
if not MicroBitPeripheral^.ButtonChordStarted then
begin
LoggingOutput('');
MicroBitPeripheral^.ButtonChordStarted:=True;
end;
MicroEvent:=GetByte shr 6;
case MicroEvent of
0:
begin
ButtonMessage:='Released ';
MicroBitPeripheral^.ButtonChordStarted:=False;
end;
1: ButtonMessage:='A down ';
2: ButtonMessage:='B down ';
3: ButtonMessage:='A and B down';
else ButtonMessage:='????????????';
end;
LoggingOutput(Format('micro:bit addr %s event number %03.3d %s - history: %s',[AddressString,MicroBitPeripheral^.ButtonCounter,ButtonMessage,S]));
end;
end;
end;
end;

begin
Expand Down Expand Up @@ -734,8 +802,7 @@ function GetByte:Byte;
Log('Init complete');
ScanCycleCounter:=0;
ReadByteCounter:=0;
ButtonCounter:=0;
ButtonChordStarted:=False;
SetLength(MicroBitPeripherals,0);
while True do
begin
ReadBackLog:=0;
Expand Down
3 changes: 2 additions & 1 deletion release-message.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Ultibo prototype-microbit-as-ultibo-peripheral repository
# prototype-microbit-as-ultibo-peripheral

# Requires:
* a micro:bit computer and a usb cable
Expand All @@ -20,6 +20,7 @@
* attach the microbit to the computer with the usb cable
* the microbit should appear as a usb folder
* copy microbit-as-ultibo-peripheral.hex from the sd card to the microbit usb folder
* safely eject the sd card
* insert the sd card into the pi
* connect the pi to the tv using the hdmi cable
* connect the pi to the optional usb keyboard
Expand Down

0 comments on commit e69f5a8

Please sign in to comment.