Kontrollera din iRobot skapa med en Palm Pilot (11 / 16 steg)
Steg 11: Programmet, del 3
Nu är det dags för "kärnan" i programmet, filen "robot.c".Högst upp i filen "robot.c" behöver vi:
#include "robot.h"
#include "string_arrays.c"
#include < PalmTypes.h >
#include < PalmCompatibility.h >
#include < System/SystemPublic.h >
#include < UI/UIPublic.h >
Annullera SetField (UInt16 formID, UInt16 fieldID, MemPtr str);
Int16 Connect();
Booleska Disconnect();
void DisplaySensors();
Boolean MenuHandler (EventPtr händelse);
Boolean SelectFormHandler (EventPtr händelse);
Int16 SendScript (char längd).
void Display (char längd).
Boolean ScriptFormHandler (EventPtr händelse);
Boolean MainFormHandler (EventPtr händelse);
Boolean AppHandleEvent (EventPtr händelse);
void AppEventLoop();
void AppStart();
void AppStop();
UInt32 PilotMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags);
GlobalsUInt16 port = 0;
char prog = 0;
unsigned char skript [30] [2].
I detta ingår generiska Palm OS bibliotekets. Jag är också att förklara alla funktioner jag har använt på toppen, så du inte behöver oroa någon speciell ordning när du redigerar filen robot.c. Längst har jag också några globala variabler som jag använder på olika punkter i programmet.
Funktionen "PilotMain" är inkörsporten till programmet. Det finns olika orsaker till att ett program kan startas på en Palm Pilot, men vi vill bara oroa dig om en; Om programmet startades av användaren PilotMain() börjar resten av programmet.
UInt32 PilotMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags) {
om (cmd == sysAppLaunchCmdNormalLaunch) {
AppStart();
AppEventLoop();
AppStop();
}
Return 0;
}
Funktionerna AppStart() och AppStop() är ganska grundläggande, AppStart() kontrollera att programmet startar ordentligt och AppStop() ser till att programmet stängs renlig.
void AppStart() {
FrmGotoForm(FormMain);
}
void AppStop() {
Disconnect();
FrmCloseAllForms();
}
AppEventLoop() är kärnan i programmet. När något händer AppEventLoop() hämtas "händelse" och försök att hantera den. Först skickas händelsen till några inbyggda funktioner för att prova och låt systemet hantera händelsen. Om systemet inte fullt hanterar händelsen AppEventLoop() så skickas händelsen till våra egna funktioner att försöka hantera det. FrmDispatchEvent() är händelsehanterarfunktionen som vi tilldelats hantera händelser för det aktiva formuläret.
void AppEventLoop() {
EventType händelse;
kort fel;
göra {
EvtGetEvent (& event, 50); Vänta 100 fästingar innan du skickar en nilEvent
Systemet kan attemt att hantera händelser innan du försöker oss själva
om (SysHandleEvent (& event)) fortsätter;
om (MenuHandleEvent ((void*) 0, & event & fel)) fortsätta;
om (AppHandleEvent (& event)) fortsätter;
om (MenuHandler (& event)) fortsätter;
Skicka händelsen till händelsehanteraren form
FrmDispatchEvent(&event);
} medan (event.eType! = appStopEvent);
}
AppHandleEvent() är den första icke-system funktion som AppEventLoop() skickar händelser till. Det kontrollerar om händelsen innebär lastning av någon av formerna. Om så det ställer in i formuläret och tilldelar en standard händelsehanterare (för FrmDispatchEvent()).
Boolean AppHandleEvent (EventPtr händelse) {
FormPtr frm;
Int frmID;
Boolean hanteras = false;
char str [255];
Str [0] = '\0';
om (händelse -> eType == frmLoadEvent) {
frmID = händelse -> data.frmLoad.formID;
frm = FrmInitForm(frmID);
FrmSetActiveForm(frm);
växel (frmID) {
fall FormMain:
FrmSetEventHandler (frm, MainFormHandler);
FrmDrawForm(frm);
StrCat (str, PROGRAM[prog]);
SetField (frmID, FldProg, str);
hanteras = sant;
bryta;
fall FormSelect:
FrmSetEventHandler (frm, SelectFormHandler);
FrmDrawForm(frm);
StrCat (str, DISCRIPIONS[prog]);
SetField (frmID, FldDescription, str);
hanteras = sant;
bryta;
fall FormMacro:
FrmSetEventHandler (frm, ScriptFormHandler);
FrmDrawForm(frm);
hanteras = sant;
bryta;
}
}
avkastning som hanteras,
}
MenuHandler() är nästa funktion AppEventLoop () listan. Om användaren gör en meny val av MenuHandler() kommer att hantera den.
Boolean MenuHandler (EventPtr händelse) {
Boolean hanteras = false;
ERR fela;
Kommandot som kör demo program att corosponds till "prog"
röding data [] = {128, 136, prog};
Handtag på Meny-knappen
om (händelse -> eType == menuEvent) {
MenuEraseStatus(NULL);
Växla (händelse -> data.menu.itemID) {
Gå till verious bildar
fall MnuStatus:
FrmGotoForm(FormMain);
hanteras = sant;
bryta;
fall MnuScript:
FrmGotoForm(FormSelect);
hanteras = sant;
bryta;
fall MnuMacro:
FrmGotoForm(FormMacro);
hanteras = sant;
bryta;
Öppna seriell anslutning
fall MnuConnect:
Connect();
hanteras = sant;
bryta;
Nära seriell anslutning
fall MnuDisconnect:
Disconnect();
hanteras = sant;
bryta;
Starta/stoppa den markerade program eller makro
fall MnuRun:
IF (!. Connect()) semester.
Skicka kommandot till iRobot
SrmSend (port, data, 3, & err);
SrmSendFlush(port);
hanteras = sant;
bryta;
fall MnuStop:
Ersätta den "prog" byten med -1 (255) att stoppa det pågående programmet
data [2] = 255;
Skicka kommandot till iRobot
IF (!. Connect()) semester.
SrmSend (port, data, 3, & err);
SrmSendFlush(port);
hanteras = sant;
bryta;
fall MnuAbout:
FrmAlert(AboutAlert);
hanteras = sant;
bryta;
}
}
avkastning som hanteras,
}
Connect() och Disconnect() används för att öppna och stänga Palm Pilots serieport. Väder eller inte roboten är ansluten till Palm Pilot och aktiverad när dessa funktioner används inte är alltför viktig. Tuff, om roboten inte får kommandot "Start" minst en gång (det skickas när anropas funktionen Connect()) du kan ha några problem att köra egna skript.
Int16 Connect() {
ERR fela;
röding data = 128;
Öppna den seriella porten
om (! port) SrmOpen (serPortCradlePort, 57600 & port);
Skicka kommandot "Start" för att se till att skapa kommer av "Off"-läge
SrmSend (hamn & data, 1, & err);
SrmSendFlush(port);
returnera hamn.
}
Booleska Disconnect() {
Stäng den seriella porten
om (hamn & &! SrmClose(port)) {
Port = 0;
return true;
} annars returnera false;
}
SetFiled() används av olika funktioner för att visa data i textfälten definieras av filen "robot.rcp".
void SetField (UInt16 formID, UInt16 fieldID, MemPtr str) {
FormPtr frm;
FieldPtr fld;
UInt16 obj;
CharPtr p;
VoidHand h;
frm = FrmGetFormPtr(formID);
obj = FrmGetObjectIndex (frm, fieldID);
FLD = (FieldPtr) FrmGetObjectPtr (frm, obj);
h = (VoidHand)FldGetTextHandle(fld);
om (h == NULL) {
h = MemHandleNew (FldGetMaxChars(fld)+1);
ErrFatalDisplayIf (! h, "Inget minne");
}
p = (CharPtr)MemHandleLock(h);
StrCopy (p, str);
MemHandleUnlock(h);
FldSetTextHandle (fld, (handtag) h);
FldDrawField(fld);
}
DisplaySensors() används av huvudformuläret (formuläret "Status") att hämta sensor information från roboten och sedan Visa det för användaren. Det skickas först kommandot "Frågelistan" till roboten med en lista med sensorer som vi är intresserade. DisplaySensors() sedan analysera robotens svar och uppdateras visningen.
void DisplaySensors() {
Datapaketet skickas till skapa som begär sensordata
röding data [] = {128, 149, 8, 8, 7, 9, 10, 11, 12, 22, 21};
Bytematris som innehåller sensor data hämtats av skapa
char inData [9]. char str [20].
UInt16 tmp, * volt;
ERR fela;
VoidHand bitmapHandle;
BitmapPtr bitmappen.
Booleska wheall = false whealr = false; Str [0] = '\0';
om (port) {/ / endast utföra denna slinga om seriell anslutning är öppen
FrmDrawForm(FrmGetActiveForm()); Åter dra formuläret om du vill radera gammal datan
Skicka begäran till skapa för sensordata och lägga svaret i "inData"
SrmReceiveFlush (port, 0);
SrmSend (port, data, 11, & err);
SrmSendFlush(port);
SrmReceive (port, inData, 9, 20, & err);
Väggen sensorn
om (inData[0]) {
bitmapHandle = DmGetResource ("Tbmp", PicWall);
Bitmap = MemHandleLock(bitmapHandle);
WinDrawBitmap (bitmap, 110, 25);
MemHandleUnlock(bitmapHandle);
}
Stötfångaren och wheal droppe sensorer
tmp = (int) inData [1].
om (tmp > = 16) tmp = tmp-16; Caster wheal
om (tmp > = 8) {/ / vänster wheal
wheall = sant;
tmp = tmp - 8.
}
om (tmp > = 4) {/ / höger wheal
whealr = sant;
tmp = tmp - 4.
}
om (tmp > = 2) {/ / vänster wheal
bitmapHandle = DmGetResource ("Tbmp", PicBumpL);
Bitmap = MemHandleLock(bitmapHandle);
WinDrawBitmap (bitmappen, 25, 30).
MemHandleUnlock(bitmapHandle);
tmp = tmp - 2.
}
om (tmp == 1) {/ / höger wheal
bitmapHandle = DmGetResource ("Tbmp", PicBumpR);
Bitmap = MemHandleLock(bitmapHandle);
WinDrawBitmap (bitmappen, 60, 30).
MemHandleUnlock(bitmapHandle);
}
Vi drar wheal efter ritning stötfångare, så den
bilder överlappa ordentligt
om (wheall) {
bitmapHandle = DmGetResource ("Tbmp", PicWhealL);
Bitmap = MemHandleLock(bitmapHandle);
WinDrawBitmap (bitmappen, 37, 52).
MemHandleUnlock(bitmapHandle);
}
om (whealr) {
bitmapHandle = DmGetResource ("Tbmp", PicWhealR);
Bitmap = MemHandleLock(bitmapHandle);
WinDrawBitmap (bitmappen, 71, 52).
MemHandleUnlock(bitmapHandle);
}
4 clif sensorerna
om (inData [2] inData [3] [4] inData + + inData [5] > 0) {
bitmapHandle = DmGetResource ("Tbmp", PicCliff);
Bitmap = MemHandleLock(bitmapHandle);
om (inData [2] > 0)
WinDrawBitmap (bitmappen, 21, 35). Vänster
om (inData [3] > 0)
WinDrawBitmap (bitmap, 31, 25); Överst till vänster
om (inData [4] > 0)
WinDrawBitmap (bitmap, 80, 25); Övre högra
om (inData [5] > 0)
WinDrawBitmap (bitmappen, 90, 35). Höger
MemHandleUnlock(bitmapHandle);
}
Raw batterispänningen
volt = (UInt16 *)(inData + 6);
StrIToA (str, * volt);
StrCat (str, "mV");
om (inData [8] > 0 & & inData [8] < = 3) StrCat (str, "(crg)");
SetField (FormMain, FldVoltage, str);
}
}
MainFormHandler() är funktionen som är tilldelad till formuläret main (status). Den är utformad att hantera händelser specifika för formuläret status. Den individuella formulärhanteraren mest bara hantera händelser orsakade av användaren, men viktigaste formulärhanteraren kommer också svara på nillEvent som genereras varje 50 "fästingar" (en fästing är ett mått på tid som Palm OS använder) av AppEventLoop().
Boolean MainFormHandler (EventPtr händelse) {
Boolean hanteras = false;
Växla (händelse -> eType) {
Varje 50 fästingar vi kontrollera sidan Skapa sensorer (i väntan på en seriell anslutning)
fall nilEvent:
DisplaySensors();
hanteras = sant;
bryta;
fall ctlSelectEvent:
om (händelse -> data.ctlSelect.controlID == BtnDisconnect) {
Disconnect();
hanteras = sant;
}
bryta;
}
avkastning som hanteras,
}
SelectFormHandler() hanterar händelser för formuläret select.
Boolean SelectFormHandler (EventPtr händelse) {
Boolean hanteras = false;
char str [255];
Str [0] = '\0';
Växla (händelse -> eType) {
fall lstSelectEvent:
PROG = händelse -> data.lstSelect.selection;
StrCat (str, DISCRIPIONS[prog]);
SetField (FormSelect, FldDescription, str);
hanteras = sant;
bryta;
}
avkastning som hanteras,
}
ScriptFormHandler() hanterar händelser för formuläret skript. En stor del av ScriptFormHandler() skilja mellan de olika programmera knapparna. Eftersom knappen programmering ID är löpande nummer, istället för att leta menyknapp händelser vi kan leta efter knappen spänner.
Boolean ScriptFormHandler (EventPtr händelse) {
CONST char MAX_SCRIPT = 8;
statiska char längd = 0;
Boolean hanteras = false;
UInt16 id;
Int16 x;
FieldPtr fld;
FormPtr frm;
Växla (händelse -> eType) {
fall frmOpenEvent:
Display(length);
hanteras = sant;
bryta;
Hantera de olika knapparna
fall ctlSelectEvent:
ID = händelse -> data.ctlSelect.controlID;
Växla (id) {
fall BtnSend:
SendScript(length);
hanteras = sant;
bryta;
fall BtnClear:
längd = 0;
Display(length);
hanteras = sant;
bryta;
fall BtnDel:
längd--;
om (längd < 0) längd = 0;
Display(length);
hanteras = sant;
bryta;
}
Skriptet knapparna
om (id > = BtnUp & & id < = BtnPause) {
om (längd < MAX_SCRIPT) {
script [längd] [0] = id-3100;
script [längd] [1] = 1;
längd ++;
}
Display(length);
hanteras = sant;
}
Skriptet tid knapparna
om (id > = BtnP1 & & id < = BtnP16) {
x = skript [längd-1] [1].
skriptet [längd-1] [1] = (x+(id-3200) < = 25)? x+(ID-3200): x;
Display(length);
hanteras = sant;
}
bryta;
Rullningslisten
fall sclRepeatEvent:
x = händelse -> data.sclRepeat.newValue - evenemang -> data.sclRepeat.value;
frm = FrmGetActiveForm();
FLD = (FieldPtr) FrmGetObjectPtr (frm, FrmGetObjectIndex (frm, FldScript));
om (x > = 0) FldScrollField (fld, x, winDown);
annat FldScrollField (fld, x-1, winUp);
bryta;
}
avkastning som hanteras,
}
Funktionen Display() översätter data i matrisen skript till en mänsklig-vänlig sträng och visar det i en textfält som användaren kan se.
Annullera Display (char längd) {
char str [1000];
char x;
char tmp [10].
Str [0] = '\0';
Aktivera skript matrisen till en sträng och Visa den
för (x = 0; x < längd; x ++) {
StrCat (str, COMMANDS[script[x][0]]);
StrCat (str, "för \0");
StrIToA (tmp, script[x][1]);
StrCat (str, tmp);
StrCat (str, "Seconds\n\0");
}
SetField (FormMacro, FldScript, str);
}
Slutligen funktionen SendScript() tar variabeln skript och översätta det till kommandon som iRobot skapa kan förstå och sedan skicka resultatet till din robot. Det kallas på ScriptFormHandler() funktion.
Int16 SendScript (char längd) {
char säker [] = {128, 131};
röding data [150];
röding i.
char x = 0;
char y;
char cmds = 0;
ERR fela;
data [x] = 131;
data [++ x] = 152;
y = ++ x;
för (jag = 0; jag < längd; i ++) {
Switch (script[i][0]) {
fall 0:
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 150;
data [++ x] = 128;
data [++ x] = 0;
data [++ x] = 155;
data [++ x] = skript [i] [1] * 10;
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 0;
data [++ x] = 128;
data [++ x] = 0;
cmds += 3.
bryta;
fall 1:
data [++ x] = 137;
data [++ x] = 255;
data [++ x] = 106;
data [++ x] = 128;
data [++ x] = 0;
data [++ x] = 155;
data [++ x] = skript [i] [1] * 10;
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 0;
data [++ x] = 128;
data [++ x] = 0;
cmds += 3.
bryta;
fall 2:
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 150;
data [++ x] = 1;
data [++ x] = 44.
data [++ x] = 155;
data [++ x] = skript [i] [1] * 10;
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 0;
data [++ x] = 128;
data [++ x] = 0;
cmds += 3.
bryta;
fall 3:
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 150;
data [++ x] = 254;
data [++ x] = 212;
data [++ x] = 155;
data [++ x] = skript [i] [1] * 10;
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 0;
data [++ x] = 128;
data [++ x] = 0;
cmds += 3.
bryta;
fall 4:
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 125;
data [++ x] = 0;
data [++ x] = 1;
data [++ x] = 155;
data [++ x] = skript [i] [1] * 10;
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 0;
data [++ x] = 128;
data [++ x] = 0;
cmds += 3.
bryta;
fall 5:
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 125;
data [++ x] = 255;
data [++ x] = 255;
data [++ x] = 155;
data [++ x] = skript [i] [1] * 10;
data [++ x] = 137;
data [++ x] = 0;
data [++ x] = 0;
data [++ x] = 128;
data [++ x] = 0;
cmds += 3.
bryta;
fall 6:
data [++ x] = 155;
data [++ x] = skript [i] [1] * 10;
cmds + = 1;
bryta;
}
}
data [y] = x + 1.
Connect();
Skicka manus
SrmSend (port, data, x + 1, & err);
SrmSendWait(port);
SrmSendFlush(port);
återvändande fela;
}