summaryrefslogtreecommitdiff
path: root/AT91SAM7S256/Source
diff options
context:
space:
mode:
Diffstat (limited to 'AT91SAM7S256/Source')
-rw-r--r--AT91SAM7S256/Source/BtTest.inc1642
-rw-r--r--AT91SAM7S256/Source/Connections.txt21
-rw-r--r--AT91SAM7S256/Source/Cursor.txt10
-rw-r--r--AT91SAM7S256/Source/Devices.txt21
-rw-r--r--AT91SAM7S256/Source/Display.txt12
-rw-r--r--AT91SAM7S256/Source/Fail.txt12
-rw-r--r--AT91SAM7S256/Source/Font.txt15
-rw-r--r--AT91SAM7S256/Source/Functions.inl3730
-rw-r--r--AT91SAM7S256/Source/Icons.txt297
-rw-r--r--AT91SAM7S256/Source/Info.txt12
-rw-r--r--AT91SAM7S256/Source/LowBattery.txt16
-rw-r--r--AT91SAM7S256/Source/Mainmenu.rms65
-rw-r--r--AT91SAM7S256/Source/Ok.txt11
-rw-r--r--AT91SAM7S256/Source/Port.txt10
-rw-r--r--AT91SAM7S256/Source/RCXintro_1.txt17
-rw-r--r--AT91SAM7S256/Source/RCXintro_10.txt11
-rw-r--r--AT91SAM7S256/Source/RCXintro_11.txt11
-rw-r--r--AT91SAM7S256/Source/RCXintro_12.txt11
-rw-r--r--AT91SAM7S256/Source/RCXintro_13.txt11
-rw-r--r--AT91SAM7S256/Source/RCXintro_14.txt11
-rw-r--r--AT91SAM7S256/Source/RCXintro_15.txt11
-rw-r--r--AT91SAM7S256/Source/RCXintro_16.txt11
-rw-r--r--AT91SAM7S256/Source/RCXintro_2.txt17
-rw-r--r--AT91SAM7S256/Source/RCXintro_3.txt17
-rw-r--r--AT91SAM7S256/Source/RCXintro_4.txt17
-rw-r--r--AT91SAM7S256/Source/RCXintro_5.txt17
-rw-r--r--AT91SAM7S256/Source/RCXintro_6.txt15
-rw-r--r--AT91SAM7S256/Source/RCXintro_7.txt14
-rw-r--r--AT91SAM7S256/Source/RCXintro_8.txt12
-rw-r--r--AT91SAM7S256/Source/RCXintro_9.txt12
-rw-r--r--AT91SAM7S256/Source/Running.txt57
-rw-r--r--AT91SAM7S256/Source/Status.txt15
-rw-r--r--AT91SAM7S256/Source/Step.txt17
-rw-r--r--AT91SAM7S256/Source/Submenu01.rms128
-rw-r--r--AT91SAM7S256/Source/Submenu02.rms401
-rw-r--r--AT91SAM7S256/Source/Submenu03.rms324
-rw-r--r--AT91SAM7S256/Source/Submenu04.rms170
-rw-r--r--AT91SAM7S256/Source/Submenu05.rms128
-rw-r--r--AT91SAM7S256/Source/Submenu06.rms51
-rw-r--r--AT91SAM7S256/Source/Submenu07.rms142
-rw-r--r--AT91SAM7S256/Source/Test1.txt17
-rw-r--r--AT91SAM7S256/Source/Test2.txt17
-rw-r--r--AT91SAM7S256/Source/Ui.txt60
-rw-r--r--AT91SAM7S256/Source/Wait.txt12
-rw-r--r--AT91SAM7S256/Source/c_button.c134
-rw-r--r--AT91SAM7S256/Source/c_button.h37
-rw-r--r--AT91SAM7S256/Source/c_button.iom61
-rw-r--r--AT91SAM7S256/Source/c_cmd.c6292
-rw-r--r--AT91SAM7S256/Source/c_cmd.h804
-rw-r--r--AT91SAM7S256/Source/c_cmd.iom178
-rw-r--r--AT91SAM7S256/Source/c_cmd_alternate.c163
-rw-r--r--AT91SAM7S256/Source/c_cmd_bytecodes.h115
-rw-r--r--AT91SAM7S256/Source/c_cmd_drawing.inc894
-rw-r--r--AT91SAM7S256/Source/c_comm.c3658
-rw-r--r--AT91SAM7S256/Source/c_comm.h151
-rw-r--r--AT91SAM7S256/Source/c_comm.iom222
-rw-r--r--AT91SAM7S256/Source/c_display.c859
-rw-r--r--AT91SAM7S256/Source/c_display.h43
-rw-r--r--AT91SAM7S256/Source/c_display.iom177
-rw-r--r--AT91SAM7S256/Source/c_input.c777
-rw-r--r--AT91SAM7S256/Source/c_input.h53
-rw-r--r--AT91SAM7S256/Source/c_input.iom109
-rw-r--r--AT91SAM7S256/Source/c_ioctrl.c78
-rw-r--r--AT91SAM7S256/Source/c_ioctrl.h28
-rw-r--r--AT91SAM7S256/Source/c_ioctrl.iom35
-rw-r--r--AT91SAM7S256/Source/c_loader.c458
-rw-r--r--AT91SAM7S256/Source/c_loader.h44
-rw-r--r--AT91SAM7S256/Source/c_loader.iom83
-rw-r--r--AT91SAM7S256/Source/c_lowspeed.c236
-rw-r--r--AT91SAM7S256/Source/c_lowspeed.h61
-rw-r--r--AT91SAM7S256/Source/c_lowspeed.iom95
-rw-r--r--AT91SAM7S256/Source/c_output.c169
-rw-r--r--AT91SAM7S256/Source/c_output.h31
-rw-r--r--AT91SAM7S256/Source/c_output.iom92
-rw-r--r--AT91SAM7S256/Source/c_sound.c309
-rw-r--r--AT91SAM7S256/Source/c_sound.h44
-rw-r--r--AT91SAM7S256/Source/c_sound.iom109
-rw-r--r--AT91SAM7S256/Source/c_ui.c1982
-rw-r--r--AT91SAM7S256/Source/c_ui.h352
-rw-r--r--AT91SAM7S256/Source/c_ui.iom116
-rw-r--r--AT91SAM7S256/Source/d_bt.c453
-rw-r--r--AT91SAM7S256/Source/d_bt.h39
-rw-r--r--AT91SAM7S256/Source/d_bt.r350
-rw-r--r--AT91SAM7S256/Source/d_button.c36
-rw-r--r--AT91SAM7S256/Source/d_button.h24
-rw-r--r--AT91SAM7S256/Source/d_button.r189
-rw-r--r--AT91SAM7S256/Source/d_display.c53
-rw-r--r--AT91SAM7S256/Source/d_display.h39
-rw-r--r--AT91SAM7S256/Source/d_display.r374
-rw-r--r--AT91SAM7S256/Source/d_hispeed.c48
-rw-r--r--AT91SAM7S256/Source/d_hispeed.h25
-rw-r--r--AT91SAM7S256/Source/d_hispeed.r190
-rw-r--r--AT91SAM7S256/Source/d_input.c104
-rw-r--r--AT91SAM7S256/Source/d_input.h37
-rw-r--r--AT91SAM7S256/Source/d_input.r99
-rw-r--r--AT91SAM7S256/Source/d_ioctrl.c102
-rw-r--r--AT91SAM7S256/Source/d_ioctrl.h25
-rw-r--r--AT91SAM7S256/Source/d_ioctrl.r310
-rw-r--r--AT91SAM7S256/Source/d_loader.c1437
-rw-r--r--AT91SAM7S256/Source/d_loader.h99
-rw-r--r--AT91SAM7S256/Source/d_loader.r117
-rw-r--r--AT91SAM7S256/Source/d_lowspeed.c77
-rw-r--r--AT91SAM7S256/Source/d_lowspeed.h28
-rw-r--r--AT91SAM7S256/Source/d_lowspeed.r932
-rw-r--r--AT91SAM7S256/Source/d_output.c1605
-rw-r--r--AT91SAM7S256/Source/d_output.h90
-rw-r--r--AT91SAM7S256/Source/d_output.r306
-rw-r--r--AT91SAM7S256/Source/d_sound.c70
-rw-r--r--AT91SAM7S256/Source/d_sound.h42
-rw-r--r--AT91SAM7S256/Source/d_sound.r514
-rw-r--r--AT91SAM7S256/Source/d_sound_adpcm.r156
-rw-r--r--AT91SAM7S256/Source/d_timer.c42
-rw-r--r--AT91SAM7S256/Source/d_timer.h26
-rw-r--r--AT91SAM7S256/Source/d_timer.r56
-rw-r--r--AT91SAM7S256/Source/d_usb.c946
-rw-r--r--AT91SAM7S256/Source/d_usb.h51
-rw-r--r--AT91SAM7S256/Source/d_usb.r65
-rw-r--r--AT91SAM7S256/Source/m_sched.c94
-rw-r--r--AT91SAM7S256/Source/m_sched.h135
-rw-r--r--AT91SAM7S256/Source/modules.h343
-rw-r--r--AT91SAM7S256/Source/stdconst.h48
121 files changed, 36453 insertions, 0 deletions
diff --git a/AT91SAM7S256/Source/BtTest.inc b/AT91SAM7S256/Source/BtTest.inc
new file mode 100644
index 0000000..b4626ab
--- /dev/null
+++ b/AT91SAM7S256/Source/BtTest.inc
@@ -0,0 +1,1642 @@
+//******* TestPrg ************************************************************
+
+#include "Test1.txt"
+#include "Test2.txt"
+
+
+extern void BtIo(void);
+
+const char BUILD_DATE[] = __DATE__;
+const char BUILD_TIME[] = __TIME__;
+
+const char MONTH[] = "JanFebMarAprMajJunJulAugSepOktNovDec";
+
+void GetProtocolVersion(UBYTE *String)
+{
+ sprintf((char*)String,"FW %2X.%02X",(FIRMWAREVERSION >> 8),FIRMWAREVERSION & 0x00FF);
+}
+
+
+void GetARMBuild(UBYTE *String)
+{
+ UWORD Tmp;
+ UWORD Lng;
+ char String1[4];
+ char String2[4];
+
+ String1[0] = BUILD_DATE[4];
+ String1[1] = BUILD_DATE[5];
+ String1[2] = 0;
+
+ Tmp = (UWORD)atoi(String1);
+ Lng = 0;
+ Lng += sprintf((char*)&String[Lng],"BUILD ");
+ Lng += sprintf((char*)&String[Lng],"%02u",Tmp);
+
+ String1[0] = BUILD_DATE[0];
+ String1[1] = BUILD_DATE[1];
+ String1[2] = BUILD_DATE[2];
+ String1[3] = 0;
+ String2[3] = 0;
+
+ Tmp = 0;
+ do
+ {
+ String2[0] = MONTH[0 + 3 * Tmp];
+ String2[1] = MONTH[1 + 3 * Tmp];
+ String2[2] = MONTH[2 + 3 * Tmp];
+ Tmp++;
+ }
+ while ((Tmp < 12) && (strcmp(String1,String2) != 0));
+
+ Lng += sprintf((char*)&String[Lng],"%02u",Tmp);
+ Lng += sprintf((char*)&String[Lng],"%c%c",BUILD_DATE[9],BUILD_DATE[10]);
+ Lng += sprintf((char*)&String[Lng],"%c%c",BUILD_TIME[0],BUILD_TIME[1]);
+ Lng += sprintf((char*)&String[Lng],"%c%c",BUILD_TIME[3],BUILD_TIME[4]);
+}
+
+
+void GetBC4Build(UBYTE *String)
+{
+ sprintf((char*)String,"BC4 %2X.%02X",pMapComm->BrickData.BluecoreVersion[1],pMapComm->BrickData.BluecoreVersion[0]);
+}
+
+
+void GetAVRBuild(UBYTE *String)
+{
+ sprintf((char*)String,"AVR %1u.%02u",((IoFromAvr.Battery >> 13) & 3),((IoFromAvr.Battery >> 10) & 7));
+}
+
+
+void GetBC4Address(UBYTE *String)
+{
+ UWORD Count;
+ UBYTE Tmp;
+
+ Count = (UWORD)sprintf((char*)String,"ID ");
+ for (Tmp = 0;(Tmp < (SIZE_OF_BDADDR - 1)) && (Count <= (DISPLAYLINE_LENGTH - 2));Tmp++)
+ {
+ Count += (UWORD)sprintf((char*)&String[Count],"%02X",(UWORD)(pMapComm->BrickData.BdAddr[Tmp]) & 0xFF);
+ }
+}
+
+
+enum TSTPRG
+{
+ SYSTEM_INIT = 1,
+ SYSTEM_UNLOCK_INIT,
+ SYSTEM_UNLOCK,
+ SYSTEM_PAGE,
+ TIMER_INIT,
+ TIMER_SHOW,
+ TIMER_HOLD,
+ BT_PAGE,
+ BT_RESET,
+ BT_RESETTING,
+ BT_LIST_INIT,
+ BT_LIST,
+ BT_CONN_INIT,
+ BT_CONN,
+ BT_UPDATE_FW,
+ TSTPRG_INIT,
+ TSTPRG_SELECT_SUBTEST,
+
+ TSTPRG_SENSOR_INIT,
+ TSTPRG_SELECT_SENSOR,
+ TSTPRG_TOUCH_SENSOR_INIT,
+ TSTPRG_TOUCH_SENSOR,
+ TSTPRG_SOUND_SENSOR_SELECT,
+ TSTPRG_SOUND_SENSOR_INIT,
+ TSTPRG_SOUND_SENSOR,
+ TSTPRG_LIGHT_SENSOR_SELECT,
+ TSTPRG_LIGHT_SENSOR_INIT,
+ TSTPRG_LIGHT_SENSOR,
+ TSTPRG_SKIP_SENSOR,
+
+ TSTPRG_RCX_INIT,
+ TSTPRG_RCX_SELECT,
+ TSTPRG_RCX_DISPLAY_INIT,
+ TSTPRG_RCX_DISPLAY,
+ TSTPRG_RCX_INPUT_SELECT,
+ TSTPRG_RCX_INPUT_INIT,
+ TSTPRG_RCX_INPUT,
+ TSTPRG_RCX_DIGITAL_INIT,
+ TSTPRG_RCX_DIGITAL_OK,
+ TSTPRG_RCX_DIGITAL_FAIL,
+ TSTPRG_RCX_DIGITAL,
+ TSTPRG_RCX_MOTOR_INIT,
+ TSTPRG_RCX_MOTOR,
+ TSTPRG_SKIP_RCX_MOTOR,
+ TSTPRG_SKIP_RCX,
+
+ TSTPRG_MOTOR_INIT,
+ TSTPRG_MOTOR,
+ TSTPRG_SKIP_MOTOR,
+
+ TSTPRG_SKIP,
+ TSTPRG_WAIT
+};
+
+const UBYTE TXT_EMPTY[] = " ";
+const UBYTE TXT_LINE[] = "----------------";
+
+#ifdef TESTPRG
+
+const UBYTE TXT_TEST[] = "Timer Test Bt ";
+
+const UBYTE TXT_TIMER[] = "Reset Hold ";
+const UBYTE TXT_TIMER_HOLD[] = " Continue ";
+
+const UBYTE TXT_LAST[] = "Last UI->BT Cmd.";
+const UBYTE TXT_BT_PAGE[] = "Reset List BtIo";
+
+const UBYTE TXT_RESETTING[] = " Resetting! ";
+
+const UBYTE TXT_BT_LIST[] = "Down ConTab Up ";
+const UBYTE TXT_BT_CONN[] = "Down Update Up ";
+
+const UBYTE TXT_BTUPDATE[] = "BT update mode !";
+const UBYTE TXT_DONE[] = " When done ";
+const UBYTE TXT_RESET[] = " activate reset ";
+const UBYTE TXT_REBOOT[] = "button to reboot";
+
+const UBYTE TXT_TESTPRG[] = " TestPrg V0.08 ";
+const UBYTE TXT_SELECT[] = "Select sub test ";
+const UBYTE TXT_SUBTEST[] = "Sens. RCX Motor";
+
+const UBYTE TXT_SELECT_SENSOR[] = " Select sensor ";
+const UBYTE TXT_SENSORS[] = "Touch Snd. Light";
+
+const UBYTE TXT_SELECT_TYPE[] = " Select type ";
+const UBYTE TXT_SOUND_SENSORS[] = " DB DBA ";
+const UBYTE TXT_LIGHT_SENSORS[] = "Pasive Active";
+
+const UBYTE TXT_SENSOR_TOUCH[] = "Touch Sensor Tst";
+const UBYTE TXT_SENSOR_SOUND_DB[] = "DB Sound Sens.";
+const UBYTE TXT_SENSOR_SOUND_DBA[] = "DBA Sound Sens.";
+const UBYTE TXT_SOUND_STOP[] = "440Hz Stop 4KHz";
+const UBYTE TXT_SENSOR_LIGHT_PASIVE[] = "Pas. Light Sens.";
+const UBYTE TXT_SENSOR_LIGHT_ACTIVE[] = "Act. Light Sens.";
+
+const UBYTE TXT_SUBTEST_STOP[] = " Stop ";
+
+const UBYTE TXT_MOTOR[] = " Motor test ";
+const UBYTE TXT_MOTOR_HEADER[] = "Outp Set Cnt";
+const UBYTE TXT_MOTOR_STOP[] = "Bwd Stop Fwd";
+
+const UBYTE TXT_RCX[] = " RCX test ";
+const UBYTE TXT_RCX_STOP[] = "Inp Disp Outp";
+const UBYTE TXT_RCX_INPUT_PASIVE[] = "Input pasive Tst";
+const UBYTE TXT_RCX_INPUT_ACTIVE[] = "Input active Tst";
+const UBYTE TXT_RCX_INPUT_SELECT[] = "Pas. Act. Dig.";
+const UBYTE TXT_RCX_INPUT_DIGITAL[] = "Digital I/O Tst";
+const UBYTE TXT_RCX_DIGITAL_OK[] = " OK ";
+const UBYTE TXT_RCX_DIGITAL_FAIL[] = " FAIL ";
+const UBYTE TXT_MOTOR_NEXT[] = "Bwd Next Fwd";
+
+
+void TestPrgRunMotor(UBYTE No,SBYTE Speed)
+{
+ pMapOutPut->Outputs[No].Mode = MOTORON | BRAKE;
+ pMapOutPut->Outputs[No].Speed = Speed;
+ pMapOutPut->Outputs[No].TachoLimit = 0;
+ pMapOutPut->Outputs[No].RunState = MOTOR_RUN_STATE_RUNNING;
+ pMapOutPut->Outputs[No].Flags = UPDATE_MODE | UPDATE_SPEED | UPDATE_TACHO_LIMIT;
+}
+
+void TestPrgFloatMotor(UBYTE No)
+{
+ pMapOutPut->Outputs[No].Mode = 0;
+ pMapOutPut->Outputs[No].Speed = 0;
+ pMapOutPut->Outputs[No].TachoLimit = 0;
+ pMapOutPut->Outputs[No].RunState = MOTOR_RUN_STATE_RUNNING;
+ pMapOutPut->Outputs[No].Flags = UPDATE_MODE | UPDATE_SPEED | UPDATE_TACHO_LIMIT;
+}
+
+SBYTE TestPrgReadMotor(UBYTE No)
+{
+ return ((SBYTE)(pMapOutPut->Outputs[No].TachoCnt / 360));
+}
+
+#endif
+
+
+UBYTE TestPrg(UBYTE Dummy)
+{
+ static UWORD Count;
+ static UBYTE TxtBuffer[TEXTLINES][DISPLAYLINE_LENGTH + 1];
+ static UBYTE State = SYSTEM_INIT;
+#ifdef TESTPRG
+ static UWORD Pointer;
+ static UWORD InputValues[NO_OF_INPUTS];
+ static SWORD OutputValues[NO_OF_OUTPUTS];
+ static UBYTE VolumeSave;
+ static UBYTE Timer;
+ static UBYTE SubState = 0;
+ UBYTE Tmp;
+#endif
+
+ Dummy = Dummy;
+ switch (State)
+ {
+ case SYSTEM_INIT :
+ {
+ GetProtocolVersion(TxtBuffer[0]);
+ GetAVRBuild(TxtBuffer[1]);
+ GetBC4Build(TxtBuffer[2]);
+ GetARMBuild(TxtBuffer[3]);
+ GetBC4Address(TxtBuffer[4]);
+
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TxtBuffer[0];
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TxtBuffer[1];
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TxtBuffer[2];
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TxtBuffer[3];
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TxtBuffer[4];
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->UpdateMask |= (TEXTLINE_BIT(TEXTLINE_3) | TEXTLINE_BIT(TEXTLINE_4) | TEXTLINE_BIT(TEXTLINE_5) | TEXTLINE_BIT(TEXTLINE_6) | TEXTLINE_BIT(TEXTLINE_7) | TEXTLINE_BIT(TEXTLINE_8));
+
+#ifdef TESTPRG
+ SubState = 0;
+#endif
+ State = SYSTEM_UNLOCK_INIT;
+ }
+ break;
+
+#ifndef TESTPRG
+
+ case SYSTEM_UNLOCK_INIT : // ENTER * 1 + LEFT * 3 + RIGHT * 2 + ENTER * 1 = TEST MENU
+ {
+ if (cUiReadButtons() != BUTTON_NONE)
+ {
+ State = TSTPRG_SKIP;
+ }
+ }
+ break;
+
+#else
+
+ case SYSTEM_UNLOCK_INIT : // ENTER * 1 + LEFT * 3 + RIGHT * 2 + ENTER * 1 = TEST MENU
+ {
+ Tmp = cUiReadButtons();
+ switch (Tmp)
+ {
+ case BUTTON_ENTER :
+ {
+ switch (SubState)
+ {
+ case 0 :
+ {
+ SubState = 1;
+ Pointer = 0;
+ Count = 0;
+ }
+ break;
+
+ case 3 :
+ {
+ State = SYSTEM_UNLOCK;
+ }
+ break;
+
+ default :
+ {
+ Tmp = BUTTON_EXIT;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case BUTTON_NONE :
+ {
+ }
+ break;
+
+ default :
+ {
+ switch (SubState)
+ {
+ case 0 :
+ {
+ Tmp = BUTTON_EXIT;
+ }
+ break;
+
+ case 1 :
+ {
+ if (Tmp == BUTTON_LEFT)
+ {
+ if (++Count >= 3)
+ {
+ Count = 0;
+ SubState = 2;
+ }
+ Pointer = 0;
+ }
+ else
+ {
+ Tmp = BUTTON_EXIT;
+ }
+ }
+ break;
+
+ case 2 :
+ {
+ if (Tmp == BUTTON_RIGHT)
+ {
+ if (++Count >= 2)
+ {
+ SubState = 3;
+ }
+ Pointer = 0;
+ }
+ else
+ {
+ Tmp = BUTTON_EXIT;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ }
+ Pointer++;
+ if (((SubState) && (Pointer > 500)) || (Tmp == BUTTON_EXIT))
+ {
+ State = TSTPRG_SKIP;
+ }
+ }
+ break;
+
+ case SYSTEM_UNLOCK :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_TEST;
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_8);
+ State = SYSTEM_PAGE;
+ }
+ break;
+
+ case SYSTEM_PAGE :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_ENTER :
+ {
+ IOMapUi.Flags &= ~UI_ENABLE_STATUS_UPDATE;
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ State = TSTPRG_INIT;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ Count = 0;
+ State = TSTPRG_SKIP;
+ }
+ break;
+
+ case BUTTON_LEFT :
+ {
+ IOMapUi.Flags &= ~UI_ENABLE_STATUS_UPDATE;
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_TIMER;
+ pMapDisplay->EraseMask |= TEXTLINE_BITS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TIMER_INIT;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ IOMapUi.Flags &= ~UI_ENABLE_STATUS_UPDATE;
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_BT_PAGE;
+ if (DISPLAYLINE_LENGTH >= 16)
+ {
+ sprintf((char*)TxtBuffer[2],"Command %02X",(UWORD)VarsUi.BTCommand & 0xFF);
+ sprintf((char*)TxtBuffer[3],"Parameter 1 %02X",(UWORD)VarsUi.BTPar1 & 0xFF);
+ sprintf((char*)TxtBuffer[4],"Parameter 2 %02X",(UWORD)VarsUi.BTPar2 & 0xFF);
+ sprintf((char*)TxtBuffer[5],"Result %04X",(UWORD)VarsUi.BTResult);
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_LAST;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_3] = TxtBuffer[2];
+ pMapDisplay->pTextLines[TEXTLINE_4] = TxtBuffer[3];
+ pMapDisplay->pTextLines[TEXTLINE_5] = TxtBuffer[4];
+ pMapDisplay->pTextLines[TEXTLINE_6] = TxtBuffer[5];
+ }
+ pMapDisplay->EraseMask |= TEXTLINE_BITS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = BT_PAGE;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TIMER_INIT :
+ {
+ State = TIMER_SHOW;
+ }
+ break;
+
+ case TIMER_SHOW :
+ {
+ sprintf((char*)TxtBuffer[2]," %10lu mS ",VarsUi.CRPasskey);
+ pMapDisplay->pTextLines[TEXTLINE_3] = TxtBuffer[2];
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3);
+
+ switch (cUiReadButtons())
+ {
+ case BUTTON_ENTER :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_TIMER_HOLD;
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_8);
+ State = TIMER_HOLD;
+ }
+ break;
+
+ case BUTTON_LEFT :
+ {
+ pMapDisplay->EraseMask |= TEXTLINE_BIT(TEXTLINE_3);
+ VarsUi.CRPasskey = 0L;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = TSTPRG_SKIP;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TIMER_HOLD :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_ENTER :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_TIMER;
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_8);
+ State = TIMER_SHOW;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = TSTPRG_SKIP;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case BT_PAGE :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_ENTER :
+ {
+ for (Count = 0;Count < TEXTLINES;Count++)
+ {
+ strcpy((char*)TxtBuffer[Count],(char*)TXT_EMPTY);
+ pMapDisplay->pTextLines[TEXTLINE_1 + Count] = TxtBuffer[Count];
+ }
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_BT_LIST;
+ pMapDisplay->EraseMask |= TEXTLINE_BITS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ Pointer = 0;
+ State = BT_LIST_INIT;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ Count = 0;
+ State = TSTPRG_SKIP;
+ }
+ break;
+
+ case BUTTON_LEFT :
+ {
+ State = BT_RESET;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_BTUPDATE;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_DONE;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_RESET;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_REBOOT;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->EraseMask |= TEXTLINE_BITS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ Timer = 0;
+ State = BT_UPDATE_FW;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case BT_RESET :
+ {
+ VarsUi.BTCommand = (UBYTE)FACTORYRESET;
+ VarsUi.BTPar1 = (UBYTE)0;
+ VarsUi.BTPar2 = (UBYTE)0;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_RESETTING;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->EraseMask |= TEXTLINE_BITS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = BT_RESETTING;
+ }
+ else
+ {
+ State = TSTPRG_SKIP;
+ }
+ }
+ break;
+
+ case BT_RESETTING :
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ State = TSTPRG_SKIP;
+ }
+ }
+ break;
+
+ case BT_UPDATE_FW :
+ {
+ if (++Timer >= 100)
+ {
+ BtIo();
+ }
+ }
+ break;
+
+ case BT_LIST_INIT :
+ {
+ sprintf((char*)TxtBuffer[0],"DeviceTable No%2u",Pointer);
+ sprintf((char*)TxtBuffer[2],"%-*.*s",DISPLAYLINE_LENGTH,DISPLAYLINE_LENGTH,(char*)pMapComm->BtDeviceTable[Pointer].Name);
+ Count = (UWORD)sprintf((char*)TxtBuffer[3],"COD=");
+ for (Tmp = 0;(Tmp < SIZE_OF_CLASS_OF_DEVICE) && (Count < (DISPLAYLINE_LENGTH - 2));Tmp++)
+ {
+ Count += (UWORD)sprintf((char*)&TxtBuffer[3][Count],"%02X",(UWORD)(pMapComm->BtDeviceTable[Pointer].ClassOfDevice[Tmp]) & 0xFF);
+ }
+ Count = (UWORD)sprintf((char*)TxtBuffer[4],"A=");
+ for (Tmp = 0;(Tmp < SIZE_OF_BDADDR) && (Count <= (DISPLAYLINE_LENGTH - 2));Tmp++)
+ {
+ Count += (UWORD)sprintf((char*)&TxtBuffer[4][Count],"%02X",(UWORD)(pMapComm->BtDeviceTable[Pointer].BdAddr[Tmp]) & 0xFF);
+ }
+ sprintf((char*)TxtBuffer[5],"Status=%02X",(UWORD)(pMapComm->BtDeviceTable[Pointer].DeviceStatus) & 0xFF);
+ pMapDisplay->EraseMask |= TEXTLINE_BITS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = BT_LIST;
+ }
+ break;
+
+ case BT_LIST :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_ENTER :
+ {
+ for (Count = 0;Count < TEXTLINES;Count++)
+ {
+ strcpy((char*)TxtBuffer[Count],(char*)TXT_EMPTY);
+ pMapDisplay->pTextLines[TEXTLINE_1 + Count] = TxtBuffer[Count];
+ }
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_BT_CONN;
+ pMapDisplay->EraseMask |= TEXTLINE_BITS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ Pointer = 0;
+ State = BT_CONN_INIT;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = SYSTEM_INIT;
+ }
+ break;
+
+ case BUTTON_LEFT :
+ {
+ if (Pointer)
+ {
+ Pointer--;
+ }
+ else
+ {
+ Pointer = (SIZE_OF_BT_DEVICE_TABLE - 1);
+ }
+ State = BT_LIST_INIT;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ if (Pointer < (SIZE_OF_BT_DEVICE_TABLE - 1))
+ {
+ Pointer++;
+ }
+ else
+ {
+ Pointer = 0;
+ }
+ State = BT_LIST_INIT;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case BT_CONN_INIT :
+ {
+ sprintf((char*)TxtBuffer[0],"Conn. Table No%2u",Pointer);
+ sprintf((char*)TxtBuffer[2],"%-*.*s",DISPLAYLINE_LENGTH,DISPLAYLINE_LENGTH,(char*)pMapComm->BtConnectTable[Pointer].Name);
+ Count = (UWORD)sprintf((char*)TxtBuffer[3],"COD=");
+ for (Tmp = 0;(Tmp < SIZE_OF_CLASS_OF_DEVICE) && (Count < (DISPLAYLINE_LENGTH - 2));Tmp++)
+ {
+ Count += (UWORD)sprintf((char*)&TxtBuffer[3][Count],"%02X",(UWORD)(pMapComm->BtConnectTable[Pointer].ClassOfDevice[Tmp]) & 0xFF);
+ }
+ Count = (UWORD)sprintf((char*)TxtBuffer[4],"A=");
+ for (Tmp = 0;(Tmp < SIZE_OF_BDADDR) && (Count <= (DISPLAYLINE_LENGTH - 2));Tmp++)
+ {
+ Count += (UWORD)sprintf((char*)&TxtBuffer[4][Count],"%02X",(UWORD)(pMapComm->BtConnectTable[Pointer].BdAddr[Tmp]) & 0xFF);
+ }
+ sprintf((char*)TxtBuffer[5],"%-*.*s",DISPLAYLINE_LENGTH,DISPLAYLINE_LENGTH,(char*)pMapComm->BtConnectTable[Pointer].PinCode);
+ if (DISPLAYLINE_LENGTH >= 16)
+ {
+ sprintf((char*)TxtBuffer[6],"H=%02X S=%02X Q=%02X",(UWORD)(pMapComm->BtConnectTable[Pointer].HandleNr) & 0xFF,(UWORD)(pMapComm->BtConnectTable[Pointer].StreamStatus) & 0xFF,(UWORD)(pMapComm->BtConnectTable[Pointer].LinkQuality) & 0xFF);
+ }
+ pMapDisplay->EraseMask |= TEXTLINE_BITS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = BT_CONN;
+ }
+ break;
+
+ case BT_CONN :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_ENTER :
+ {
+ State = BT_CONN_INIT;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = SYSTEM_INIT;
+ }
+ break;
+
+ case BUTTON_LEFT :
+ {
+ if (Pointer)
+ {
+ Pointer--;
+ }
+ else
+ {
+ Pointer = (SIZE_OF_BT_CONNECT_TABLE - 1);
+ }
+ State = BT_CONN_INIT;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ if (Pointer < (SIZE_OF_BT_CONNECT_TABLE - 1))
+ {
+ Pointer++;
+ }
+ else
+ {
+ Pointer = 0;
+ }
+ State = BT_CONN_INIT;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_INIT :
+ {
+ IOMapUi.Flags &= ~UI_ENABLE_STATUS_UPDATE;
+
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_TESTPRG;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_SELECT;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_SUBTEST;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+
+ State = TSTPRG_SELECT_SUBTEST;
+ }
+ break;
+
+ case TSTPRG_SELECT_SUBTEST :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ State = TSTPRG_SENSOR_INIT;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ State = TSTPRG_MOTOR_INIT;
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ State = TSTPRG_RCX_INIT;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ Count = 0;
+ State = TSTPRG_SKIP;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_SENSOR_INIT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_TESTPRG;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_SELECT_SENSOR;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_SENSORS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ InputValues[Count] = 0x7FFF;
+ strcpy((char*)TxtBuffer[Count]," ");
+ }
+
+ State = TSTPRG_SELECT_SENSOR;
+ }
+ break;
+
+ case TSTPRG_SELECT_SENSOR :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ State = TSTPRG_TOUCH_SENSOR_INIT;
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_SELECT_TYPE;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_SOUND_SENSORS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_SOUND_SENSOR_SELECT;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_SELECT_TYPE;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_LIGHT_SENSORS;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_LIGHT_SENSOR_SELECT;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = TSTPRG_INIT;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_TOUCH_SENSOR_INIT :
+ {
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3 + Count] = TxtBuffer[Count];
+ }
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_SENSOR_TOUCH;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_SUBTEST_STOP;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = SWITCH;
+ }
+ State = TSTPRG_TOUCH_SENSOR;
+ }
+ break;
+
+ case TSTPRG_TOUCH_SENSOR :
+ {
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ if (InputValues[Count] != pMapInput->Inputs[Count].ADRaw)
+ {
+ InputValues[Count] = pMapInput->Inputs[Count].ADRaw;
+ sprintf((char*)TxtBuffer[Count]," Input %u = %4u ",(UWORD)Count + 1,(UWORD)InputValues[Count]);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3 + Count);
+ }
+ }
+ if (cUiReadButtons() != BUTTON_NONE)
+ {
+ State = TSTPRG_SKIP_SENSOR;
+ }
+ }
+ break;
+
+ case TSTPRG_SOUND_SENSOR_SELECT :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_SENSOR_SOUND_DB;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = SOUND_DB;
+ }
+ State = TSTPRG_SOUND_SENSOR_INIT;
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ State = TSTPRG_SKIP_SENSOR;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = TSTPRG_SKIP_SENSOR;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_SENSOR_SOUND_DBA;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = SOUND_DBA;
+ }
+ State = TSTPRG_SOUND_SENSOR_INIT;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_SOUND_SENSOR_INIT :
+ {
+ VolumeSave = pMapSound->Volume;
+ pMapSound->Volume = MAX_VOLUME;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3 + Count] = TxtBuffer[Count];
+ }
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_SOUND_STOP;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_SOUND_SENSOR;
+ }
+ break;
+
+ case TSTPRG_SOUND_SENSOR :
+ {
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ if (InputValues[Count] != pMapInput->Inputs[Count].ADRaw)
+ {
+ InputValues[Count] = pMapInput->Inputs[Count].ADRaw;
+ sprintf((char*)TxtBuffer[Count]," Input %u = %4u ",(UWORD)Count + 1,(UWORD)InputValues[Count]);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3 + Count);
+ }
+ }
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ pMapSound->Freq = 440;
+ pMapSound->Duration = 2000;
+ pMapSound->Mode = SOUND_TONE;
+ pMapSound->Flags |= SOUND_UPDATE;
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ pMapSound->State = SOUND_STOP;
+ pMapSound->Volume = VolumeSave;
+ State = TSTPRG_SKIP_SENSOR;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ pMapSound->State = SOUND_STOP;
+ pMapSound->Volume = VolumeSave;
+ State = TSTPRG_SKIP_SENSOR;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ pMapSound->Freq = 4000;
+ pMapSound->Duration = 2000;
+ pMapSound->Mode = SOUND_TONE;
+ pMapSound->Flags |= SOUND_UPDATE;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_LIGHT_SENSOR_SELECT :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_SENSOR_LIGHT_PASIVE;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = LIGHT_INACTIVE;
+ }
+ State = TSTPRG_LIGHT_SENSOR_INIT;
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ State = TSTPRG_SKIP_SENSOR;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = TSTPRG_SKIP_SENSOR;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_SENSOR_LIGHT_ACTIVE;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = LIGHT_ACTIVE;
+ }
+ State = TSTPRG_LIGHT_SENSOR_INIT;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_LIGHT_SENSOR_INIT :
+ {
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3 + Count] = TxtBuffer[Count];
+ }
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_SUBTEST_STOP;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_LIGHT_SENSOR;
+ }
+ break;
+
+ case TSTPRG_LIGHT_SENSOR :
+ {
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ if (InputValues[Count] != pMapInput->Inputs[Count].ADRaw)
+ {
+ InputValues[Count] = pMapInput->Inputs[Count].ADRaw;
+ sprintf((char*)TxtBuffer[Count]," Input %u = %4u ",(UWORD)Count + 1,(UWORD)InputValues[Count]);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3 + Count);
+ }
+ }
+ if (cUiReadButtons() != BUTTON_NONE)
+ {
+ State = TSTPRG_SKIP_SENSOR;
+ }
+ }
+ break;
+
+ case TSTPRG_SKIP_SENSOR :
+ {
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = NO_SENSOR;
+ }
+ State = TSTPRG_SENSOR_INIT;
+ }
+ break;
+
+ case TSTPRG_MOTOR_INIT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_MOTOR;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_MOTOR_HEADER;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_MOTOR_STOP;
+
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ OutputValues[Count] = 0x7FFF;
+ TestPrgRunMotor(Count,0);
+ strcpy((char*)TxtBuffer[Count]," ");
+ pMapDisplay->pTextLines[TEXTLINE_4 + Count] = TxtBuffer[Count];
+ }
+
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_MOTOR;
+ }
+ break;
+
+ case TSTPRG_MOTOR :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ if (OutputValues[Count] != (SWORD)TestPrgReadMotor(Count))
+ {
+ OutputValues[Count] = (SWORD)TestPrgReadMotor(Count);
+ sprintf((char*)TxtBuffer[Count]," %c %-4d %4d",(char)Count + 'A',(SWORD)pMapOutPut->Outputs[Count].Speed,OutputValues[Count]);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_4 + Count);
+ }
+ }
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ OutputValues[Count] = 0x7FFF;
+ TestPrgRunMotor(Count,-50);
+ }
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ OutputValues[Count] = 0x7FFF;
+ TestPrgRunMotor(Count,0);
+ }
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = TSTPRG_SKIP_MOTOR;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ OutputValues[Count] = 0x7FFF;
+ TestPrgRunMotor(Count,50);
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_SKIP_MOTOR :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ TestPrgFloatMotor(Count);
+ }
+ State = TSTPRG_INIT;
+ }
+ break;
+
+ case TSTPRG_RCX_INIT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_RCX;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_SELECT;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_RCX_STOP;
+
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_RCX_SELECT;
+ }
+ break;
+
+ case TSTPRG_RCX_SELECT :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_SELECT_TYPE;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_RCX_INPUT_SELECT;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ InputValues[Count] = 0x7FFF;
+ strcpy((char*)TxtBuffer[Count]," ");
+ }
+ State = TSTPRG_RCX_INPUT_SELECT;
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ State = TSTPRG_RCX_DISPLAY_INIT;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ State = TSTPRG_RCX_MOTOR_INIT;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = TSTPRG_INIT;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_RCX_DISPLAY_INIT :
+ {
+ Count = 0;
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ State = TSTPRG_RCX_DISPLAY;
+ }
+ break;
+
+ case TSTPRG_RCX_DISPLAY :
+ {
+ if ((Count & 0x7FF) == 0x000)
+ {
+ pMapDisplay->pScreens[SCREEN_BACKGROUND] = (BMPMAP*)Test1;
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ }
+ if ((Count & 0x7FF) == 0x3FF)
+ {
+ pMapDisplay->pScreens[SCREEN_BACKGROUND] = (BMPMAP*)Test2;
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ }
+ Count++;
+ if (cUiReadButtons() != BUTTON_NONE)
+ {
+ State = TSTPRG_SKIP_RCX;
+ }
+ }
+ break;
+
+ case TSTPRG_RCX_INPUT_SELECT :
+ {
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_RCX_INPUT_PASIVE;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = SWITCH;
+ }
+ State = TSTPRG_RCX_INPUT_INIT;
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_RCX_INPUT_ACTIVE;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = REFLECTION;
+ }
+ State = TSTPRG_RCX_INPUT_INIT;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = TSTPRG_SKIP_RCX;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_RCX_INPUT_DIGITAL;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_SUBTEST_STOP;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = CUSTOM;
+ }
+ SubState = 0;
+ Timer = 0;
+ State = TSTPRG_RCX_DIGITAL_INIT;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_RCX_INPUT_INIT :
+ {
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3 + Count] = TxtBuffer[Count];
+ }
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_SUBTEST_STOP;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_RCX_INPUT;
+ Timer = 0;
+ }
+ break;
+
+ case TSTPRG_RCX_INPUT :
+ {
+ if (++Timer >= 250)
+ {
+ Timer = 0;
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ if (InputValues[Count] != pMapInput->Inputs[Count].ADRaw)
+ {
+ InputValues[Count] = pMapInput->Inputs[Count].ADRaw;
+ sprintf((char*)TxtBuffer[Count]," Input %u = %4u ",(UWORD)Count + 1,(UWORD)InputValues[Count]);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3 + Count);
+ }
+ }
+ }
+ if (cUiReadButtons() != BUTTON_NONE)
+ {
+ State = TSTPRG_SKIP_RCX;
+ }
+ }
+ break;
+
+ case TSTPRG_RCX_DIGITAL_INIT :
+ {
+ if (++Timer >= 20)
+ {
+ Timer = 0;
+ switch (SubState)
+ {
+ case 0 :
+ {
+ pMapInput->Inputs[0].DigiPinsDir |= DIGI0; // Digi 1-0 output -,
+ pMapInput->Inputs[0].DigiPinsDir &= ~DIGI1; // Digi 1-1 input -, |
+ pMapInput->Inputs[2].DigiPinsDir &= ~DIGI0; // Digi 3-0 input | -'
+ pMapInput->Inputs[2].DigiPinsDir |= DIGI1; // Digi 3-1 output -'
+
+ pMapInput->Inputs[0].DigiPinsOut |= DIGI0; // Digi 1-0 output high
+ pMapInput->Inputs[2].DigiPinsOut &= ~DIGI1; // Digi 3-1 output low
+
+ SubState++;
+ }
+ break;
+
+ case 1 :
+ {
+ if ((pMapInput->Inputs[2].DigiPinsIn & DIGI0) && !(pMapInput->Inputs[0].DigiPinsIn & DIGI1))
+ {
+ pMapInput->Inputs[0].DigiPinsOut &= ~DIGI0; // Digi 1-0 output low
+ pMapInput->Inputs[2].DigiPinsOut |= DIGI1; // Digi 3-1 output high
+
+ SubState++;
+ }
+ else
+ {
+ State = TSTPRG_RCX_DIGITAL_FAIL;
+ }
+ }
+ break;
+
+ case 2 :
+ {
+ if (!(pMapInput->Inputs[2].DigiPinsIn & DIGI0) && (pMapInput->Inputs[0].DigiPinsIn & DIGI1))
+ {
+ pMapInput->Inputs[0].DigiPinsDir &= ~DIGI0; // Digi 1-0 input
+ pMapInput->Inputs[0].DigiPinsDir &= ~DIGI1; // Digi 1-1 input
+ pMapInput->Inputs[2].DigiPinsDir &= ~DIGI0; // Digi 3-0 input
+ pMapInput->Inputs[2].DigiPinsDir &= ~DIGI1; // Digi 3-1 input
+
+ pMapInput->Inputs[1].DigiPinsDir |= DIGI0; // Digi 2-0 output -,
+ pMapInput->Inputs[1].DigiPinsDir &= ~DIGI1; // Digi 2-1 input -, |
+ pMapInput->Inputs[3].DigiPinsDir &= ~DIGI0; // Digi 4-0 input | -'
+ pMapInput->Inputs[3].DigiPinsDir |= DIGI1; // Digi 4-1 output -'
+
+ pMapInput->Inputs[1].DigiPinsOut |= DIGI0; // Digi 2-0 output high
+ pMapInput->Inputs[3].DigiPinsOut &= ~DIGI1; // Digi 4-1 output low
+
+ SubState++;
+ }
+ else
+ {
+ State = TSTPRG_RCX_DIGITAL_FAIL;
+ }
+ }
+ break;
+
+ case 3 :
+ {
+ if ((pMapInput->Inputs[3].DigiPinsIn & DIGI0) && !(pMapInput->Inputs[1].DigiPinsIn & DIGI1))
+ {
+ pMapInput->Inputs[1].DigiPinsOut &= ~DIGI0; // Digi 2-0 output low
+ pMapInput->Inputs[3].DigiPinsOut |= DIGI1; // Digi 4-1 output high
+
+ SubState++;
+ }
+ else
+ {
+ State = TSTPRG_RCX_DIGITAL_FAIL;
+ }
+ }
+ break;
+
+ case 4 :
+ {
+ if (!(pMapInput->Inputs[3].DigiPinsIn & DIGI0) && (pMapInput->Inputs[1].DigiPinsIn & DIGI1))
+ {
+ pMapInput->Inputs[1].DigiPinsDir &= ~DIGI0; // Digi 2-0 input
+ pMapInput->Inputs[1].DigiPinsDir &= ~DIGI1; // Digi 2-1 input
+ pMapInput->Inputs[3].DigiPinsDir &= ~DIGI0; // Digi 4-0 input
+ pMapInput->Inputs[3].DigiPinsDir &= ~DIGI1; // Digi 4-1 input
+
+ State = TSTPRG_RCX_DIGITAL_OK;
+ }
+ else
+ {
+ State = TSTPRG_RCX_DIGITAL_FAIL;
+ }
+ }
+ break;
+
+ }
+ }
+ }
+ break;
+
+ case TSTPRG_RCX_DIGITAL_OK :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_RCX_DIGITAL_OK;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_RCX_DIGITAL;
+ }
+ break;
+
+ case TSTPRG_RCX_DIGITAL_FAIL :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_RCX_DIGITAL_FAIL;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_RCX_DIGITAL;
+ }
+ break;
+
+ case TSTPRG_RCX_DIGITAL :
+ {
+ if (cUiReadButtons() != BUTTON_NONE)
+ {
+ State = TSTPRG_SKIP_RCX;
+ }
+ }
+ break;
+
+ case TSTPRG_RCX_MOTOR_INIT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_1] = (UBYTE*)TXT_MOTOR;
+ pMapDisplay->pTextLines[TEXTLINE_2] = (UBYTE*)TXT_LINE;
+ pMapDisplay->pTextLines[TEXTLINE_3] = (UBYTE*)TXT_MOTOR_HEADER;
+ pMapDisplay->pTextLines[TEXTLINE_4] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_5] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_6] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_7] = (UBYTE*)TXT_EMPTY;
+ pMapDisplay->pTextLines[TEXTLINE_8] = (UBYTE*)TXT_MOTOR_NEXT;
+
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ OutputValues[Count] = 0x7FFF;
+ TestPrgRunMotor(Count,0);
+ strcpy((char*)TxtBuffer[Count]," ");
+ pMapDisplay->pTextLines[TEXTLINE_4 + Count] = TxtBuffer[Count];
+ }
+
+ Pointer = 0;
+ pMapDisplay->UpdateMask |= TEXTLINE_BITS;
+ State = TSTPRG_RCX_MOTOR;
+ }
+ break;
+
+ case TSTPRG_RCX_MOTOR :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ if (OutputValues[Count] != (SWORD)TestPrgReadMotor(Count))
+ {
+ OutputValues[Count] = (SWORD)TestPrgReadMotor(Count);
+ if (Pointer == Count)
+ {
+ sprintf((char*)TxtBuffer[Count],"> %c %-4d %4d",(char)Count + 'A',(SWORD)pMapOutPut->Outputs[Count].Speed,OutputValues[Count]);
+ }
+ else
+ {
+ sprintf((char*)TxtBuffer[Count]," %c %-4d %4d",(char)Count + 'A',(SWORD)pMapOutPut->Outputs[Count].Speed,OutputValues[Count]);
+ }
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_4 + Count);
+ }
+ }
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ OutputValues[Count] = 0x7FFF;
+ if (Pointer == Count)
+ {
+ TestPrgRunMotor(Count,-50);
+ }
+ else
+ {
+ TestPrgRunMotor(Count,0);
+ }
+ }
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ OutputValues[Count] = 0x7FFF;
+ TestPrgRunMotor(Count,0);
+ }
+ if (++Pointer >= NO_OF_OUTPUTS)
+ {
+ State = TSTPRG_SKIP_RCX_MOTOR;
+ }
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ State = TSTPRG_SKIP_RCX_MOTOR;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ OutputValues[Count] = 0x7FFF;
+ if (Pointer == Count)
+ {
+ TestPrgRunMotor(Count,50);
+ }
+ else
+ {
+ TestPrgRunMotor(Count,0);
+ }
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case TSTPRG_SKIP_RCX_MOTOR :
+ {
+ for (Count = 0;Count < NO_OF_OUTPUTS;Count++)
+ {
+ TestPrgFloatMotor(Count);
+ }
+ State = TSTPRG_RCX_INIT;
+ }
+ break;
+
+ case TSTPRG_SKIP_RCX :
+ {
+ for (Count = 0;Count < NO_OF_INPUTS;Count++)
+ {
+ pMapInput->Inputs[Count].SensorType = NO_SENSOR;
+ }
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ State = TSTPRG_RCX_INIT;
+ }
+ break;
+
+#endif
+
+ case TSTPRG_SKIP :
+ {
+ Count++;
+ if (Count == 100)
+ {
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ }
+ if (Count >= 200)
+ {
+ IOMapUi.Flags |= UI_REDRAW_STATUS;
+ State = 0;
+ }
+ }
+ break;
+
+ default :
+ {
+ State = SYSTEM_INIT;
+ }
+ break;
+
+ }
+
+ return (State);
+}
diff --git a/AT91SAM7S256/Source/Connections.txt b/AT91SAM7S256/Source/Connections.txt
new file mode 100644
index 0000000..685304f
--- /dev/null
+++ b/AT91SAM7S256/Source/Connections.txt
@@ -0,0 +1,21 @@
+const ICON Connections[] =
+{
+ 0x04,0x00, // Graphics Format
+ 0x01,0x20, // Graphics DataSize
+ 0x01, // Graphics Count X
+ 0x04, // Graphics Count Y
+ 0x18, // Graphics Width
+ 0x18, // Graphics Height
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x00,0x00,0x7E,0x81,0x81,0x7E,0x00,0x00,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x02,0x02,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x00,0x00,0x00,0x82,0xFF,0x80,0x00,0x00,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x02,0x02,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x00,0x00,0xE2,0x91,0x89,0x86,0x00,0x00,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x02,0x02,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x00,0x00,0x42,0x81,0x89,0x76,0x00,0x00,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x02,0x02,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/Cursor.txt b/AT91SAM7S256/Source/Cursor.txt
new file mode 100644
index 0000000..d1e830e
--- /dev/null
+++ b/AT91SAM7S256/Source/Cursor.txt
@@ -0,0 +1,10 @@
+const BMPMAP Cursor[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0x08, // Graphics DataSize
+ 0x00, // Graphics Start X
+ 0x00, // Graphics Start Y
+ 0x07, // Graphics Width
+ 0x08, // Graphics Height
+ 0x21,0x31,0x39,0x3D,0x39,0x31,0x21
+};
diff --git a/AT91SAM7S256/Source/Devices.txt b/AT91SAM7S256/Source/Devices.txt
new file mode 100644
index 0000000..57be902
--- /dev/null
+++ b/AT91SAM7S256/Source/Devices.txt
@@ -0,0 +1,21 @@
+const ICON Devices[] =
+{
+ 0x04,0x00, // Graphics Format
+ 0x01,0x20, // Graphics DataSize
+ 0x01, // Graphics Count X
+ 0x04, // Graphics Count Y
+ 0x18, // Graphics Width
+ 0x18, // Graphics Height
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x82,0x44,0x28,0xFF,0x11,0xAA,0x44,0x00,0x00,0x06,0x01,0x00,0x40,0x20,0x11,0x0E,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x9E,0x91,0x51,0x51,0x51,0x91,0x9E,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x24,0x24,0x24,0x3C,0x25,0x25,0x25,0x3C,0x24,0x24,0x24,0x3F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x70,0x08,0x30,0x40,0x40,0x40,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x4E,0x91,0x51,0x91,0x51,0x8E,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x10,0x11,0x12,0x11,0x12,0x11,0x12,0x10,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x06,0x07,0x05,0x06,0x05,0x06,0x05,0x06,0x05,0x06,0x05,0x06,0x05,0x07,0x06,0x00,0x00,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/Display.txt b/AT91SAM7S256/Source/Display.txt
new file mode 100644
index 0000000..049eeaf
--- /dev/null
+++ b/AT91SAM7S256/Source/Display.txt
@@ -0,0 +1,12 @@
+const BMPMAP Display[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0xD8, // Graphics DataSize
+ 0x0E, // Graphics Start X
+ 0x10, // Graphics Start Y
+ 0x48, // Graphics Width
+ 0x18, // Graphics Height
+ 0xF8,0xFC,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0E,0xFC,0xF8,0xC0,
+ 0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,
+ 0x0F,0x1F,0x38,0x30,0x30,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x78,0x7F,0x3F,0x1F
+};
diff --git a/AT91SAM7S256/Source/Fail.txt b/AT91SAM7S256/Source/Fail.txt
new file mode 100644
index 0000000..6048462
--- /dev/null
+++ b/AT91SAM7S256/Source/Fail.txt
@@ -0,0 +1,12 @@
+const BMPMAP Fail[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0x48, // Graphics DataSize
+ 0x00, // Graphics Start X
+ 0x08, // Graphics Start Y
+ 0x18, // Graphics Width
+ 0x18, // Graphics Height
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x03,0x00,0x7C,0x00,0x03,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x04,0x04,0x04,0x04,0x04,0x05,0x04,0x04,0x04,0x04,0x04,0x03,0x00,0x00,0x00,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/Font.txt b/AT91SAM7S256/Source/Font.txt
new file mode 100644
index 0000000..e748f76
--- /dev/null
+++ b/AT91SAM7S256/Source/Font.txt
@@ -0,0 +1,15 @@
+const ICON Font[] =
+{
+ 0x04,0x00, // Graphics Format
+ 0x02,0x40, // Graphics DataSize
+ 0x10, // Graphics Count X
+ 0x06, // Graphics Count Y
+ 0x06, // Graphics Width
+ 0x08, // Graphics Height
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x5F,0x06,0x00,0x00,0x07,0x03,0x00,0x07,0x03,0x00,0x24,0x7E,0x24,0x7E,0x24,0x00,0x24,0x2B,0x6A,0x12,0x00,0x00,0x63,0x13,0x08,0x64,0x63,0x00,0x30,0x4C,0x52,0x22,0x50,0x00,0x00,0x07,0x03,0x00,0x00,0x00,0x00,0x3E,0x41,0x00,0x00,0x00,0x00,0x41,0x3E,0x00,0x00,0x00,0x08,0x3E,0x1C,0x3E,0x08,0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x80,0x60,0x60,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x00,
+ 0x3E,0x51,0x49,0x45,0x3E,0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x22,0x49,0x49,0x49,0x36,0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x2F,0x49,0x49,0x49,0x31,0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00,0x6C,0x6C,0x00,0x00,0x00,0x00,0xEC,0x6C,0x00,0x00,0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x24,0x24,0x24,0x24,0x24,0x00,0x00,0x41,0x22,0x14,0x08,0x00,0x02,0x01,0x59,0x09,0x06,0x00,
+ 0x3E,0x41,0x5D,0x55,0x1E,0x00,0x7E,0x11,0x11,0x11,0x7E,0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x7F,0x41,0x41,0x41,0x3E,0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x3E,0x41,0x49,0x49,0x7A,0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00,0x41,0x7F,0x41,0x00,0x00,0x30,0x40,0x40,0x40,0x3F,0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x7F,0x02,0x04,0x02,0x7F,0x00,0x7F,0x02,0x04,0x08,0x7F,0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,
+ 0x7F,0x09,0x09,0x09,0x06,0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x7F,0x09,0x09,0x19,0x66,0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x3F,0x40,0x3C,0x40,0x3F,0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x07,0x08,0x70,0x08,0x07,0x00,0x71,0x49,0x45,0x43,0x00,0x00,0x00,0x7F,0x41,0x41,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00,0x41,0x41,0x7F,0x00,0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
+ 0x00,0x02,0x05,0x02,0x00,0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x7F,0x44,0x44,0x44,0x38,0x00,0x38,0x44,0x44,0x44,0x28,0x00,0x38,0x44,0x44,0x44,0x7F,0x00,0x38,0x54,0x54,0x54,0x08,0x00,0x08,0x7E,0x09,0x09,0x00,0x00,0x18,0x24,0xA4,0xA4,0xFC,0x00,0x7F,0x04,0x04,0x78,0x00,0x00,0x00,0x00,0x7D,0x40,0x00,0x00,0x40,0x80,0x84,0x7D,0x00,0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x7F,0x40,0x00,0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x7C,0x04,0x04,0x78,0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00,
+ 0xFC,0x44,0x44,0x44,0x38,0x00,0x38,0x44,0x44,0x44,0xFC,0x00,0x44,0x78,0x44,0x04,0x08,0x00,0x08,0x54,0x54,0x54,0x20,0x00,0x04,0x3E,0x44,0x24,0x00,0x00,0x3C,0x40,0x20,0x7C,0x00,0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x3C,0x60,0x30,0x60,0x3C,0x00,0x6C,0x10,0x10,0x6C,0x00,0x00,0x9C,0xA0,0x60,0x3C,0x00,0x00,0x64,0x54,0x54,0x4C,0x00,0x00,0x08,0x3E,0x41,0x41,0x00,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x00,0x41,0x41,0x3E,0x08,0x00,0x02,0x01,0x02,0x01,0x00,0x00,0x10,0x20,0x40,0x38,0x07,0x00
+};
diff --git a/AT91SAM7S256/Source/Functions.inl b/AT91SAM7S256/Source/Functions.inl
new file mode 100644
index 0000000..e641409
--- /dev/null
+++ b/AT91SAM7S256/Source/Functions.inl
@@ -0,0 +1,3730 @@
+//
+// Programmer
+//
+// Date init 26.04.2005
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: $
+//
+// Filename $Workfile:: $
+//
+// Version $Revision:: $
+//
+// Archive $Archive:: $
+//
+// Platform C
+//
+
+//******* cUiBtTest **********************************************************
+
+const UBYTE NONVOLATILE_NAME[] = UI_NONVOLATILE; // Non volatile filename without extention
+const UBYTE DEFAULT_PROGRAM_NAME[] = UI_PROGRAM_DEFAULT; // On brick programming filename without extention
+const UBYTE TEMP_PROGRAM_FILENAME[] = UI_PROGRAM_TEMP; // On brick programming tmp filename
+const UBYTE VM_PROGRAM_READER[] = UI_PROGRAM_READER; // On brick programming script reader filename without extention
+const UBYTE DEFAULT_PIN_CODE[] = UI_PINCODE_DEFAULT; // Default blue tooth pin code
+const UBYTE TXT_INVALID_SENSOR[] = "??????????????"; // Display invalid sensor data
+
+
+#define SENSORS (MENU_SENSOR_INVALID - MENU_SENSOR_EMPTY)
+
+const UBYTE SENSORTYPE[SENSORS] = // for view and datalog
+{
+ 0, // MENU_SENSOR_EMPTY
+ SOUND_DB, // MENU_SENSOR_SOUND_DB
+ SOUND_DBA, // MENU_SENSOR_SOUND_DBA
+ LIGHT_ACTIVE, // MENU_SENSOR_LIGHT
+ LIGHT_INACTIVE, // MENU_SENSOR_LIGHT_AMB
+ REFLECTION, // MENU_SENSOR_LIGHT_OLD
+ SWITCH, // MENU_SENSOR_TOUCH
+ 0, // MENU_SENSOR_MOTOR_DEG
+ 0, // MENU_SENSOR_MOTOR_ROT
+ ANGLE, // MENU_SENSOR_ROTATION
+ LOWSPEED_9V, // MENU_SENSOR_ULTRASONIC_IN
+ LOWSPEED_9V, // MENU_SENSOR_ULTRASONIC_CM
+ TEMPERATURE, // MENU_SENSOR_TEMP_C
+ TEMPERATURE // MENU_SENSOR_TEMP_F
+};
+
+const UBYTE SENSORMODE[SENSORS] = // for view and datalog
+{
+ 0, // MENU_SENSOR_EMPTY
+ PCTFULLSCALEMODE, // MENU_SENSOR_SOUND_DB
+ PCTFULLSCALEMODE, // MENU_SENSOR_SOUND_DBA
+ PCTFULLSCALEMODE, // MENU_SENSOR_LIGHT
+ PCTFULLSCALEMODE, // MENU_SENSOR_LIGHT_AMB
+ PCTFULLSCALEMODE, // MENU_SENSOR_LIGHT_OLD
+ BOOLEANMODE, // MENU_SENSOR_TOUCH
+ 0, // MENU_SENSOR_MOTOR_DEG
+ 0, // MENU_SENSOR_MOTOR_ROT
+ ANGLESTEPSMODE, // MENU_SENSOR_ROTATION
+ 0, // MENU_SENSOR_ULTRASONIC_IN
+ 0, // MENU_SENSOR_ULTRASONIC_CM
+ CELSIUSMODE, // MENU_SENSOR_TEMP_C
+ FAHRENHEITMODE // MENU_SENSOR_TEMP_F
+};
+
+const UBYTE SENSORFORMAT[SENSORS][10] =
+{
+ "", // MENU_SENSOR_EMPTY
+ "%3.0f %%", // MENU_SENSOR_SOUND_DB
+ "%3.0f %%", // MENU_SENSOR_SOUND_DBA
+ "%3.0f %%", // MENU_SENSOR_LIGHT
+ "%3.0f %%", // MENU_SENSOR_LIGHT_AMB
+ "%3.0f %%", // MENU_SENSOR_LIGHT_OLD
+ "%1.0f", // MENU_SENSOR_TOUCH
+ "%8.0f `", // MENU_SENSOR_MOTOR_DEG
+ "%8.0f R", // MENU_SENSOR_MOTOR_ROT
+ "%6.0f T", // MENU_SENSOR_ROTATION
+ "%3.0f In", // MENU_SENSOR_ULTRASONIC_IN
+ "%3.0f cm", // MENU_SENSOR_ULTRASONIC_CM
+ "%5.1f `C", // MENU_SENSOR_TEMP_C
+ "%5.1f `F" // MENU_SENSOR_TEMP_F
+};
+
+const float SENSORDIVIDER[SENSORS] =
+{
+ 1.0, // MENU_SENSOR_EMPTY
+ 1.0, // MENU_SENSOR_SOUND_DB
+ 1.0, // MENU_SENSOR_SOUND_DBA
+ 1.0, // MENU_SENSOR_LIGHT
+ 1.0, // MENU_SENSOR_LIGHT_AMB
+ 1.0, // MENU_SENSOR_LIGHT_OLD
+ 1.0, // MENU_SENSOR_TOUCH
+ 1.0, // MENU_SENSOR_MOTOR_DEG
+ 360.0, // MENU_SENSOR_MOTOR_ROT
+ 1.0, // MENU_SENSOR_ROTATION
+ 2.54, // MENU_SENSOR_ULTRASONIC_IN
+ 1.0, // MENU_SENSOR_ULTRASONIC_CM
+ 10.0, // MENU_SENSOR_TEMP_C
+ 10.0 // MENU_SENSOR_TEMP_F
+};
+
+
+//******* cUiSetupUltrasonic *************************************************
+
+void cUiSetupUltrasonic(UBYTE Port)
+{
+ Port -= MENU_PORT_1;
+ pMapLowSpeed->OutBuf[Port].InPtr = 0;
+ pMapLowSpeed->OutBuf[Port].OutPtr = 0;
+
+ pMapLowSpeed->OutBuf[Port].Buf[pMapLowSpeed->OutBuf[Port].InPtr] = ULTRA_SONIC; // Device Adress
+ pMapLowSpeed->OutBuf[Port].InPtr++;
+ pMapLowSpeed->OutBuf[Port].Buf[pMapLowSpeed->OutBuf[Port].InPtr] = 0x41; // Function => Set command
+ pMapLowSpeed->OutBuf[Port].InPtr++;
+ pMapLowSpeed->OutBuf[Port].Buf[pMapLowSpeed->OutBuf[Port].InPtr] = 0x02; // Function => Set to continiues measurement
+ pMapLowSpeed->OutBuf[Port].InPtr++;
+
+ pMapLowSpeed->InBuf[Port].BytesToRx = 0;
+ pMapLowSpeed->ChannelState[Port] = LOWSPEED_INIT;
+ pMapLowSpeed->State |= (COM_CHANNEL_ONE_ACTIVE << Port);
+}
+
+
+
+//******* cUiAskUltrasonic ***************************************************
+
+void cUiAskUltrasonic(UBYTE Port)
+{
+ Port -= MENU_PORT_1;
+ pMapLowSpeed->OutBuf[Port].InPtr = 0;
+ pMapLowSpeed->OutBuf[Port].OutPtr = 0;
+
+ pMapLowSpeed->OutBuf[Port].Buf[pMapLowSpeed->OutBuf[Port].InPtr] = ULTRA_SONIC; // Device Adress
+ pMapLowSpeed->OutBuf[Port].InPtr++;
+ pMapLowSpeed->OutBuf[Port].Buf[pMapLowSpeed->OutBuf[Port].InPtr] = 0x42; // Function => Read result 1
+ pMapLowSpeed->OutBuf[Port].InPtr++;
+
+ pMapLowSpeed->InBuf[Port].BytesToRx = 1;
+ pMapLowSpeed->ChannelState[Port] = LOWSPEED_INIT;
+ pMapLowSpeed->State |= (COM_CHANNEL_ONE_ACTIVE << Port);
+}
+
+
+
+//******* cUiReadUltrasonic **************************************************
+
+UBYTE cUiReadUltrasonic(UBYTE Port)
+{
+ UBYTE Result;
+
+ Port -= MENU_PORT_1;
+ if ((pMapLowSpeed->ChannelState[Port] == LOWSPEED_IDLE) || (pMapLowSpeed->ChannelState[Port] == LOWSPEED_DONE))
+ {
+ Result = (UBYTE)pMapLowSpeed->InBuf[Port].Buf[pMapLowSpeed->InBuf[Port].OutPtr];
+ pMapLowSpeed->InBuf[Port].OutPtr++;
+ if (pMapLowSpeed->InBuf[Port].OutPtr >= SIZE_OF_LSBUF)
+ {
+ pMapLowSpeed->InBuf[Port].OutPtr = 0;
+ }
+ if (Result == 0)
+ {
+ Result = 0xFF;
+ }
+ }
+ else
+ {
+ Result = 0xFF;
+ }
+
+ return (Result);
+}
+
+
+
+//******* cUiResetSensor *****************************************************
+
+void cUiResetSensor(UBYTE Port,UBYTE Sensor) // Set sensor parameters
+{
+ switch (Sensor)
+ {
+ case MENU_SENSOR_MOTOR_DEG :
+ {
+ pMapOutPut->Outputs[Port - MENU_PORT_A].Flags |= UPDATE_RESET_COUNT;
+ }
+ break;
+
+ case MENU_SENSOR_MOTOR_ROT :
+ {
+ pMapOutPut->Outputs[Port - MENU_PORT_A].Flags |= UPDATE_RESET_COUNT;
+ }
+ break;
+
+ case MENU_SENSOR_ROTATION :
+ {
+ pMapInput->Inputs[Port - MENU_PORT_1].SensorValue = 0;
+ }
+ break;
+
+ }
+}
+
+
+
+//******* cUiSetupSensor *****************************************************
+
+void cUiSetupSensor(UBYTE Port,UBYTE Sensor) // Set sensor parameters
+{
+ switch (Sensor)
+ {
+ case MENU_SENSOR_MOTOR_DEG :
+ {
+ pMapOutPut->Outputs[Port - MENU_PORT_A].Mode &= ~(BRAKE | MOTORON);
+ pMapOutPut->Outputs[Port - MENU_PORT_A].Flags |= UPDATE_MODE | UPDATE_SPEED;
+ pMapOutPut->Outputs[Port - MENU_PORT_A].TachoCnt = 0;
+ }
+ break;
+
+ case MENU_SENSOR_MOTOR_ROT :
+ {
+ pMapOutPut->Outputs[Port - MENU_PORT_A].Mode &= ~(BRAKE | MOTORON);
+ pMapOutPut->Outputs[Port - MENU_PORT_A].Flags |= UPDATE_MODE | UPDATE_SPEED;
+ pMapOutPut->Outputs[Port - MENU_PORT_A].TachoCnt = 0;
+ }
+ break;
+
+ case MENU_SENSOR_ULTRASONIC_IN :
+ {
+ pMapInput->Inputs[Port - MENU_PORT_1].SensorType = SENSORTYPE[Sensor - MENU_SENSOR_EMPTY];
+ cUiSetupUltrasonic(Port);
+ }
+ break;
+
+ case MENU_SENSOR_ULTRASONIC_CM :
+ {
+ pMapInput->Inputs[Port - MENU_PORT_1].SensorType = SENSORTYPE[Sensor - MENU_SENSOR_EMPTY];
+ cUiSetupUltrasonic(Port);
+ }
+ break;
+
+ default :
+ {
+ pMapInput->Inputs[Port - MENU_PORT_1].SensorType = SENSORTYPE[Sensor - MENU_SENSOR_EMPTY];
+ pMapInput->Inputs[Port - MENU_PORT_1].SensorMode = SENSORMODE[Sensor - MENU_SENSOR_EMPTY];
+ }
+ break;
+
+ }
+}
+
+
+
+//******* cUiAskSensor *******************************************************
+
+void cUiAskSensor(UBYTE Port,UBYTE Sensor) // Ask for sensor data
+{
+ switch (Sensor)
+ {
+ case MENU_SENSOR_ULTRASONIC_IN :
+ {
+ cUiAskUltrasonic(Port);
+ }
+ break;
+
+ case MENU_SENSOR_ULTRASONIC_CM :
+ {
+ cUiAskUltrasonic(Port);
+ }
+ break;
+
+ default :
+ {
+ }
+ break;
+
+ }
+}
+
+
+
+//******* cUiGetSensorValue **************************************************
+
+UBYTE cUiGetSensorValue(UBYTE Port,UBYTE Sensor,SLONG *Value)
+{
+ UBYTE Result = FALSE;
+
+ *Value = 0L;
+ switch (Sensor)
+ {
+ case MENU_SENSOR_MOTOR_DEG :
+ {
+ *Value = pMapOutPut->Outputs[Port - MENU_PORT_A].TachoCnt;
+ Result = TRUE;
+ }
+ break;
+
+ case MENU_SENSOR_MOTOR_ROT :
+ {
+ *Value = pMapOutPut->Outputs[Port - MENU_PORT_A].TachoCnt;
+ Result = TRUE;
+ }
+ break;
+
+ case MENU_SENSOR_ULTRASONIC_IN :
+ {
+ Result = cUiReadUltrasonic(Port);
+ if (Result != 0xFF)
+ {
+ *Value = Result;
+ Result = TRUE;
+ }
+ else
+ {
+ Result = FALSE;
+ }
+ }
+ break;
+
+ case MENU_SENSOR_ULTRASONIC_CM :
+ {
+ Result = cUiReadUltrasonic(Port);
+ if (Result != 0xFF)
+ {
+ *Value = Result;
+ Result = TRUE;
+ }
+ else
+ {
+ Result = FALSE;
+ }
+ }
+ break;
+
+ default :
+ {
+ if (pMapInput->Inputs[Port - MENU_PORT_1].InvalidData != INVALID_DATA)
+ {
+ *Value = pMapInput->Inputs[Port - MENU_PORT_1].SensorValue;
+ Result = TRUE;
+ }
+ }
+ break;
+
+ }
+
+ return (Result);
+}
+
+
+
+//******* cUiPrintSensorInDisplayBuffer **************************************
+
+void cUiPrintSensorInDisplayBuffer(UBYTE Port,UBYTE Sensor,UBYTE Valid,SLONG Value)
+{
+ SWORD Tmp;
+
+ Tmp = sprintf((char*)VarsUi.DisplayBuffer,(char*)SENSORFORMAT[Sensor - MENU_SENSOR_EMPTY],(float)0);
+ if (Valid == TRUE)
+ {
+ if (Tmp < sprintf((char*)VarsUi.DisplayBuffer,(char*)SENSORFORMAT[Sensor - MENU_SENSOR_EMPTY],(float)Value / SENSORDIVIDER[Sensor - MENU_SENSOR_EMPTY]))
+ {
+ sprintf((char*)VarsUi.DisplayBuffer,"%*.*s",Tmp,Tmp,(char*)TXT_INVALID_SENSOR);
+ }
+ }
+ else
+ {
+ sprintf((char*)VarsUi.DisplayBuffer,"%*.*s",Tmp,Tmp,(char*)TXT_INVALID_SENSOR);
+ }
+}
+
+
+
+//******* cUiReleaseSensors **************************************************
+
+void cUiReleaseSensors(void)
+{
+ UBYTE Tmp;
+
+ for (Tmp = 0;Tmp < NO_OF_INPUTS;Tmp++)
+ {
+ pMapInput->Inputs[Tmp].SensorType = NO_SENSOR;
+ }
+}
+
+
+
+//******* cUiBtCommand *******************************************************
+
+enum
+{
+ UI_BT_CTRL,
+
+ UI_BT_GET_DEVICES, // (UI_BT_GET_DEVICES,Known,*pDevices,NULL) [Known = 0,1]
+ UI_BT_GET_DEVICE_NAME, // (UI_BT_GET_DEVICE_NAME,Known,*pIndex,*pDeviceName) [Known = 0,1]
+ UI_BT_GET_DEVICE_TYPE, // (UI_BT_GET_DEVICE_TYPE,Known,*pIndex,*pDeviceType) [Known = 0,1]
+
+ UI_BT_GET_CONNECTION_NAME, // (UI_BT_GET_CONNECTION_NAME,NULL,*pConnection,*pConnectionName)
+ UI_BT_GET_CONNECTION_TYPE, // (UI_BT_GET_CONNECTION_TYPE,NULL,*pConnection,*pConnectionType)
+ UI_BT_GET_CONNECTION_VALID, // (UI_BT_GET_CONNECTION_NAME,NULL,*pConnection,NULL)
+
+ UI_BT_DUMMY
+};
+
+
+#define UI_BT_FAILED 0x8200 // General command failed
+#define UI_BT_SUCCES 0x0000 // Command executed succesfully
+
+
+UBYTE cUiBTGetDeviceType(UBYTE *pCOD)
+{
+ ULONG COD;
+ UBYTE Result;
+ UBYTE Tmp;
+
+ COD = 0;
+ for (Tmp = 0;Tmp < SIZE_OF_CLASS_OF_DEVICE;Tmp++)
+ {
+ COD <<= 8;
+ COD |= (ULONG)*pCOD;
+ pCOD++;
+ }
+
+ Result = DEVICETYPE_UNKNOWN;
+ if ((COD & 0x00001FFF) == 0x00000804)
+ {
+ Result = DEVICETYPE_NXT;
+ }
+ if ((COD & 0x00001F00) == 0x00000200)
+ {
+ Result = DEVICETYPE_PHONE;
+ }
+ if ((COD & 0x00001F00) == 0x00000100)
+ {
+ Result = DEVICETYPE_PC;
+ }
+
+ return (Result);
+}
+
+
+UBYTE cUiBTGetDeviceIndex(UBYTE Known,UBYTE No,UBYTE *pIndex)
+{
+ UBYTE Result = 0;
+ UBYTE Tmp;
+
+ *pIndex = 0;
+ if (Known)
+ {
+ for (Tmp = 0;(Tmp < SIZE_OF_BT_DEVICE_TABLE) && (Result == 0);Tmp++)
+ {
+ if ((pMapComm->BtDeviceTable[Tmp].DeviceStatus & BT_DEVICE_KNOWN))
+ {
+ if (No == *pIndex)
+ {
+ *pIndex = Tmp;
+ Result = ~0;
+ }
+ else
+ {
+ (*pIndex)++;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (Tmp = 0;(Tmp < SIZE_OF_BT_DEVICE_TABLE) && (Result == 0);Tmp++)
+ {
+ if ((pMapComm->BtDeviceTable[Tmp].DeviceStatus & BT_DEVICE_UNKNOWN) || (pMapComm->BtDeviceTable[Tmp].DeviceStatus & BT_DEVICE_KNOWN))
+ {
+ if (No == *pIndex)
+ {
+ *pIndex = Tmp;
+ Result = ~0;
+ }
+ else
+ {
+ (*pIndex)++;
+ }
+ }
+ }
+ }
+
+ return (Result);
+}
+
+
+UWORD cUiBTCommand(UBYTE Cmd,UBYTE Flag,UBYTE *pParam1,UBYTE *pParam2)
+{
+ UWORD Result = UI_BT_FAILED;
+
+ switch(Cmd)
+ {
+ case UI_BT_GET_DEVICES :
+ {
+ cUiBTGetDeviceIndex(Flag,SIZE_OF_BT_DEVICE_TABLE,pParam1);
+ Result = UI_BT_SUCCES;
+ }
+ break;
+
+ case UI_BT_GET_DEVICE_NAME :
+ {
+ if ((*pParam1 < SIZE_OF_BT_DEVICE_TABLE) && (pParam2 != NULL))
+ {
+ pParam2[0] = 0;
+ if (cUiBTGetDeviceIndex(Flag,*pParam1,&VarsUi.BTTmpIndex))
+ {
+ sprintf((char*)pParam2,"%.*s",DISPLAYLINE_LENGTH,(char*)pMapComm->BtDeviceTable[VarsUi.BTTmpIndex].Name);
+ Result = UI_BT_SUCCES;
+ }
+ }
+ }
+ break;
+
+ case UI_BT_GET_DEVICE_TYPE :
+ {
+ if ((*pParam1 < SIZE_OF_BT_DEVICE_TABLE) && (pParam2 != NULL))
+ {
+ pParam2[0] = 0;
+ if (cUiBTGetDeviceIndex(Flag,*pParam1,&VarsUi.BTTmpIndex))
+ {
+ pParam2[0] = cUiBTGetDeviceType(pMapComm->BtDeviceTable[VarsUi.BTTmpIndex].ClassOfDevice);
+ Result = UI_BT_SUCCES;
+ }
+ }
+ }
+ break;
+
+ case UI_BT_GET_CONNECTION_NAME :
+ {
+ if (*pParam1 < SIZE_OF_BT_CONNECT_TABLE)
+ {
+ if (pMapComm->BtConnectTable[*pParam1].Name[0])
+ {
+ if (pParam2 != NULL)
+ {
+ sprintf((char*)pParam2,"%.*s",DISPLAYLINE_LENGTH,(char*)pMapComm->BtConnectTable[*pParam1].Name);
+ }
+ Result = UI_BT_SUCCES;
+ }
+ else
+ {
+ if (pParam2 != NULL)
+ {
+ pParam2[0] = 0;
+ }
+ }
+ }
+ }
+ break;
+
+ case UI_BT_GET_CONNECTION_TYPE :
+ {
+ if ((*pParam1 < SIZE_OF_BT_CONNECT_TABLE) && (pParam2 != NULL))
+ {
+ pParam2[0] = 0;
+ if (pMapComm->BtConnectTable[*pParam1].Name[0])
+ {
+ pParam2[0] = cUiBTGetDeviceType(pMapComm->BtConnectTable[*pParam1].ClassOfDevice);
+ Result = UI_BT_SUCCES;
+ }
+ }
+ }
+ break;
+
+ case UI_BT_GET_CONNECTION_VALID :
+ {
+ if (*pParam1 < SIZE_OF_BT_CONNECT_TABLE)
+ {
+ if (pMapComm->BtConnectTable[*pParam1].Name[0])
+ {
+ Result = UI_BT_SUCCES;
+ }
+ }
+ }
+ break;
+
+ }
+
+ return (Result);
+}
+
+
+
+#include "BtTest.inc"
+
+//******* cUiNVxxxxx *********************************************************
+
+void cUiNVWriteByte(void)
+{
+ sprintf((char*)VarsUi.NVFilename,"%s.%s",(char*)NONVOLATILE_NAME,(char*)TXT_SYS_EXT);
+ VarsUi.NVTmpHandle = pMapLoader->pFunc(FINDFIRST,VarsUi.NVFilename,VarsUi.SearchFilenameBuffer,&VarsUi.NVTmpLength);
+ if (!(VarsUi.NVTmpHandle & 0x8000))
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.NVTmpHandle,NULL,NULL);
+ pMapLoader->pFunc(DELETE,VarsUi.NVFilename,NULL,NULL);
+ }
+ VarsUi.NVTmpLength = 1;
+ VarsUi.NVTmpHandle = pMapLoader->pFunc(OPENWRITE,VarsUi.NVFilename,NULL,&VarsUi.NVTmpLength);
+ pMapLoader->pFunc(WRITE,(UBYTE*)&VarsUi.NVTmpHandle,(UBYTE*)&VarsUi.NVData,&VarsUi.NVTmpLength);
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.NVTmpHandle,NULL,NULL);
+}
+
+void cUiNVWritePowerOnTimeCount(UBYTE Count)
+{
+ VarsUi.NVData &= ~0x07;
+ VarsUi.NVData |= (Count & 0x07);
+ cUiNVWriteByte();
+}
+
+UBYTE cUiNVReadPowerOnTimeCount(void)
+{
+ return (VarsUi.NVData & 0x07);
+}
+
+void cUiNVWriteVolumeCount(UBYTE Count)
+{
+ VarsUi.NVData &= ~0x70;
+ VarsUi.NVData |= ((Count << 4) & 0x70);
+ cUiNVWriteByte();
+}
+
+UBYTE cUiNVReadVolumeCount(void)
+{
+ return ((VarsUi.NVData >> 4) & 0x07);
+}
+
+void cUiNVReadByte(void)
+{
+ VarsUi.NVData = 0xFF;
+ sprintf((char*)VarsUi.NVFilename,"%s.%s",(char*)NONVOLATILE_NAME,(char*)TXT_SYS_EXT);
+ VarsUi.NVTmpHandle = pMapLoader->pFunc(OPENREAD,VarsUi.NVFilename,NULL,&VarsUi.NVTmpLength);
+ if (!(VarsUi.NVTmpHandle & 0x8000))
+ {
+ VarsUi.NVTmpLength = 1;
+ pMapLoader->pFunc(READ,(UBYTE*)&VarsUi.NVTmpHandle,&VarsUi.NVData,&VarsUi.NVTmpLength);
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.NVTmpHandle,NULL,NULL);
+ }
+
+ if ((cUiNVReadPowerOnTimeCount() > (POWER_OFF_TIME_STEPS - 1)) || (cUiNVReadVolumeCount() > MAX_VOLUME))
+ {
+ VarsUi.NVData = 0xFF;
+ cUiNVWritePowerOnTimeCount(POWER_OFF_TIME_DEFAULT);
+ cUiNVWriteVolumeCount(MAX_VOLUME);
+ }
+}
+
+
+
+//******* cUiFeedback ********************************************************
+
+UBYTE cUiFeedback(BMPMAP *Bitmap,UBYTE TextNo1,UBYTE TextNo2,UWORD Time) // Show bimap and text
+{
+// if ((VarsUi.FBState == 0) || ((pMapDisplay->Flags & DISPLAY_POPUP) == 0))
+ {
+ switch (VarsUi.FBState)
+ {
+ case 0 : // Set busy
+ {
+ VarsUi.FBState++;
+ }
+ break;
+
+ case 1 : // Clear line 2,3,4
+ {
+ if (DISPLAY_IDLE)
+ {
+ pMapDisplay->EraseMask |= (TEXTLINE_BIT(TEXTLINE_2) | TEXTLINE_BIT(TEXTLINE_3) | TEXTLINE_BIT(TEXTLINE_4));
+ VarsUi.FBState++;
+ }
+ }
+ break;
+
+ case 2 : // Show bitmap if pressent
+ {
+ if (DISPLAY_IDLE)
+ {
+ if (Bitmap != NULL)
+ {
+ pMapDisplay->pBitmaps[BITMAP_1] = Bitmap;
+ pMapDisplay->UpdateMask |= BITMAP_BIT(BITMAP_1);
+ }
+ VarsUi.FBState++;
+ }
+ }
+ break;
+
+ case 3 : // Get text string
+ {
+ if (DISPLAY_IDLE)
+ {
+ pMapDisplay->UpdateMask |= SPECIAL_BIT(TOPLINE);
+ VarsUi.FBText = cUiGetString(TextNo1);
+ VarsUi.FBPointer = 0;
+ if (TextNo2)
+ {
+ VarsUi.FBState = 5;
+ }
+ else
+ {
+ VarsUi.FBState++;
+ }
+ }
+ }
+ break;
+
+ case 4 : // Show text string
+ {
+ if ((VarsUi.FBText[VarsUi.FBPointer]) && (VarsUi.FBPointer < NO_OF_FEEDBACK_CHARS))
+ {
+ pMapDisplay->pFunc(DISPLAY_CHAR,TRUE,24 + VarsUi.FBPointer * 6,16,VarsUi.FBText[VarsUi.FBPointer],0);
+ VarsUi.FBPointer++;
+ }
+ else
+ {
+ VarsUi.FBTimer = 0;
+ VarsUi.FBState = 7;
+ }
+ }
+ break;
+
+ case 5 : // Show text string
+ {
+ if ((VarsUi.FBText[VarsUi.FBPointer]) && (VarsUi.FBPointer < NO_OF_FEEDBACK_CHARS))
+ {
+ pMapDisplay->pFunc(DISPLAY_CHAR,TRUE,24 + VarsUi.FBPointer * 6,12,VarsUi.FBText[VarsUi.FBPointer],0);
+ VarsUi.FBPointer++;
+ }
+ else
+ {
+ VarsUi.FBText = cUiGetString(TextNo2);
+ VarsUi.FBPointer = 0;
+ VarsUi.FBState++;
+ }
+ }
+ break;
+
+ case 6 : // Show text string
+ {
+ if ((VarsUi.FBText[VarsUi.FBPointer]) && (VarsUi.FBPointer < NO_OF_FEEDBACK_CHARS))
+ {
+ pMapDisplay->pFunc(DISPLAY_CHAR,TRUE,24 + VarsUi.FBPointer * 6,20,VarsUi.FBText[VarsUi.FBPointer],0);
+ VarsUi.FBPointer++;
+ }
+ else
+ {
+ VarsUi.FBTimer = 0;
+ VarsUi.FBState++;
+ }
+ }
+ break;
+
+ case 7 : // Wait if time provided
+ {
+ if (++VarsUi.FBTimer >= (Time + 100))
+ {
+ VarsUi.FBState++;
+ }
+ }
+ break;
+
+ default : // Exit
+ {
+ VarsUi.FBState = 0;
+ }
+ break;
+
+ }
+ }
+
+ return (VarsUi.FBState);
+}
+
+
+
+//******* cUiFileList ********************************************************
+
+UBYTE cUiFindNoOfFiles(UBYTE FileType,UBYTE *NoOfFiles)
+{
+ switch (VarsUi.FNOFState)
+ {
+ case 0 :
+ {
+ *NoOfFiles = 0;
+
+ if (FileType >= FILETYPES)
+ {
+ FileType = FILETYPE_ALL;
+ }
+ sprintf((char*)VarsUi.FNOFSearchBuffer,"*.%s",TXT_FILE_EXT[FileType]);
+
+ VarsUi.FNOFHandle = pMapLoader->pFunc(FINDFIRST,VarsUi.FNOFSearchBuffer,VarsUi.FNOFNameBuffer,&VarsUi.FNOFLength);
+ if (!(VarsUi.FNOFHandle & 0x8000))
+ {
+ *NoOfFiles = 1;
+ VarsUi.FNOFState++;
+ }
+ }
+ break;
+
+ case 1 :
+ {
+ VarsUi.FNOFHandle = pMapLoader->pFunc(FINDNEXT,(UBYTE*)&VarsUi.FNOFHandle,VarsUi.FNOFNameBuffer,&VarsUi.FNOFLength);
+ if (!(VarsUi.FNOFHandle & 0x8000))
+ {
+ *NoOfFiles += 1;
+ }
+ else
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.FNOFHandle,NULL,NULL);
+ VarsUi.FNOFState = 0;
+ }
+ }
+ break;
+
+ }
+
+ return (VarsUi.FNOFState);
+}
+
+
+UBYTE cUiFindNameForFileNo(UBYTE FileType,UBYTE FileNo,UBYTE *Name)
+{
+ switch (VarsUi.FNOFState)
+ {
+ case 0 :
+ {
+ Name[0] = 0;
+
+ if (FileNo)
+ {
+ if (FileType >= FILETYPES)
+ {
+ FileType = FILETYPE_ALL;
+ }
+ sprintf((char*)VarsUi.FNOFSearchBuffer,"*.%s",TXT_FILE_EXT[FileType]);
+
+ VarsUi.FNOFHandle = pMapLoader->pFunc(FINDFIRST,VarsUi.FNOFSearchBuffer,Name,&VarsUi.FNOFLength);
+ if (!(VarsUi.FNOFHandle & 0x8000))
+ {
+ if (FileNo != 1)
+ {
+ VarsUi.FNOFFileNo = 1;
+ VarsUi.FNOFState++;
+ }
+ else
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.FNOFHandle,NULL,NULL);
+ }
+ }
+ }
+ }
+ break;
+
+ case 1 :
+ {
+ VarsUi.FNOFHandle = pMapLoader->pFunc(FINDNEXT,(UBYTE*)&VarsUi.FNOFHandle,Name,&VarsUi.FNOFLength);
+ if (!(VarsUi.FNOFHandle & 0x8000))
+ {
+ VarsUi.FNOFFileNo++;
+ if (FileNo == VarsUi.FNOFFileNo)
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.FNOFHandle,NULL,NULL);
+ VarsUi.FNOFState = 0;
+ }
+ }
+ else
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.FNOFHandle,NULL,NULL);
+ VarsUi.FNOFState = 0;
+ }
+ }
+ break;
+
+ }
+
+ return (VarsUi.FNOFState);
+}
+
+
+UBYTE cUiFileList(UBYTE Action) // Show files and select
+{
+ switch (Action)
+ {
+ case MENU_INIT :
+ {
+ if (!VarsUi.State)
+ {
+ VarsUi.FileCenter = 1;
+ VarsUi.NextState = IOMapUi.State;
+ }
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_LEFT :
+ {
+ if (!VarsUi.State)
+ {
+ cUiListLeft(VarsUi.NoOfFiles,&VarsUi.FileCenter);
+ VarsUi.NextState = TEST_BUTTONS;
+ }
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_RIGHT :
+ {
+ if (!VarsUi.State)
+ {
+ cUiListRight(VarsUi.NoOfFiles,&VarsUi.FileCenter);
+ VarsUi.NextState = TEST_BUTTONS;
+ }
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_SELECT :
+ {
+ }
+ break;
+
+ default :
+ {
+ if (Action < FILETYPES)
+ {
+ if (!VarsUi.State)
+ {
+ VarsUi.FileType = Action;
+ VarsUi.FileCenter = 1;
+ VarsUi.NextState = IOMapUi.State;
+ }
+ Action = MENU_DRAW;
+ }
+ else
+ {
+ IOMapUi.State = EXIT_PRESSED;
+ VarsUi.State = 0;
+ }
+ }
+ break;
+
+ }
+
+ if (Action == MENU_DRAW)
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ VarsUi.FNOFState = 0;
+ VarsUi.State++;
+ }
+ break;
+
+ case 1 :
+ {
+ if (cUiFindNoOfFiles(VarsUi.FileType,&VarsUi.NoOfFiles) == 0)
+ {
+ if (VarsUi.NoOfFiles)
+ {
+ cUiListCalc(VarsUi.NoOfFiles,&VarsUi.FileCenter,&VarsUi.FileLeft,&VarsUi.FileRight);
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 0;
+ IOMapUi.State = EXIT_PRESSED;
+ }
+ }
+ }
+ break;
+
+ case 2 :
+ {
+ if (cUiFindNameForFileNo(VarsUi.FileType,VarsUi.FileCenter,VarsUi.SelectedFilename) == 0)
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ default :
+ {
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = NULL;
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = NULL;
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = NULL;
+
+ if (VarsUi.FileLeft)
+ {
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = (UBYTE*)&Icons->Data[(VarsUi.FileType + ALLFILES) * Icons->ItemPixelsX * (Icons->ItemPixelsY / 8)];
+ pMapDisplay->UpdateMask |= MENUICON_BIT(MENUICON_LEFT);
+ }
+ if (VarsUi.FileCenter)
+ {
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = (UBYTE*)&Icons->Data[(VarsUi.FileType + ALLFILES) * Icons->ItemPixelsX * (Icons->ItemPixelsY / 8)];
+ pMapDisplay->UpdateMask |= MENUICON_BIT(MENUICON_CENTER);
+ }
+ if (VarsUi.FileRight)
+ {
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = (UBYTE*)&Icons->Data[(VarsUi.FileType + ALLFILES) * Icons->ItemPixelsX * (Icons->ItemPixelsY / 8)];
+ pMapDisplay->UpdateMask |= MENUICON_BIT(MENUICON_RIGHT);
+ }
+
+ pMapDisplay->EraseMask |= TEXTLINE_BIT(TEXTLINE_5);
+
+ // Search forward for termination
+ VarsUi.Tmp = 0;
+ while ((VarsUi.SelectedFilename[VarsUi.Tmp]) && (VarsUi.Tmp < FILENAME_LENGTH))
+ {
+ VarsUi.Tmp++;
+ }
+
+ // Search backward for "."
+ while ((VarsUi.Tmp) && (VarsUi.SelectedFilename[VarsUi.Tmp] != '.'))
+ {
+ VarsUi.Tmp--;
+ }
+
+ if (VarsUi.Tmp > DISPLAYLINE_LENGTH)
+ {
+ VarsUi.Tmp = DISPLAYLINE_LENGTH;
+ }
+
+ VarsUi.DisplayBuffer[VarsUi.Tmp] = 0;
+
+ // Copy only name not ext
+ while (VarsUi.Tmp)
+ {
+ VarsUi.Tmp--;
+ VarsUi.DisplayBuffer[VarsUi.Tmp] = VarsUi.SelectedFilename[VarsUi.Tmp];
+ }
+
+ pMapDisplay->pMenuText = VarsUi.DisplayBuffer;
+ pMapDisplay->EraseMask |= MENUICON_BITS;
+ pMapDisplay->UpdateMask |= (SPECIAL_BIT(FRAME_SELECT) | SPECIAL_BIT(MENUTEXT));
+
+ IOMapUi.State = VarsUi.NextState;
+ VarsUi.State = 0;
+ }
+ break;
+
+ }
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* cUiVolume **********************************************************
+
+UBYTE cUiVolume(UBYTE Action) // MENU_INIT,MENU_LEFT,MENU_RIGHT,MENU_EXIT
+{
+ switch (Action)
+ {
+ case MENU_INIT : // Init time counter and cursor bitmap
+ {
+ VarsUi.Counter = cUiNVReadVolumeCount() + 1;
+
+ VarsUi.pTmp = (UBYTE*)Cursor;
+ for (VarsUi.Tmp = 0;(VarsUi.Tmp < SIZE_OF_CURSOR) && (VarsUi.Tmp < (UBYTE)sizeof(Cursor));VarsUi.Tmp++)
+ {
+ VarsUi.CursorTmp[VarsUi.Tmp] = *VarsUi.pTmp;
+ VarsUi.pTmp++;
+ }
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_LEFT : // Dec
+ {
+ cUiListLeft(MAX_VOLUME + 1,&VarsUi.Counter);
+ IOMapUi.Volume = VarsUi.Counter - 1;
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_RIGHT : // Inc
+ {
+ cUiListRight(MAX_VOLUME + 1,&VarsUi.Counter);
+ IOMapUi.Volume = VarsUi.Counter - 1;
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_ENTER : // Enter
+ {
+ cUiNVWriteVolumeCount(VarsUi.Counter - 1);
+ IOMapUi.Volume = cUiNVReadVolumeCount();
+ pMapSound->Volume = IOMapUi.Volume;
+ Action = MENU_EXIT;
+ }
+ break;
+
+ case MENU_EXIT : // Leave
+ {
+ IOMapUi.Volume = cUiNVReadVolumeCount();
+ }
+ break;
+
+ }
+ if (Action == MENU_DRAW)
+ {
+ sprintf((char*)VarsUi.DisplayBuffer,"%u",(UWORD)VarsUi.Counter - 1);
+ pMapDisplay->pTextLines[TEXTLINE_3] = VarsUi.DisplayBuffer;
+
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)VarsUi.CursorTmp;
+ VarsUi.CursorTmp[4] = 46;
+ VarsUi.CursorTmp[5] = 24;
+ pMapDisplay->EraseMask |= (TEXTLINE_BIT(TEXTLINE_3) | TEXTLINE_BIT(TEXTLINE_4));
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(TEXTLINE_3);
+ pMapDisplay->UpdateMask |= (TEXTLINE_BIT(TEXTLINE_3) | BITMAP_BIT(BITMAP_1));
+ }
+ if (Action == MENU_EXIT)
+ {
+ IOMapUi.State = EXIT_PRESSED;
+ }
+
+ return (0);
+}
+
+
+
+//******* cUiGetUserString ***************************************************
+
+#define STRINGTYPES 2
+
+#define TOPTEXT_LINE TEXTLINE_3
+#define STRING_LINE TEXTLINE_5
+
+typedef struct
+{
+ const UBYTE Text;
+ const UBYTE *Figures;
+ const UBYTE NoOfFigures;
+ const UBYTE MaxStringLength;
+ const UBYTE WindowSize;
+ const SBYTE DefaultPointer;
+}
+STRSETS;
+
+const UBYTE PincodeFigures[] = { "0987654321" "\x7F" "abcdefghijklmnopqrstuvwxyz " };
+const UBYTE FilenameFigures[] = { "0987654321" "\x7F" "abcdefghijklmnopqrstuvwxyz " };
+
+const STRSETS StrSets[STRINGTYPES] =
+{
+ { TXT_GETUSERSTRING_PIN, PincodeFigures, 37, SIZE_OF_BT_PINCODE - 1, 15, 10 },
+ { TXT_GETUSERSTRING_FILENAME, FilenameFigures, 37, FILENAME_LENGTH - 4 , 15, 10 }
+};
+
+
+UBYTE cUiGetUserString(UBYTE Type) // 0=Pincode, 1=filename
+{
+ UBYTE Tmp1;
+ SBYTE Tmp2;
+
+ if (Type < STRINGTYPES)
+ {
+ switch (VarsUi.GUSState)
+ {
+ case 0 : // Init screen
+ {
+ // Disable update and prepare screen
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_LARGE);
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)Ok;
+
+ // Set figure pointer to default
+ VarsUi.FigurePointer = (SBYTE)StrSets[Type].DefaultPointer;
+
+ // Calculate cursor from default string
+ VarsUi.GUSCursor = 0;
+ while ((VarsUi.GUSCursor < DISPLAYLINE_LENGTH) && VarsUi.UserString[VarsUi.GUSCursor])
+ {
+ VarsUi.GUSCursor++;
+ }
+ VarsUi.GUSNoname = TRUE;
+
+ VarsUi.GUSState++;
+ }
+ break;
+
+ case 1 : // Update user string
+ {
+ if (!(pMapDisplay->EraseMask & SCREEN_BIT(SCREEN_LARGE)))
+ {
+ // Display top text
+ pMapDisplay->pTextLines[TOPTEXT_LINE] = cUiGetString(StrSets[Type].Text);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TOPTEXT_LINE);
+
+ Tmp1 = 0;
+ while (VarsUi.UserString[Tmp1] && (Tmp1 < StrSets[Type].MaxStringLength))
+ {
+ VarsUi.DisplayText[Tmp1] = VarsUi.UserString[Tmp1];
+ Tmp1++;
+ }
+ if (Tmp1 < StrSets[Type].MaxStringLength)
+ {
+ VarsUi.DisplayText[Tmp1] = '_';
+ Tmp1++;
+ }
+ while (Tmp1 < StrSets[Type].MaxStringLength)
+ {
+ VarsUi.DisplayText[Tmp1] = ' ';
+ Tmp1++;
+ }
+ VarsUi.DisplayText[Tmp1] = 0;
+
+ pMapDisplay->pTextLines[STRING_LINE] = VarsUi.DisplayText;
+ pMapDisplay->UpdateMask |= (TEXTLINE_BIT(STRING_LINE) | SPECIAL_BIT(TOPLINE));
+ pMapDisplay->EraseMask |= BITMAP_BIT(BITMAP_1);
+ VarsUi.GUSState++;
+ }
+ }
+ break;
+
+ case 2 : // Update figure string
+ {
+ if (!(pMapDisplay->EraseMask & BITMAP_BIT(BITMAP_1)))
+ {
+ Tmp2 = VarsUi.FigurePointer;
+
+ for (Tmp1 = 0;Tmp1 < 3;Tmp1++)
+ {
+ if (Tmp2)
+ {
+ Tmp2--;
+ }
+ else
+ {
+ Tmp2 = StrSets[Type].NoOfFigures - 1;
+ }
+ }
+ for (Tmp1 = 0;Tmp1 < 7;Tmp1++)
+ {
+ if ((Tmp1 == 3) && (StrSets[Type].Figures[Tmp2] == 0x7F))
+ {
+ pMapDisplay->UpdateMask |= BITMAP_BIT(BITMAP_1);
+ }
+ else
+ {
+ pMapDisplay->pFunc(DISPLAY_CHAR,TRUE,5 + Tmp1 * 14,52,StrSets[Type].Figures[Tmp2],0);
+ }
+ if (Tmp2 < (StrSets[Type].NoOfFigures - 1))
+ {
+ Tmp2++;
+ }
+ else
+ {
+ Tmp2 = 0;
+ }
+ }
+ pMapDisplay->pFunc(DISPLAY_HORISONTAL_LINE,TRUE,42,47,57,0);
+ pMapDisplay->pFunc(DISPLAY_VERTICAL_LINE,TRUE,42,47,0,63);
+ pMapDisplay->pFunc(DISPLAY_VERTICAL_LINE,TRUE,57,47,0,63);
+
+ VarsUi.GUSState++;
+ }
+ }
+ break;
+
+ case 3 : // Get user input
+ {
+ if ((pMapButton->State[BTN4] & LONG_PRESSED_EV))
+ {
+ if (VarsUi.GUSCursor)
+ {
+ if ((VarsUi.UserString[VarsUi.GUSCursor - 1] >= 'a') && (VarsUi.UserString[VarsUi.GUSCursor - 1] <= 'z'))
+ {
+ VarsUi.UserString[VarsUi.GUSCursor - 1] -= ' ';
+ VarsUi.GUSState -= 2;
+ }
+ }
+ }
+
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ if (VarsUi.FigurePointer)
+ {
+ VarsUi.FigurePointer--;
+ }
+ else
+ {
+ VarsUi.FigurePointer = StrSets[Type].NoOfFigures - 1;
+ }
+ pMapDisplay->EraseMask |= BITMAP_BIT(BITMAP_1);
+ VarsUi.GUSState -= 2;
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ switch (StrSets[Type].Figures[VarsUi.FigurePointer])
+ {
+ case 0x7F :
+ {
+ VarsUi.GUSState = 100;
+ }
+ break;
+
+ default :
+ {
+ VarsUi.GUSNoname = FALSE;
+ if (VarsUi.GUSCursor < StrSets[Type].MaxStringLength)
+ {
+ VarsUi.UserString[VarsUi.GUSCursor] = StrSets[Type].Figures[VarsUi.FigurePointer];
+ VarsUi.GUSCursor++;
+ VarsUi.UserString[VarsUi.GUSCursor] = 0;
+ VarsUi.GUSState -= 2;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ if (VarsUi.FigurePointer < (StrSets[Type].NoOfFigures - 1))
+ {
+ VarsUi.FigurePointer++;
+ }
+ else
+ {
+ VarsUi.FigurePointer = 0;
+ }
+ pMapDisplay->EraseMask |= BITMAP_BIT(BITMAP_1);
+ VarsUi.GUSState -= 2;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ if (VarsUi.GUSCursor)
+ {
+ if (VarsUi.GUSNoname == TRUE)
+ {
+ VarsUi.GUSNoname = FALSE;
+ while (VarsUi.GUSCursor)
+ {
+ VarsUi.UserString[VarsUi.GUSCursor] = 0;
+ VarsUi.GUSCursor--;
+ }
+ }
+ else
+ {
+ VarsUi.GUSCursor--;
+ }
+ VarsUi.UserString[VarsUi.GUSCursor] = 0;
+ VarsUi.GUSState -= 2;
+ }
+ else
+ {
+ VarsUi.UserString[0] = 0;
+ VarsUi.GUSState = 100;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ default : // Clean up screen
+ {
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ pMapDisplay->UpdateMask = 0;
+ IOMapUi.Flags |= UI_REDRAW_STATUS;
+ VarsUi.GUSState = 0;
+ }
+ break;
+ }
+ }
+
+ return (VarsUi.GUSState);
+}
+
+
+
+//******* cUiDataLogging *****************************************************
+
+void cUiDrawPortNo(UBYTE *Bitmap,UBYTE MenuIconNo,UBYTE PortNo)
+{
+ UBYTE Tmp;
+
+ Bitmap[0] = (UBYTE)(FILEFORMAT_BITMAP >> 8);
+ Bitmap[1] = (UBYTE)(FILEFORMAT_BITMAP);
+ Bitmap[2] = (UBYTE)(SIZE_OF_PORTBITMAP >> 8);
+ Bitmap[3] = (UBYTE)(SIZE_OF_PORTBITMAP);
+ Bitmap[4] = DISPLAY_MENUICONS_X_OFFS + DISPLAY_MENUICONS_X_DIFF * MenuIconNo + 2;
+ Bitmap[5] = DISPLAY_MENUICONS_Y;
+ Bitmap[6] = Port[0].ItemPixelsX;
+ Bitmap[7] = Port[0].ItemPixelsY;
+
+ Tmp = 0;
+ while (Tmp < Bitmap[6])
+ {
+ Bitmap[Tmp + FILEHEADER_LENGTH] = Port[0].Data[Tmp + PortNo * Bitmap[6]];
+ Tmp++;
+ }
+
+}
+
+//******* cUiRunning **********************************************************
+
+void cUiRunning(UBYTE Action)
+{
+ switch (Action)
+ {
+ case MENU_INIT :
+ {
+ VarsUi.RunIconSave = pMapDisplay->pMenuIcons[MENUICON_CENTER];
+ VarsUi.RunBitmapPointer = 0;
+ VarsUi.RunTimer = 0;
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_LARGE);
+ pMapDisplay->UpdateMask |= SPECIAL_BIT(TOPLINE);
+ }
+ break;
+
+ case MENU_RUN :
+ {
+ if ((IOMapUi.Flags & UI_ENABLE_STATUS_UPDATE))
+ {
+ if (++VarsUi.RunTimer >= RUN_BITMAP_CHANGE_TIME)
+ {
+ VarsUi.RunTimer = 0;
+ if (++VarsUi.RunBitmapPointer >= Running->ItemsY )
+ {
+ VarsUi.RunBitmapPointer = 0;
+ }
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = (UBYTE*)&Running->Data[VarsUi.RunBitmapPointer * Running->ItemPixelsX * (Running->ItemPixelsY / 8)];
+ pMapDisplay->EraseMask |= MENUICON_BIT(MENUICON_CENTER);
+ pMapDisplay->UpdateMask |= MENUICON_BIT(MENUICON_CENTER);
+ }
+ }
+ }
+ break;
+
+ case MENU_UPDATE :
+ {
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = (UBYTE*)&Running->Data[VarsUi.RunBitmapPointer * Running->ItemPixelsX * (Running->ItemPixelsY / 8)];
+ pMapDisplay->UpdateMask |= MENUICON_BIT(MENUICON_CENTER);
+ }
+ break;
+
+ case MENU_EXIT :
+ {
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = VarsUi.RunIconSave;
+ pMapDisplay->UpdateMask = MENUICON_BITS | SPECIAL_BIT(MENUTEXT);
+ }
+ break;
+
+ }
+}
+
+//******* cUiOnBrickProgramming **********************************************
+
+UBYTE cUiOnBrickProgramming(UBYTE Action) // On brick programming
+{
+ switch (Action)
+ {
+ case MENU_INIT : // Show motor / sensor text
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3] = cUiGetString(TXT_ONBRICKPROGRAMMING_PLEASE_USE_PORT);
+ pMapDisplay->pTextLines[TEXTLINE_4] = cUiGetString(TXT_ONBRICKPROGRAMMING_1_TOUCH_SENSOR);
+ pMapDisplay->pTextLines[TEXTLINE_5] = cUiGetString(TXT_ONBRICKPROGRAMMING_2_SOUND_SENSOR);
+ pMapDisplay->pTextLines[TEXTLINE_6] = cUiGetString(TXT_ONBRICKPROGRAMMING_3_LIGHT_SENSOR);
+ pMapDisplay->pTextLines[TEXTLINE_7] = cUiGetString(TXT_ONBRICKPROGRAMMING_4_ULTRA_SONIC);
+ pMapDisplay->pTextLines[TEXTLINE_8] = cUiGetString(TXT_ONBRICKPROGRAMMING_BC_LR_MOTORS);
+ pMapDisplay->EraseMask |= (TEXTLINE_BIT(TEXTLINE_3) | TEXTLINE_BIT(TEXTLINE_4) | TEXTLINE_BIT(TEXTLINE_5) | TEXTLINE_BIT(TEXTLINE_6) | TEXTLINE_BIT(TEXTLINE_7) | TEXTLINE_BIT(TEXTLINE_8));
+ pMapDisplay->UpdateMask &= ~SPECIAL_BIT(FRAME_SELECT);
+ pMapDisplay->UpdateMask |= (TEXTLINE_BIT(TEXTLINE_3) | TEXTLINE_BIT(TEXTLINE_4) | TEXTLINE_BIT(TEXTLINE_5) | TEXTLINE_BIT(TEXTLINE_6) | TEXTLINE_BIT(TEXTLINE_7) | TEXTLINE_BIT(TEXTLINE_8) | SPECIAL_BIT(TOPLINE));
+ pMapDisplay->TextLinesCenterFlags |= (TEXTLINE_BIT(TEXTLINE_3) | TEXTLINE_BIT(TEXTLINE_4) | TEXTLINE_BIT(TEXTLINE_5) | TEXTLINE_BIT(TEXTLINE_6) | TEXTLINE_BIT(TEXTLINE_7) | TEXTLINE_BIT(TEXTLINE_8));
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_TEXT : // Show empty program steps
+ {
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_LARGE);
+
+ VarsUi.pTmp = (UBYTE*)Cursor;
+ for (VarsUi.Tmp = 0;(VarsUi.Tmp < SIZE_OF_CURSOR) && (VarsUi.Tmp < (UBYTE)sizeof(Cursor));VarsUi.Tmp++)
+ {
+ VarsUi.CursorTmp[VarsUi.Tmp] = *VarsUi.pTmp;
+ VarsUi.pTmp++;
+ }
+
+ for (VarsUi.ProgramStepPointer = 0;VarsUi.ProgramStepPointer < ON_BRICK_PROGRAMSTEPS;VarsUi.ProgramStepPointer++)
+ {
+ VarsUi.ProgramSteps[VarsUi.ProgramStepPointer] = MENU_ACTION_EMPTY;
+ }
+ VarsUi.ProgramStepPointer = 0;
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_EXIT : // Delete one steps and exit at the end
+ {
+ if (VarsUi.ProgramStepPointer)
+ {
+ if (VarsUi.ProgramStepPointer < ON_BRICK_PROGRAMSTEPS)
+ {
+ VarsUi.ProgramSteps[VarsUi.ProgramStepPointer] = MENU_ACTION_EMPTY;
+ }
+ VarsUi.ProgramStepPointer--;
+ }
+ else
+ {
+ IOMapUi.State = NEXT_MENU;
+ }
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_RUN : // Run program steps until end or user press exit button
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ VarsUi.pTmp = (UBYTE*)Cursor;
+ for (VarsUi.Tmp = 0;(VarsUi.Tmp < SIZE_OF_CURSOR) && (VarsUi.Tmp < (UBYTE)sizeof(Cursor));VarsUi.Tmp++)
+ {
+ VarsUi.CursorTmp[VarsUi.Tmp] = *VarsUi.pTmp;
+ VarsUi.pTmp++;
+ }
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)VarsUi.CursorTmp;
+ cUiRunning(MENU_INIT);
+ Action = MENU_DRAW;
+ VarsUi.State++;
+ }
+ break;
+
+ case 1 : // If sound finished -> Init text and program pointer
+ {
+ if (SOUND_IDLE == pMapSound->State)
+ {
+ VarsUi.ProgramStepPointer = ON_BRICK_PROGRAMSTEPS;
+ VarsUi.MenuIconTextSave = pMapDisplay->pMenuText;
+ pMapDisplay->EraseMask |= SPECIAL_BIT(MENUTEXT);
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 2 : // load file to run
+ {
+ if (PROG_IDLE == pMapCmd->ProgStatus)
+ {
+ sprintf((char*)pMapCmd->FileName,"%s.%s",(char*)VM_PROGRAM_READER,(char*)TXT_SYS_EXT);
+ pMapCmd->ActivateFlag = TRUE;
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 3 : // Wait for end of file
+ {
+ if (PROG_RUNNING != pMapCmd->ProgStatus)
+ {
+ pMapCmd->ProgStatus = PROG_RESET;
+ VarsUi.State = 99;
+ VarsUi.ProgramStepPointer = ON_BRICK_PROGRAMSTEPS;
+ }
+ else
+ {
+ if (VarsUi.OBPTimer >= MIN_DISPLAY_UPDATE_TIME)
+ {
+ if (IOMapUi.OBPPointer != VarsUi.ProgramStepPointer)
+ {
+ VarsUi.ProgramStepPointer = IOMapUi.OBPPointer;
+ Action = MENU_DRAW;
+ }
+ }
+ }
+ }
+ break;
+
+ default : // Program stopped
+ {
+ pMapDisplay->pMenuText = VarsUi.MenuIconTextSave;
+ pMapDisplay->UpdateMask |= SPECIAL_BIT(MENUTEXT);
+ Action = MENU_DRAW;
+ VarsUi.State = 0;
+ }
+ break;
+
+ }
+ if (VarsUi.State)
+ {
+ cUiRunning(MENU_RUN);
+ }
+ else
+ {
+ cUiRunning(MENU_EXIT);
+ }
+ }
+ break;
+
+ case MENU_LEFT : // NA
+ {
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_RIGHT : // NA
+ {
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_UPDATE : // NA
+ {
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_SAVE : // Save NXT program
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ // Suggest default filename to user
+ strcpy((char*)VarsUi.UserString,(char*)DEFAULT_PROGRAM_NAME);
+ VarsUi.State++;
+ }
+ break;
+
+ case 1 :
+ {
+ if (!cUiGetUserString(1))
+ {
+ if (VarsUi.UserString[0])
+ {
+ sprintf((char*)VarsUi.SelectedFilename,"%s.%s",VarsUi.UserString,TXT_FILE_EXT[FILETYPE_NXT]);
+
+ // If tmp file exist -> ask for overwrite
+ VarsUi.TmpHandle = pMapLoader->pFunc(FINDFIRST,(UBYTE*)VarsUi.SelectedFilename,VarsUi.FilenameBuffer,&VarsUi.TmpLength);
+ if (!(VarsUi.TmpHandle & 0x8000))
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State += 2;
+ }
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ }
+ break;
+
+ case 2 :
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_OBP_FILE_EXIST_FAIL,TXT_FB_OBP_OVERWRITE_FAIL,0))
+ {
+ VarsUi.State = 0;
+ }
+ }
+ break;
+
+ case 3 :
+ {
+ // Rename TEMP_PROGRAM_FILENAME to VarsUi.SelectedFilename(user filename)
+ sprintf((char*)VarsUi.FilenameBuffer,"%s.%s",(char*)TEMP_PROGRAM_FILENAME,(char*)TXT_TMP_EXT);
+ VarsUi.TmpHandle = pMapLoader->pFunc(RENAMEFILE,VarsUi.FilenameBuffer,VarsUi.SelectedFilename,&VarsUi.TmpLength);
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ VarsUi.State++;
+ }
+ break;
+
+ case 4 : // Display saved text
+ {
+ if (!cUiFeedback((BMPMAP*)Info,TXT_FB_OBP_FILE_SAVED_INFO,0,DISPLAY_SHOW_TIME))
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ default :
+ {
+ cUiMenuPrevFile();
+ IOMapUi.State = NEXT_MENU;
+ VarsUi.State = 0;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case MENU_OVERWRITE : // Over write existing file
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ // Delete VarsUi.SelectedFilename(user filename)
+ VarsUi.TmpHandle = pMapLoader->pFunc(FINDFIRST,(UBYTE*)VarsUi.SelectedFilename,VarsUi.FilenameBuffer,&VarsUi.TmpLength);
+ if (!(VarsUi.TmpHandle & 0x8000))
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ pMapLoader->pFunc(DELETE,VarsUi.SelectedFilename,NULL,NULL);
+ }
+
+ // Rename TEMP_PROGRAM_FILENAME to VarsUi.SelectedFilename(user filename)
+ sprintf((char*)VarsUi.FilenameBuffer,"%s.%s",(char*)TEMP_PROGRAM_FILENAME,(char*)TXT_TMP_EXT);
+ VarsUi.TmpHandle = pMapLoader->pFunc(RENAMEFILE,VarsUi.FilenameBuffer,VarsUi.SelectedFilename,&VarsUi.TmpLength);
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ VarsUi.State++;
+ }
+ break;
+
+ default : // Display saved text
+ {
+ if (!cUiFeedback((BMPMAP*)Info,TXT_FB_OBP_FILE_SAVED_INFO,0,DISPLAY_SHOW_TIME))
+ {
+ VarsUi.State = 0;
+ }
+ }
+ break;
+
+ }
+
+ }
+ break;
+
+ default : // Insert selected action/waitfor in program and save if finished
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ VarsUi.ProgramSteps[VarsUi.ProgramStepPointer] = Action;
+ if (VarsUi.ProgramStepPointer < ON_BRICK_PROGRAMSTEPS)
+ {
+ VarsUi.ProgramStepPointer++;
+ }
+ if (VarsUi.ProgramStepPointer == ON_BRICK_PROGRAMSTEPS)
+ {
+ // If tmp file exist -> delete it
+ sprintf((char*)VarsUi.FilenameBuffer,"%s.%s",(char*)TEMP_PROGRAM_FILENAME,(char*)TXT_TMP_EXT);
+ VarsUi.TmpHandle = pMapLoader->pFunc(FINDFIRST,VarsUi.FilenameBuffer,VarsUi.SearchFilenameBuffer,&VarsUi.TmpLength);
+ if (!(VarsUi.TmpHandle & 0x8000))
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ pMapLoader->pFunc(DELETE,VarsUi.FilenameBuffer,NULL,NULL);
+ }
+
+ // Save program as tmp file
+ VarsUi.TmpLength = FILEHEADER_LENGTH + ON_BRICK_PROGRAMSTEPS;
+ VarsUi.TmpHandle = pMapLoader->pFunc(OPENWRITE,VarsUi.FilenameBuffer,NULL,&VarsUi.TmpLength);
+ if (!(VarsUi.TmpHandle & 0x8000))
+ {
+ VarsUi.FileHeader[0] = (UBYTE)(FILEFORMAT_PROGRAM >> 8);
+ VarsUi.FileHeader[1] = (UBYTE)(FILEFORMAT_PROGRAM);
+ VarsUi.FileHeader[2] = (UBYTE)(ON_BRICK_PROGRAMSTEPS >> 8);
+ VarsUi.FileHeader[3] = (UBYTE)(ON_BRICK_PROGRAMSTEPS);
+ VarsUi.FileHeader[4] = (UBYTE)(ON_BRICK_PROGRAMSTEPS);
+ VarsUi.FileHeader[5] = (UBYTE)0;
+ VarsUi.FileHeader[6] = (UBYTE)0;
+ VarsUi.FileHeader[7] = (UBYTE)0;
+ VarsUi.TmpLength = FILEHEADER_LENGTH;
+ pMapLoader->pFunc(WRITE,(UBYTE*)&VarsUi.TmpHandle,(UBYTE*)VarsUi.FileHeader,&VarsUi.TmpLength);
+ VarsUi.TmpLength = ON_BRICK_PROGRAMSTEPS;
+ pMapLoader->pFunc(WRITE,(UBYTE*)&VarsUi.TmpHandle,(UBYTE*)VarsUi.ProgramSteps,&VarsUi.TmpLength);
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ }
+ else
+ {
+ VarsUi.State++;
+ }
+ }
+ Action = MENU_DRAW;
+ }
+ break;
+
+ default : // Display memory error text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_OBP_MEMORY_FULL_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ cUiMenuPrevFile();
+ IOMapUi.State = NEXT_MENU;
+ VarsUi.State = 0;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ }
+
+ // Update display screen
+ if (Action == MENU_DRAW)
+ {
+ VarsUi.OBPTimer = 0;
+
+ for (VarsUi.Pointer = 0;VarsUi.Pointer < ON_BRICK_PROGRAMSTEPS;VarsUi.Pointer++)
+ {
+ VarsUi.Tmp = VarsUi.ProgramSteps[VarsUi.Pointer];
+ if ((VarsUi.Tmp >= MENU_ACTION_EMPTY) && (VarsUi.Tmp < MENU_ACTION_INVALID))
+ {
+ VarsUi.Tmp -= MENU_ACTION_EMPTY;
+ pMapDisplay->StepIcons[VarsUi.Pointer] = VarsUi.Tmp + 1;
+ }
+ if ((VarsUi.Tmp >= MENU_WAIT_EMPTY) && (VarsUi.Tmp < MENU_WAIT_INVALID))
+ {
+ VarsUi.Tmp -= MENU_WAIT_EMPTY;
+ pMapDisplay->StepIcons[VarsUi.Pointer] = VarsUi.Tmp + 1 + 16;
+ }
+ if (VarsUi.Tmp == MENU_LOOP)
+ {
+ pMapDisplay->StepIcons[VarsUi.Pointer] = 31;
+ }
+ if (VarsUi.Tmp == MENU_STOP)
+ {
+ pMapDisplay->StepIcons[VarsUi.Pointer] = 32;
+ }
+ pMapDisplay->UpdateMask |= STEPICON_BIT(STEPICON_1 + VarsUi.Pointer);
+ }
+
+ // and cursor
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)VarsUi.CursorTmp;
+ if (VarsUi.ProgramStepPointer < ON_BRICK_PROGRAMSTEPS)
+ {
+ VarsUi.CursorTmp[4] = 13 + (VarsUi.ProgramStepPointer * 17);
+ VarsUi.CursorTmp[5] = 24;
+ pMapDisplay->UpdateMask |= BITMAP_BIT(BITMAP_1);
+ }
+ if (PROG_RUNNING != pMapCmd->ProgStatus)
+ {
+ pMapDisplay->EraseMask |= (TEXTLINE_BIT(TEXTLINE_3) | TEXTLINE_BIT(TEXTLINE_2));
+ }
+ pMapDisplay->EraseMask |= TEXTLINE_BIT(TEXTLINE_4);
+ pMapDisplay->UpdateMask |= (SPECIAL_BIT(STEPLINE) | SPECIAL_BIT(TOPLINE));
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* cUiFileRun **********************************************************
+
+UBYTE cUiFindFileType(UBYTE *Filename) // Find file type number
+{
+ UBYTE Ext[FILENAME_LENGTH + 1];
+ UBYTE Result;
+ UBYTE Tmp1;
+ UBYTE Tmp2;
+
+ Result = FILETYPE_ALL;
+
+ Tmp1 = 0;
+ while ((Filename[Tmp1]) && (Tmp1 < FILENAME_LENGTH)) // Search forward for termination
+ {
+ Tmp1++;
+ }
+
+ while ((Tmp1) && (Filename[Tmp1] != '.')) // Search backward for "."
+ {
+ Tmp1--;
+ }
+
+ if (Filename[Tmp1] == '.') // If "."
+ {
+ Tmp1++;
+ Tmp2 = 0;
+
+ while ((Filename[Tmp1]) && (Tmp1 < FILENAME_LENGTH)) // Convert to upper to Ext
+ {
+ Ext[Tmp2] = tolower(Filename[Tmp1]);
+ Tmp1++;
+ Tmp2++;
+ }
+ Ext[Tmp2] = 0; // Inser termination
+
+ // Calculate type
+ for (Tmp1 = FILETYPE_ALL;(Tmp1 < FILETYPES) && (Result == FILETYPE_ALL);Tmp1++)
+ {
+ if (strcmp((char*)TXT_FILE_EXT[Tmp1],(char*)Ext) == 0)
+ {
+ Result = Tmp1;
+ }
+ }
+ }
+
+ return (Result);
+}
+
+
+#define FILERUN_FILENAMELINE TEXTLINE_4
+#define FILERUN_TEXTLINE TEXTLINE_5
+
+UBYTE cUiFileRun(UBYTE Action) // Run selected file
+{
+ switch (Action)
+ {
+
+ case MENU_INIT :
+ {
+ VarsUi.Tmp = 0;
+ while ((VarsUi.SelectedFilename[VarsUi.Tmp]) && (VarsUi.Tmp < FILENAME_LENGTH)) // Search forward for termination
+ {
+ VarsUi.Tmp++;
+ }
+
+ while ((VarsUi.Tmp) && (VarsUi.SelectedFilename[VarsUi.Tmp] != '.')) // Search backward for "."
+ {
+ VarsUi.Tmp--;
+ }
+
+ if (VarsUi.Tmp > DISPLAYLINE_LENGTH)
+ {
+ VarsUi.Tmp = DISPLAYLINE_LENGTH;
+ }
+
+ VarsUi.DisplayBuffer[VarsUi.Tmp] = 0;
+
+ while (VarsUi.Tmp) // Copy only name not ext
+ {
+ VarsUi.Tmp--;
+ VarsUi.DisplayBuffer[VarsUi.Tmp] = VarsUi.SelectedFilename[VarsUi.Tmp];
+ }
+
+ pMapDisplay->pTextLines[FILERUN_FILENAMELINE] = (UBYTE*)VarsUi.DisplayBuffer;
+ pMapDisplay->TextLinesCenterFlags = TEXTLINE_BIT(FILERUN_FILENAMELINE);
+ pMapDisplay->UpdateMask = TEXTLINE_BIT(FILERUN_FILENAMELINE);
+ }
+ break;
+
+ case MENU_RUN :
+ {
+ if (VarsUi.Timer < DISPLAY_SHOW_TIME)
+ {
+ VarsUi.Timer++;
+ }
+
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ IOMapUi.Flags |= UI_BUSY;
+ VarsUi.State++;
+ }
+ break;
+
+ case 1 : // Set state from extention when sound is ready
+ {
+ if (SOUND_IDLE == pMapSound->State)
+ {
+ pMapDisplay->pTextLines[FILERUN_TEXTLINE] = cUiGetString(TXT_FILERUN_RUNNING);
+ pMapDisplay->UpdateMask = (TEXTLINE_BIT(FILERUN_TEXTLINE) | TEXTLINE_BIT(FILERUN_FILENAMELINE));
+ pMapDisplay->TextLinesCenterFlags = (TEXTLINE_BIT(FILERUN_TEXTLINE) | TEXTLINE_BIT(FILERUN_FILENAMELINE));
+ cUiRunning(MENU_INIT);
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 2 :
+ {
+ if ((!pMapDisplay->EraseMask) && (!pMapDisplay->UpdateMask))
+ {
+ VarsUi.State = 10 * cUiFindFileType(VarsUi.SelectedFilename);
+ if (VarsUi.State == (FILETYPE_TRYME * 10))
+ {
+ VarsUi.State = FILETYPE_LMS * 10;
+ }
+ }
+ }
+ break;
+
+ case (FILETYPE_SOUND * 10 + 0) : // Start sound file (*.snd, *.rso) Wait for sound idle
+ {
+ strcpy((char*)pMapSound->SoundFilename,(char*)VarsUi.SelectedFilename);
+ pMapSound->Volume = IOMapUi.Volume;
+ pMapSound->Mode = SOUND_ONCE;
+ pMapSound->Flags |= SOUND_UPDATE;
+ VarsUi.State++;
+ }
+ break;
+
+ case (FILETYPE_SOUND * 10 + 1) : // Wait for stop or user break
+ {
+ cUiRunning(MENU_RUN);
+
+ if (SOUND_IDLE == pMapSound->State)
+ {
+ pMapDisplay->pTextLines[FILERUN_TEXTLINE] = cUiGetString(TXT_FILERUN_ENDED);
+ VarsUi.State = 99;
+ }
+ if (BUTTON_EXIT == cUiReadButtons())
+ {
+ pMapSound->Flags &= ~SOUND_UPDATE;
+ pMapSound->State = SOUND_STOP;
+ pMapDisplay->pTextLines[FILERUN_TEXTLINE] = cUiGetString(TXT_FILERUN_ABORTED);
+ VarsUi.State = 99;
+ }
+ }
+ break;
+
+ case (FILETYPE_LMS * 10 + 0) : // Start LMS file (*.rxe)
+ {
+ if ((!pMapDisplay->EraseMask) && (pMapCmd->ProgStatus == PROG_IDLE) && (!pMapButton->State[BTN4]))
+ {
+ strcpy((char*)pMapCmd->FileName,(char*)VarsUi.SelectedFilename);
+ pMapCmd->ActivateFlag = TRUE;
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case (FILETYPE_LMS * 10 + 1) : // Wait for program stop or user break
+ {
+ cUiRunning(MENU_RUN);
+
+ if ((IOMapUi.Flags & UI_REDRAW_STATUS) && (IOMapUi.Flags & UI_ENABLE_STATUS_UPDATE))
+ {
+ pMapDisplay->pTextLines[FILERUN_FILENAMELINE] = (UBYTE*)VarsUi.DisplayBuffer;
+ pMapDisplay->TextLinesCenterFlags = TEXTLINE_BIT(FILERUN_FILENAMELINE);
+ pMapDisplay->UpdateMask = TEXTLINE_BIT(FILERUN_FILENAMELINE);
+ pMapDisplay->pTextLines[FILERUN_TEXTLINE] = cUiGetString(TXT_FILERUN_RUNNING);
+ pMapDisplay->UpdateMask = (TEXTLINE_BIT(FILERUN_TEXTLINE) | TEXTLINE_BIT(FILERUN_FILENAMELINE));
+ pMapDisplay->TextLinesCenterFlags = (TEXTLINE_BIT(FILERUN_TEXTLINE) | TEXTLINE_BIT(FILERUN_FILENAMELINE));
+ }
+
+ switch (pMapCmd->ProgStatus)
+ {
+ case PROG_RUNNING :
+ {
+ }
+ break;
+
+ case PROG_OK :
+ {
+ pMapDisplay->pTextLines[FILERUN_TEXTLINE] = cUiGetString(TXT_FILERUN_ENDED);
+ VarsUi.State = 99;
+ }
+ break;
+
+ case PROG_ABORT :
+ {
+ pMapDisplay->pTextLines[FILERUN_TEXTLINE] = cUiGetString(TXT_FILERUN_ABORTED);
+ VarsUi.State = 99;
+ }
+ break;
+
+ default :
+ {
+ pMapDisplay->pTextLines[FILERUN_TEXTLINE] = cUiGetString(TXT_FILERUN_FILE_ERROR);
+ VarsUi.State = 99;
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case (FILETYPE_NXT * 10 + 0) :// Start Program file (*.prg)
+ {
+ VarsUi.TmpHandle = pMapLoader->pFunc(OPENREAD,VarsUi.SelectedFilename,NULL,&VarsUi.TmpLength);
+ if (!(VarsUi.TmpHandle & 0x8000))
+ {
+ VarsUi.TmpLength = FILEHEADER_LENGTH;
+ pMapLoader->pFunc(READ,(UBYTE*)&VarsUi.TmpHandle,VarsUi.FileHeader,&VarsUi.TmpLength);
+ VarsUi.TmpLength = ON_BRICK_PROGRAMSTEPS;
+ pMapLoader->pFunc(READ,(UBYTE*)&VarsUi.TmpHandle,VarsUi.ProgramSteps,&VarsUi.TmpLength);
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ }
+ if ((ON_BRICK_PROGRAMSTEPS == VarsUi.TmpLength) && (VarsUi.FileHeader[0] == (UBYTE)(FILEFORMAT_PROGRAM >> 8)) && (VarsUi.FileHeader[1] == (UBYTE)(FILEFORMAT_PROGRAM)))
+ {
+ // If tmp file exist -> delete it
+ sprintf((char*)VarsUi.FilenameBuffer,"%s.%s",(char*)TEMP_PROGRAM_FILENAME,(char*)TXT_TMP_EXT);
+ VarsUi.TmpHandle = pMapLoader->pFunc(FINDFIRST,VarsUi.FilenameBuffer,VarsUi.SearchFilenameBuffer,&VarsUi.TmpLength);
+ if (!(VarsUi.TmpHandle & 0x8000))
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ pMapLoader->pFunc(DELETE,VarsUi.FilenameBuffer,NULL,NULL);
+ }
+
+ // Save program as tmp file
+ VarsUi.TmpLength = FILEHEADER_LENGTH + ON_BRICK_PROGRAMSTEPS;
+ VarsUi.TmpHandle = pMapLoader->pFunc(OPENWRITE,VarsUi.FilenameBuffer,NULL,&VarsUi.TmpLength);
+ if (!(VarsUi.TmpHandle & 0x8000))
+ {
+ VarsUi.TmpLength = FILEHEADER_LENGTH;
+ pMapLoader->pFunc(WRITE,(UBYTE*)&VarsUi.TmpHandle,(UBYTE*)VarsUi.FileHeader,&VarsUi.TmpLength);
+ VarsUi.TmpLength = ON_BRICK_PROGRAMSTEPS;
+ pMapLoader->pFunc(WRITE,(UBYTE*)&VarsUi.TmpHandle,(UBYTE*)VarsUi.ProgramSteps,&VarsUi.TmpLength);
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ }
+
+ pMapDisplay->UpdateMask &= ~TEXTLINE_BIT(FILERUN_FILENAMELINE);
+ pMapDisplay->EraseMask |= TEXTLINE_BIT(FILERUN_FILENAMELINE);
+ VarsUi.State++;
+ }
+ else
+ {
+ pMapDisplay->pTextLines[FILERUN_TEXTLINE] = cUiGetString(TXT_FILERUN_FILE_ERROR);
+ VarsUi.State = 99;
+ }
+ VarsUi.GUSState = 0;
+ }
+ break;
+
+ case (FILETYPE_NXT * 10 + 1) : // Wait for program stop or user break
+ {
+ VarsUi.State = VarsUi.GUSState;
+ cUiOnBrickProgramming(MENU_RUN);
+ VarsUi.GUSState = VarsUi.State;
+ if (VarsUi.State)
+ {
+ VarsUi.State = (FILETYPE_NXT * 10 + 1);
+ }
+ else
+ {
+ pMapDisplay->pTextLines[FILERUN_TEXTLINE] = cUiGetString(TXT_FILERUN_ENDED);
+ VarsUi.State = 99;
+ }
+ }
+ break;
+
+ case 99 : // Wait for display show time or user action
+ {
+ pMapDisplay->EraseMask = SCREEN_BIT(SCREEN_LARGE);
+ pMapDisplay->UpdateMask = (TEXTLINE_BIT(FILERUN_TEXTLINE) | TEXTLINE_BIT(FILERUN_FILENAMELINE));
+ pMapDisplay->TextLinesCenterFlags = (TEXTLINE_BIT(FILERUN_TEXTLINE) | TEXTLINE_BIT(FILERUN_FILENAMELINE));
+ IOMapUi.Flags |= UI_REDRAW_STATUS | UI_ENABLE_STATUS_UPDATE;
+ cUiRunning(MENU_UPDATE);
+ VarsUi.Timer = 0;
+ VarsUi.State++;
+ }
+ break;
+
+ default :
+ {
+ if ((++VarsUi.Timer >= DISPLAY_SHOW_TIME) || (BUTTON_NONE != cUiReadButtons()))
+ {
+ if (pMapCmd->ProgStatus != PROG_IDLE)
+ pMapCmd->ProgStatus = PROG_RESET;
+ pMapDisplay->UpdateMask = 0;
+ pMapDisplay->TextLinesCenterFlags = 0;
+ cUiRunning(MENU_EXIT);
+ pMapDisplay->EraseMask = TEXTLINE_BIT(FILERUN_TEXTLINE);
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(FILERUN_FILENAMELINE);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(FILERUN_FILENAMELINE);
+ IOMapUi.Flags &= ~UI_BUSY;
+ VarsUi.State = 0;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* cUiFileDelete *******************************************************
+
+UBYTE cUiFileDelete(UBYTE Action)
+{
+ if (MENU_INIT == Action)
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ VarsUi.State++;
+ }
+ break;
+
+ case 1 :
+ {
+ if (SOUND_IDLE == pMapSound->State)
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 2 :
+ {
+ pMapLoader->pFunc(DELETE,VarsUi.SelectedFilename,NULL,NULL);
+ VarsUi.State++;
+ }
+ break;
+
+ default : // Display deleted text
+ {
+ if (!cUiFeedback((BMPMAP*)Info,TXT_FB_FD_FILE_DELETED_INFO,0,DISPLAY_SHOW_TIME))
+ {
+ IOMapUi.State = EXIT_PRESSED;
+ VarsUi.State = 0;
+ }
+ }
+ break;
+
+ }
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* cUiView ************************************************************
+
+UBYTE cUiView(UBYTE Action) // MENU_INIT
+{
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ switch (Action)
+ {
+ case MENU_INIT : // Init
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3] = cUiGetString(TXT_VIEW_SELECT);
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(TEXTLINE_3);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3);
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_SMALL);
+ }
+ break;
+
+ default :
+ {
+ if ((Action > MENU_SENSOR_EMPTY) && (Action < MENU_SENSOR_INVALID))
+ {
+ VarsUi.SelectedSensor = Action;
+ }
+ if ((Action >= MENU_PORT_1) && (Action <= MENU_PORT_C))
+ {
+ VarsUi.SelectedPort = Action;
+ IOMapUi.Flags |= UI_BUSY;
+
+ cUiSetupSensor(VarsUi.SelectedPort,VarsUi.SelectedSensor);
+ cUiResetSensor(VarsUi.SelectedPort,VarsUi.SelectedSensor);
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_LARGE);
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)Display;
+ pMapDisplay->UpdateMask = BITMAP_BIT(BITMAP_1);
+ IOMapUi.Flags |= UI_REDRAW_STATUS;
+ VarsUi.ReadoutTimer = 0;;
+ VarsUi.Timer = 0;
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case 1 :
+ {
+ VarsUi.ReadoutTimer++;
+ VarsUi.Timer++;
+ if (VarsUi.Timer == MIN_SENSOR_READ_TIME)
+ {
+ // Ask sensors for data
+ cUiAskSensor(VarsUi.SelectedPort,VarsUi.SelectedSensor);
+ }
+ if (VarsUi.Timer >= (MIN_SENSOR_READ_TIME * 2))
+ {
+ // Read sensor data
+ VarsUi.ViewSampleValid = cUiGetSensorValue(VarsUi.SelectedPort,VarsUi.SelectedSensor,&VarsUi.ViewSampleValue);
+ VarsUi.Timer = 0;
+ }
+
+ if (VarsUi.ReadoutTimer >= DISPLAY_VIEW_UPDATE)
+ {
+ VarsUi.ReadoutTimer = 0;
+ cUiPrintSensorInDisplayBuffer(VarsUi.SelectedPort,VarsUi.SelectedSensor,VarsUi.ViewSampleValid,VarsUi.ViewSampleValue);
+ pMapDisplay->pTextLines[TEXTLINE_4] = VarsUi.DisplayBuffer;
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(TEXTLINE_4);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_4);
+ }
+
+ VarsUi.Tmp = cUiReadButtons();
+ if (VarsUi.Tmp == BUTTON_EXIT)
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3] = cUiGetString(TXT_VIEW_SELECT);
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(TEXTLINE_3);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3);
+ pMapDisplay->UpdateMask &= ~TEXTLINE_BIT(TEXTLINE_4);
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_SMALL);
+ VarsUi.State++;
+ }
+ if (VarsUi.Tmp == BUTTON_ENTER)
+ {
+ cUiResetSensor(VarsUi.SelectedPort,VarsUi.SelectedSensor);
+ }
+ }
+ break;
+
+ default :
+ {
+ cUiReleaseSensors();
+ IOMapUi.Flags &= ~UI_BUSY;
+ VarsUi.State = 0;
+ IOMapUi.State = EXIT_PRESSED;
+ }
+ break;
+
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* cUiBtOn ************************************************************
+
+UBYTE cUiBtOn(UBYTE Action)
+{
+ switch (Action)
+ {
+ case MENU_ON :
+ {
+ switch (VarsUi.State)
+ {
+ case 0 : // Turn BT on
+ {
+ VarsUi.BTCommand = (UBYTE)BTON;
+ VarsUi.BTPar1 = (UBYTE)0;
+ VarsUi.BTPar2 = (UBYTE)0;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ break;
+
+ case 1 : // Display turning on text
+ {
+ if (!cUiFeedback((BMPMAP*)Wait,TXT_FB_BT_TURNING_ON_WAIT,0,0))
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 2 : // Check result
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ if (VarsUi.BTResult == SUCCESS)
+ {
+ Action = MENU_EXIT;
+ }
+ else
+ {
+ VarsUi.State++;
+ }
+ }
+ }
+ break;
+
+ default : // Display fail text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_BT_TURNING_ON_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case MENU_OFF :
+ {
+ switch (VarsUi.State)
+ {
+ case 0 : // Turn BT off
+ {
+ VarsUi.BTCommand = (UBYTE)BTOFF;
+ VarsUi.BTPar1 = (UBYTE)0;
+ VarsUi.BTPar2 = (UBYTE)0;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ break;
+
+ case 1 : // Display turning off text
+ {
+ if (!cUiFeedback((BMPMAP*)Wait,TXT_FB_BT_TURNING_OFF_WAIT,0,0))
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 2 : // Check result
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ if (VarsUi.BTResult == SUCCESS)
+ {
+ Action = MENU_EXIT;
+ }
+ else
+ {
+ VarsUi.State++;
+ }
+ }
+ }
+ break;
+
+ default : // Display fail text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_BT_TURNING_OFF_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ }
+ if (Action == MENU_EXIT)
+ {
+ VarsUi.State = 0;
+ IOMapUi.State = EXIT_PRESSED;
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* cUiBtVisiability ***************************************************
+
+UBYTE cUiBtVisiability(UBYTE Action) // Visibility on/off
+{
+ switch (Action)
+ {
+ case MENU_ON : // Set visible
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ VarsUi.BTCommand = (UBYTE)VISIBILITY;
+ VarsUi.BTPar1 = (UBYTE)1;
+ VarsUi.BTPar2 = (UBYTE)0;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ default :
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case MENU_OFF : // Set invisible
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ VarsUi.BTCommand = (UBYTE)VISIBILITY;
+ VarsUi.BTPar1 = (UBYTE)0;
+ VarsUi.BTPar2 = (UBYTE)0;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ default :
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ }
+ if (Action == MENU_EXIT)
+ {
+ VarsUi.State = 0;
+ IOMapUi.State = EXIT_PRESSED;
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* cUiBtSearch ********************************************************
+
+UBYTE cUiBtSearch(UBYTE Action) // Search for devices
+{
+ if (Action == MENU_INIT) // Init
+ {
+ switch (VarsUi.State)
+ {
+ case 0 : // Show three menu icons
+ {
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = pMapDisplay->pMenuIcons[MENUICON_CENTER];
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = pMapDisplay->pMenuIcons[MENUICON_CENTER];
+ pMapDisplay->UpdateMask |= MENUICON_BITS;
+ VarsUi.State++;
+ }
+ break;
+
+ case 1 : // Display wait text and start search
+ {
+ if (!cUiFeedback((BMPMAP*)Wait,TXT_FB_BT_SEARCHING_WAIT,0,0))
+ {
+ VarsUi.BTCommand = (UBYTE)SEARCH;
+ VarsUi.BTPar1 = (UBYTE)1;
+ VarsUi.BTPar2 = (UBYTE)0;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ VarsUi.DisplayBuffer[0] = 0;
+ pMapDisplay->pMenuText = VarsUi.DisplayBuffer;
+ pMapDisplay->UpdateMask |= SPECIAL_BIT(MENUTEXT);
+ VarsUi.NoOfNames = 0;
+ VarsUi.NoOfDevices = 0;
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ }
+ break;
+
+ case 2 : // Wait for search finished
+ {
+ if (VarsUi.NoOfNames != pMapComm->BtDeviceNameCnt)
+ {
+ VarsUi.NoOfNames = pMapComm->BtDeviceNameCnt;
+
+ if ((VarsUi.NoOfNames) && (VarsUi.NoOfNames <= DISPLAYLINE_LENGTH))
+ {
+ sprintf((char*)VarsUi.DisplayBuffer,"%.*s",VarsUi.NoOfNames,"****************");
+ pMapDisplay->pMenuText = VarsUi.DisplayBuffer;
+ pMapDisplay->UpdateMask |= SPECIAL_BIT(MENUTEXT);
+ }
+ }
+ if (VarsUi.NoOfDevices != pMapComm->BtDeviceCnt)
+ {
+ VarsUi.NoOfDevices = pMapComm->BtDeviceCnt;
+
+ if ((VarsUi.NoOfDevices) && (VarsUi.NoOfDevices <= DISPLAYLINE_LENGTH))
+ {
+ sprintf((char*)VarsUi.DisplayBuffer,"%.*s",VarsUi.NoOfDevices,"????????????????");
+ pMapDisplay->pMenuText = VarsUi.DisplayBuffer;
+ pMapDisplay->UpdateMask |= SPECIAL_BIT(MENUTEXT);
+ }
+ }
+
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ cUiBTCommand(UI_BT_GET_DEVICES,0,&VarsUi.Devices,NULL);
+ if (VarsUi.Devices)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+
+ if (cUiReadButtons() == BUTTON_EXIT)
+ {
+ VarsUi.BTCommand = (UBYTE)STOPSEARCH;
+ VarsUi.BTPar1 = (UBYTE)0;
+ VarsUi.BTPar2 = (UBYTE)0;
+ pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult));
+ VarsUi.State = 4;
+ }
+ }
+ break;
+
+ case 3 : // Auto enter to next menu
+ {
+ IOMapUi.State = ENTER_PRESSED;
+ VarsUi.State = 0;
+ }
+ break;
+
+ case 4 : // Display info text
+ {
+ if (!cUiFeedback((BMPMAP*)Info,TXT_FB_BT_SEARCH_ABORTED_INFO,0,DISPLAY_SHOW_TIME))
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 5 : // Wait for abort
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ cUiBTCommand(UI_BT_GET_DEVICES,0,&VarsUi.Devices,NULL);
+ if (VarsUi.Devices)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ }
+ break;
+
+ case 6 : // Auto enter to next menu
+ {
+ IOMapUi.State = ENTER_PRESSED;
+ VarsUi.State = 0;
+ }
+ break;
+
+ default : // Display fail text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_BT_SEARCHING_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ VarsUi.State = 0;
+ IOMapUi.State = EXIT_PRESSED;
+ }
+ }
+ break;
+
+ }
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* cUiBtDeviceList ****************************************************
+
+UBYTE cUiBtDeviceList(UBYTE Action) // Show devices
+{
+ switch (Action)
+ {
+ case MENU_INIT : // Init "Search" list
+ {
+ VarsUi.SelectedDevice = 0;
+ VarsUi.DevicesKnown = 0;
+ cUiBTCommand(UI_BT_GET_DEVICES,VarsUi.DevicesKnown,&VarsUi.Devices,NULL);
+ if (VarsUi.Devices)
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3] = cUiGetString(TXT_BTDEVICELIST_SELECT);
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(TEXTLINE_3);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3);
+ VarsUi.MenuIconTextSave = pMapDisplay->pMenuText;
+ VarsUi.DeviceCenter = 1;
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ else
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ case MENU_INIT_ALTERNATIVE : // Init only "My contacts"
+ {
+ VarsUi.SelectedDevice = 0;
+ VarsUi.DevicesKnown = 1;
+ cUiBTCommand(UI_BT_GET_DEVICES,VarsUi.DevicesKnown,&VarsUi.Devices,NULL);
+ if (VarsUi.Devices)
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3] = cUiGetString(TXT_BTDEVICELIST_SELECT);
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(TEXTLINE_3);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3);
+ VarsUi.MenuIconTextSave = pMapDisplay->pMenuText;
+ VarsUi.DeviceCenter = 1;
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ else
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ case MENU_LEFT : // Left button
+ {
+ cUiListLeft(VarsUi.Devices,&VarsUi.DeviceCenter);
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_RIGHT : // Right button
+ {
+ cUiListRight(VarsUi.Devices,&VarsUi.DeviceCenter);
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_SELECT : // Select for connection
+ {
+ VarsUi.SelectedDevice = VarsUi.DeviceCenter;
+ pMapDisplay->pMenuText = VarsUi.MenuIconTextSave;
+ IOMapUi.State = NEXT_MENU;
+ }
+ break;
+
+ case MENU_DELETE : // Remove device from "My contacts"
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ if (VarsUi.SelectedDevice)
+ {
+ if (cUiBTGetDeviceIndex(VarsUi.DevicesKnown,VarsUi.SelectedDevice - 1,&VarsUi.BTIndex))
+ {
+ VarsUi.BTCommand = (UBYTE)REMOVEDEVICE;
+ VarsUi.BTPar1 = (UBYTE)VarsUi.BTIndex;
+ VarsUi.BTPar2 = (UBYTE)0;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ else
+ {
+ Action = MENU_EXIT;
+ }
+ VarsUi.SelectedDevice = 0;
+ }
+ else
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ case 1 :
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ if (VarsUi.BTResult == SUCCESS)
+ {
+ Action = MENU_EXIT;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ }
+ break;
+
+ default : // Display fail text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_BT_REMOVE_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ }
+
+ if (Action == MENU_DRAW)
+ {
+ cUiListCalc(VarsUi.Devices,&VarsUi.DeviceCenter,&VarsUi.DeviceLeft,&VarsUi.DeviceRight);
+
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = NULL;
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = NULL;
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = NULL;
+
+ if (VarsUi.DeviceLeft)
+ {
+ VarsUi.Tmp = VarsUi.DeviceLeft - 1;
+ cUiBTCommand(UI_BT_GET_DEVICE_TYPE,VarsUi.DevicesKnown,&VarsUi.Tmp,&VarsUi.DeviceType);
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = (UBYTE*)&Devices->Data[VarsUi.DeviceType * Devices->ItemPixelsX * (Devices->ItemPixelsY / 8)];
+ pMapDisplay->UpdateMask |= MENUICON_BIT(MENUICON_LEFT);
+ }
+ if (VarsUi.DeviceCenter)
+ {
+ VarsUi.Tmp = VarsUi.DeviceCenter - 1;
+ cUiBTCommand(UI_BT_GET_DEVICE_TYPE,VarsUi.DevicesKnown,&VarsUi.Tmp,&VarsUi.DeviceType);
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = (UBYTE*)&Devices->Data[VarsUi.DeviceType * Devices->ItemPixelsX * (Devices->ItemPixelsY / 8)];
+ pMapDisplay->UpdateMask |= MENUICON_BIT(MENUICON_CENTER);
+ }
+ if (VarsUi.DeviceRight)
+ {
+ VarsUi.Tmp = VarsUi.DeviceRight - 1;
+ cUiBTCommand(UI_BT_GET_DEVICE_TYPE,VarsUi.DevicesKnown,&VarsUi.Tmp,&VarsUi.DeviceType);
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = (UBYTE*)&Devices->Data[VarsUi.DeviceType * Devices->ItemPixelsX * (Devices->ItemPixelsY / 8)];
+ pMapDisplay->UpdateMask |= MENUICON_BIT(MENUICON_RIGHT);
+ }
+
+ pMapDisplay->EraseMask |= TEXTLINE_BIT(TEXTLINE_5);
+
+ VarsUi.Tmp = VarsUi.DeviceCenter - 1;
+ cUiBTCommand(UI_BT_GET_DEVICE_NAME,VarsUi.DevicesKnown,&VarsUi.Tmp,VarsUi.DisplayBuffer);
+
+ pMapDisplay->pMenuText = VarsUi.DisplayBuffer;
+ pMapDisplay->EraseMask |= MENUICON_BITS;
+ pMapDisplay->UpdateMask |= (SPECIAL_BIT(FRAME_SELECT) | SPECIAL_BIT(MENUTEXT));
+ }
+ if (Action == MENU_EXIT)
+ {
+ VarsUi.State = 0;
+ IOMapUi.State = EXIT_PRESSED;
+ }
+
+ return (VarsUi.State);
+}
+
+
+//******* cUiBtConnectList ***************************************************
+
+UBYTE cUiBtConnectList(UBYTE Action) // Show connections and maybe disconnect
+{
+ switch (Action)
+ {
+ case MENU_INIT : // Init
+ {
+ VarsUi.Slots = SIZE_OF_BT_CONNECT_TABLE;
+ VarsUi.SlotCenter = 2;
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_LEFT : // Left button
+ {
+ cUiListLeft(VarsUi.Slots,&VarsUi.SlotCenter);
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_RIGHT : // Right button
+ {
+ cUiListRight(VarsUi.Slots,&VarsUi.SlotCenter);
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_UPDATE : // Check connection valid
+ {
+ VarsUi.Tmp = VarsUi.SlotCenter - 1;
+ if (cUiBTCommand(UI_BT_GET_CONNECTION_VALID,NULL,&VarsUi.Tmp,NULL) != UI_BT_SUCCES)
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ case MENU_DISCONNECT : // Disconnect
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ VarsUi.SelectedSlot = VarsUi.SlotCenter - 1;
+ VarsUi.BTCommand = (UBYTE)DISCONNECT;
+ VarsUi.BTPar1 = (UBYTE)VarsUi.SelectedSlot;
+ VarsUi.BTPar2 = (UBYTE)0;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ break;
+
+ case 1 :
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ if (VarsUi.BTResult == SUCCESS)
+ {
+ Action = MENU_EXIT;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ }
+ break;
+
+ default : // Display fail text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_BT_DISCONNECT_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ }
+ if (Action == MENU_DRAW)
+ {
+ cUiListCalc(VarsUi.Slots,&VarsUi.SlotCenter,&VarsUi.SlotLeft,&VarsUi.SlotRight);
+
+ pMapDisplay->pBitmaps[BITMAP_2] = (BMPMAP*)VarsUi.PortBitmapLeft;
+ pMapDisplay->pBitmaps[BITMAP_3] = (BMPMAP*)VarsUi.PortBitmapCenter;
+ pMapDisplay->pBitmaps[BITMAP_4] = (BMPMAP*)VarsUi.PortBitmapRight;
+
+ VarsUi.Tmp = VarsUi.SlotLeft - 1;
+ if (cUiBTCommand(UI_BT_GET_CONNECTION_VALID,NULL,&VarsUi.Tmp,NULL) == UI_BT_SUCCES)
+ {
+ cUiBTCommand(UI_BT_GET_CONNECTION_TYPE,NULL,&VarsUi.Tmp,&VarsUi.DeviceType);
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = (UBYTE*)&Devices->Data[VarsUi.DeviceType * Devices->ItemPixelsX * (Devices->ItemPixelsY / 8)];
+ cUiDrawPortNo(VarsUi.PortBitmapLeft,MENUICON_LEFT,VarsUi.Tmp);
+ pMapDisplay->UpdateMask |= BITMAP_BIT(BITMAP_2);
+ }
+ else
+ {
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = (UBYTE*)&Connections->Data[VarsUi.Tmp * Connections->ItemPixelsX * (Connections->ItemPixelsY / 8)];
+ }
+
+ VarsUi.Tmp = VarsUi.SlotCenter - 1;
+ cUiBTCommand(UI_BT_GET_CONNECTION_NAME,NULL,&VarsUi.Tmp,VarsUi.DisplayBuffer);
+ pMapDisplay->EraseMask |= TEXTLINE_BIT(TEXTLINE_5);
+ pMapDisplay->pMenuText = VarsUi.DisplayBuffer;
+
+ if (cUiBTCommand(UI_BT_GET_CONNECTION_VALID,NULL,&VarsUi.Tmp,NULL) == UI_BT_SUCCES)
+ {
+ cUiBTCommand(UI_BT_GET_CONNECTION_TYPE,NULL,&VarsUi.Tmp,&VarsUi.DeviceType);
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = (UBYTE*)&Devices->Data[VarsUi.DeviceType * Devices->ItemPixelsX * (Devices->ItemPixelsY / 8)];
+ cUiDrawPortNo(VarsUi.PortBitmapCenter,MENUICON_CENTER,VarsUi.Tmp);
+ pMapDisplay->UpdateMask |= BITMAP_BIT(BITMAP_3);
+ }
+ else
+ {
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = (UBYTE*)&Connections->Data[VarsUi.Tmp * Connections->ItemPixelsX * (Connections->ItemPixelsY / 8)];
+ }
+ VarsUi.Tmp = VarsUi.SlotRight - 1;
+ if (cUiBTCommand(UI_BT_GET_CONNECTION_VALID,NULL,&VarsUi.Tmp,NULL) == UI_BT_SUCCES)
+ {
+ cUiBTCommand(UI_BT_GET_CONNECTION_TYPE,NULL,&VarsUi.Tmp,&VarsUi.DeviceType);
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = (UBYTE*)&Devices->Data[VarsUi.DeviceType * Devices->ItemPixelsX * (Devices->ItemPixelsY / 8)];
+ cUiDrawPortNo(VarsUi.PortBitmapRight,MENUICON_RIGHT,VarsUi.Tmp);
+ pMapDisplay->UpdateMask |= BITMAP_BIT(BITMAP_4);
+ }
+ else
+ {
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = (UBYTE*)&Connections->Data[VarsUi.Tmp * Connections->ItemPixelsX * (Connections->ItemPixelsY / 8)];
+ }
+ pMapDisplay->EraseMask &= ~SCREEN_BIT(SCREEN_LARGE);
+ pMapDisplay->EraseMask |= MENUICON_BITS;
+ pMapDisplay->UpdateMask |= (MENUICON_BITS | SPECIAL_BIT(FRAME_SELECT) | SPECIAL_BIT(MENUTEXT));
+ }
+ if (Action == MENU_EXIT)
+ {
+ VarsUi.State = 0;
+ IOMapUi.State = EXIT_PRESSED;
+ }
+
+
+ return (VarsUi.State);
+}
+
+
+UBYTE cUiBtConnect(UBYTE Action) // Select connection no and insert device
+{
+ switch (Action)
+ {
+ case MENU_INIT : // Init
+ {
+ VarsUi.Slots = SIZE_OF_BT_CONNECT_TABLE - 1;
+ VarsUi.SlotCenter = 1;
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_LEFT : // Left button
+ {
+ cUiListLeft(VarsUi.Slots,&VarsUi.SlotCenter);
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_RIGHT : // Right button
+ {
+ cUiListRight(VarsUi.Slots,&VarsUi.SlotCenter);
+ Action = MENU_DRAW;
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_CONNECT : // Insert device
+ {
+ switch (VarsUi.State)
+ {
+ case 0 : // Check selected device
+ {
+ VarsUi.SelectedSlot = (UBYTE)VarsUi.SlotCenter;
+ if (VarsUi.SelectedDevice)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ case 1 : // Display wait text
+ {
+ if (!cUiFeedback((BMPMAP*)Wait,TXT_FB_BT_CONNECTING_WAIT,0,0))
+ {
+ if (cUiBTGetDeviceIndex(VarsUi.DevicesKnown,VarsUi.SelectedDevice - 1,&VarsUi.BTIndex))
+ {
+ VarsUi.BTCommand = (UBYTE)CONNECT;
+ VarsUi.BTPar1 = (UBYTE)VarsUi.BTIndex;
+ VarsUi.BTPar2 = (UBYTE)VarsUi.SelectedSlot;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ else
+ {
+ VarsUi.State = 99;
+ }
+ }
+ }
+ break;
+
+ case 2 : // Wait for result
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ if (VarsUi.BTResult == SUCCESS)
+ {
+ Action = MENU_EXIT;
+ }
+ else
+ {
+ if (VarsUi.BTResult == REQPIN)
+ {
+ sprintf((char*)pMapSound->SoundFilename,"%s.%s",(char*)UI_ATTENTION_SOUND,(char*)TXT_SOUND_EXT);
+ pMapSound->Volume = IOMapUi.Volume;
+ pMapSound->Mode = SOUND_ONCE;
+ pMapSound->Flags |= SOUND_UPDATE;
+ strcpy((char*)VarsUi.UserString,(char*)DEFAULT_PIN_CODE);
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 6;
+ }
+ }
+ }
+ }
+ break;
+
+ case 3 : // Get pincode and send
+ {
+ if (!cUiGetUserString(0))
+ {
+ if (VarsUi.UserString[0] == 0)
+ {
+ sprintf((char*)VarsUi.UserString,"%08lX",VarsUi.CRPasskey);
+ Action = MENU_EXIT;
+ }
+ else
+ {
+ VarsUi.State++;
+ }
+ pMapComm->pFunc2(VarsUi.UserString);
+ }
+ }
+ break;
+
+ case 4 : // Display wait text
+ {
+ if (!cUiFeedback((BMPMAP*)Wait,TXT_FB_BT_CONNECTING_WAIT,0,0))
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 5 : // Wait for result
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ if (VarsUi.BTResult == SUCCESS)
+ {
+ Action = MENU_EXIT;
+ }
+ else
+ {
+ VarsUi.State = 6;
+ }
+ }
+ }
+ break;
+
+ case 6 : // Display busy text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_BT_CONNECT_BUSY_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ default : // Display fail text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_BT_CONNECTING_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ case MENU_SEND :
+ {
+ switch (VarsUi.State)
+ {
+ case 0 : // Check connection
+ {
+ VarsUi.SelectedSlot = (UBYTE)VarsUi.SlotCenter;
+ if (VarsUi.SelectedFilename[0] && (cUiBTCommand(UI_BT_GET_CONNECTION_NAME,NULL,&VarsUi.SelectedSlot,NULL) == UI_BT_SUCCES))
+ {
+ VarsUi.State += 2;
+ }
+ else
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 1 : // Display fail text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_BT_SENDING_NO_CONN_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ case 2 : // Display wait text and send file
+ {
+ if (!cUiFeedback((BMPMAP*)Wait,TXT_FB_BT_SENDING_WAIT,0,0))
+ {
+ VarsUi.BTCommand = (UBYTE)SENDFILE;
+ VarsUi.BTPar1 = (UBYTE)VarsUi.SelectedSlot;
+ VarsUi.BTPar2 = (UBYTE)0;
+ if (pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,VarsUi.SelectedFilename,&(VarsUi.BTResult)) == SUCCESS)
+ {
+ VarsUi.Timer = 0;
+ VarsUi.State++;
+ }
+ else
+ {
+ VarsUi.State = 4;
+ }
+ }
+ }
+ break;
+
+ case 3 : // Wait for result
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ if (VarsUi.BTResult == SUCCESS)
+ {
+ VarsUi.State += 2;
+ }
+ else
+ {
+ VarsUi.State++;
+ }
+ }
+ VarsUi.Timer++;
+ }
+ break;
+
+ case 4 : // Display fail text
+ {
+ if (!cUiFeedback((BMPMAP*)Fail,TXT_FB_BT_SENDING_FAIL,0,DISPLAY_SHOW_ERROR_TIME))
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ case 5 : // Wait min. "DISPLAY_SHOW_TIME" to show "TXT_FB_BT_SENDING_WAIT"
+ {
+ if (++VarsUi.Timer >= DISPLAY_SHOW_TIME)
+ {
+ Action = MENU_EXIT;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ }
+ if (Action == MENU_DRAW) // Update display
+ {
+ cUiListCalc(VarsUi.Slots,&VarsUi.SlotCenter,&VarsUi.SlotLeft,&VarsUi.SlotRight);
+
+ pMapDisplay->pBitmaps[BITMAP_2] = (BMPMAP*)VarsUi.PortBitmapLeft;
+ pMapDisplay->pBitmaps[BITMAP_3] = (BMPMAP*)VarsUi.PortBitmapCenter;
+ pMapDisplay->pBitmaps[BITMAP_4] = (BMPMAP*)VarsUi.PortBitmapRight;
+
+ VarsUi.Tmp = VarsUi.SlotLeft;
+ if (cUiBTCommand(UI_BT_GET_CONNECTION_VALID,NULL,&VarsUi.Tmp,NULL) == UI_BT_SUCCES)
+ {
+ cUiBTCommand(UI_BT_GET_CONNECTION_TYPE,NULL,&VarsUi.Tmp,&VarsUi.DeviceType);
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = (UBYTE*)&Devices->Data[VarsUi.DeviceType * Devices->ItemPixelsX * (Devices->ItemPixelsY / 8)];
+ cUiDrawPortNo(VarsUi.PortBitmapLeft,MENUICON_LEFT,VarsUi.Tmp);
+ pMapDisplay->UpdateMask |= BITMAP_BIT(BITMAP_2);
+ }
+ else
+ {
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = (UBYTE*)&Connections->Data[VarsUi.Tmp * Connections->ItemPixelsX * (Connections->ItemPixelsY / 8)];
+ }
+
+ VarsUi.Tmp = VarsUi.SlotCenter;
+ cUiBTCommand(UI_BT_GET_CONNECTION_NAME,NULL,&VarsUi.Tmp,VarsUi.DisplayBuffer);
+ pMapDisplay->EraseMask |= TEXTLINE_BIT(TEXTLINE_5);
+ pMapDisplay->pMenuText = VarsUi.DisplayBuffer;
+
+ if (cUiBTCommand(UI_BT_GET_CONNECTION_VALID,NULL,&VarsUi.Tmp,NULL) == UI_BT_SUCCES)
+ {
+ cUiBTCommand(UI_BT_GET_CONNECTION_TYPE,NULL,&VarsUi.Tmp,&VarsUi.DeviceType);
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = (UBYTE*)&Devices->Data[VarsUi.DeviceType * Devices->ItemPixelsX * (Devices->ItemPixelsY / 8)];
+ cUiDrawPortNo(VarsUi.PortBitmapCenter,MENUICON_CENTER,VarsUi.Tmp);
+ pMapDisplay->UpdateMask |= BITMAP_BIT(BITMAP_3);
+ }
+ else
+ {
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = (UBYTE*)&Connections->Data[VarsUi.Tmp * Connections->ItemPixelsX * (Connections->ItemPixelsY / 8)];
+ }
+ VarsUi.Tmp = VarsUi.SlotRight;
+ if (cUiBTCommand(UI_BT_GET_CONNECTION_VALID,NULL,&VarsUi.Tmp,NULL) == UI_BT_SUCCES)
+ {
+ cUiBTCommand(UI_BT_GET_CONNECTION_TYPE,NULL,&VarsUi.Tmp,&VarsUi.DeviceType);
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = (UBYTE*)&Devices->Data[VarsUi.DeviceType * Devices->ItemPixelsX * (Devices->ItemPixelsY / 8)];
+ cUiDrawPortNo(VarsUi.PortBitmapRight,MENUICON_RIGHT,VarsUi.Tmp);
+ pMapDisplay->UpdateMask |= BITMAP_BIT(BITMAP_4);
+ }
+ else
+ {
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = (UBYTE*)&Connections->Data[VarsUi.Tmp * Connections->ItemPixelsX * (Connections->ItemPixelsY / 8)];
+ }
+ pMapDisplay->EraseMask &= ~SCREEN_BIT(SCREEN_LARGE);
+ pMapDisplay->EraseMask |= MENUICON_BITS;
+ pMapDisplay->UpdateMask |= (MENUICON_BITS | SPECIAL_BIT(FRAME_SELECT) | SPECIAL_BIT(MENUTEXT));
+ }
+ if (Action == MENU_EXIT)
+ {
+ IOMapUi.State = EXIT_PRESSED;
+ VarsUi.State = 0;
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* cUiPowerOffTime ****************************************************
+
+UBYTE cUiPowerOffTime(UBYTE Action) // MENU_INIT,MENU_LEFT,MENU_RIGHT,MENU_EXIT
+{
+ switch (Action)
+ {
+ case MENU_INIT : // Init time counter and cursor bitmap
+ {
+ VarsUi.Counter = cUiNVReadPowerOnTimeCount() + 1;
+
+ VarsUi.pTmp = (UBYTE*)Cursor;
+ for (VarsUi.Tmp = 0;(VarsUi.Tmp < SIZE_OF_CURSOR) && (VarsUi.Tmp < (UBYTE)sizeof(Cursor));VarsUi.Tmp++)
+ {
+ VarsUi.CursorTmp[VarsUi.Tmp] = *VarsUi.pTmp;
+ VarsUi.pTmp++;
+ }
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_LEFT : // Dec
+ {
+ cUiListLeft(POWER_OFF_TIME_STEPS,&VarsUi.Counter);
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_RIGHT : // Inc
+ {
+ cUiListRight(POWER_OFF_TIME_STEPS,&VarsUi.Counter);
+ Action = MENU_DRAW;
+ }
+ break;
+
+ case MENU_ENTER : // Enter
+ {
+ cUiNVWritePowerOnTimeCount(VarsUi.Counter - 1);
+ IOMapUi.SleepTimeout = PowerOffTimeSteps[cUiNVReadPowerOnTimeCount()];
+ Action = MENU_EXIT;
+ }
+ break;
+
+ }
+
+ if (Action == MENU_DRAW)
+ {
+ if (VarsUi.Counter > 1)
+ {
+ sprintf((char*)VarsUi.DisplayBuffer,"%u",(UWORD)PowerOffTimeSteps[VarsUi.Counter - 1]);
+ }
+ else
+ {
+ sprintf((char*)VarsUi.DisplayBuffer,(char*)cUiGetString(TXT_POWEROFFTIME_NEVER));
+ }
+ pMapDisplay->pTextLines[TEXTLINE_3] = VarsUi.DisplayBuffer;
+
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)VarsUi.CursorTmp;
+ VarsUi.CursorTmp[4] = 46;
+ VarsUi.CursorTmp[5] = 24;
+ pMapDisplay->EraseMask |= (TEXTLINE_BIT(TEXTLINE_3) | TEXTLINE_BIT(TEXTLINE_4));
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(TEXTLINE_3);
+ pMapDisplay->UpdateMask |= (TEXTLINE_BIT(TEXTLINE_3) | BITMAP_BIT(BITMAP_1));
+ }
+ if (Action == MENU_EXIT)
+ {
+ IOMapUi.State = EXIT_PRESSED;
+ }
+
+ return (0);
+}
+
+
+
+//******* cUiBTConnectRequest ************************************************
+
+UBYTE cUiBTConnectRequest(UBYTE Action)
+{
+ switch (Action)
+ {
+ case MENU_INIT :
+ {
+ switch (VarsUi.CRState)
+ {
+ case 0 :
+ {
+ sprintf((char*)pMapSound->SoundFilename,"%s.%s",(char*)UI_ATTENTION_SOUND,(char*)TXT_SOUND_EXT);
+ pMapSound->Volume = IOMapUi.Volume;
+ pMapSound->Mode = SOUND_ONCE;
+ pMapSound->Flags |= SOUND_UPDATE;
+ VarsUi.CRState++;
+ }
+ break;
+
+ case 1 :
+ {
+ if (DISPLAY_IDLE)
+ {
+ pMapDisplay->Flags |= DISPLAY_POPUP;
+ VarsUi.CRState++;
+ }
+ }
+ break;
+
+ case 2 :
+ {
+ strcpy((char*)VarsUi.UserString,(char*)DEFAULT_PIN_CODE);
+ IOMapUi.Flags |= UI_REDRAW_STATUS;
+ VarsUi.CRState++;
+ }
+ break;
+
+ case 3 : // Get pincode and send
+ {
+ if (!cUiGetUserString(0))
+ {
+ if (VarsUi.UserString[0] == 0)
+ {
+ sprintf((char*)VarsUi.UserString,"%08lX",VarsUi.CRPasskey);
+ }
+ pMapComm->pFunc2(VarsUi.UserString);
+ VarsUi.CRState++;
+ }
+ }
+ break;
+
+ case 4 :
+ {
+ if (DISPLAY_IDLE)
+ {
+ pMapDisplay->Flags &= ~DISPLAY_POPUP;
+ VarsUi.CRState = 0;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ }
+
+ return (VarsUi.CRState);
+}
+
+
+
+//******* cUiFilesDelete *****************************************************
+
+UBYTE cUiFilesDelete(UBYTE Action)
+{
+ switch (Action)
+ {
+ case MENU_INIT :
+ {
+ pMapDisplay->pTextLines[TEXTLINE_3] = cUiGetString(TXT_FILESDELETE_DELETING_ALL);
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(TEXTLINE_3);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_3);
+ sprintf((char*)VarsUi.DisplayBuffer,(char*)cUiGetString(TXT_FILESDELETE_S_FILES),(char*)cUiGetString(TXT_FILETYPE[VarsUi.SelectedType]));
+ pMapDisplay->pTextLines[TEXTLINE_4] = VarsUi.DisplayBuffer;
+ pMapDisplay->TextLinesCenterFlags |= TEXTLINE_BIT(TEXTLINE_4);
+ pMapDisplay->UpdateMask |= TEXTLINE_BIT(TEXTLINE_4);
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ break;
+
+ case MENU_DELETE :
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ if (VarsUi.SelectedType < FILETYPES)
+ {
+ sprintf((char*)VarsUi.FilenameBuffer,"*.%s",TXT_FILE_EXT[VarsUi.SelectedType]);
+ }
+ else
+ {
+ sprintf((char*)VarsUi.FilenameBuffer,"*.*");
+ }
+ VarsUi.State++;
+ }
+ break;
+
+ case 1 :
+ {
+ if (SOUND_IDLE == pMapSound->State)
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 2 : // Delete files
+ {
+ VarsUi.TmpHandle = pMapLoader->pFunc(FINDFIRST,VarsUi.FilenameBuffer,VarsUi.SelectedFilename,&VarsUi.TmpLength);
+ if (!(VarsUi.TmpHandle & 0x8000))
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsUi.TmpHandle,NULL,NULL);
+ pMapLoader->pFunc(DELETE,VarsUi.SelectedFilename,NULL,NULL);
+ }
+ else
+ {
+ pMapDisplay->EraseMask |= MENUICON_BITS;
+ pMapDisplay->EraseMask |= SPECIAL_BIT(MENUTEXT);
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ default : // Display Files deleted text
+ {
+ if (!cUiFeedback((BMPMAP*)Info,TXT_FB_FD_FILES_INFO,TXT_FB_FD_DELETED_INFO,DISPLAY_SHOW_TIME))
+ {
+ IOMapUi.State = EXIT_PRESSED;
+ VarsUi.State = 0;
+ }
+ }
+ break;
+
+ }
+ }
+ break;
+
+ default :
+ {
+ if (Action < FILETYPES)
+ {
+ VarsUi.SelectedType = Action;
+ }
+ else
+ {
+ VarsUi.SelectedType = FILETYPE_ALL;
+ }
+ }
+ break;
+
+ }
+
+ return (VarsUi.State);
+}
+
+
+//******* cUiOff *************************************************************
+
+UBYTE cUiOff(UBYTE Action) // Tell AVR to turn off ARM
+{
+ if (Action == MENU_INIT)
+ {
+ switch (VarsUi.State)
+ {
+ case 0 : // Stop VM if running
+ {
+ if (pMapCmd->ProgStatus == PROG_RUNNING)
+ {
+ pMapCmd->DeactivateFlag = TRUE;
+ }
+ VarsUi.State++;
+ }
+ break;
+
+ case 1 : // When VM is stopped -> Display off and close all connections
+ {
+ if (pMapCmd->ProgStatus != PROG_RUNNING)
+ {
+ pMapDisplay->Flags &= ~DISPLAY_ON;
+ VarsUi.BTCommand = (UBYTE)DISCONNECTALL;
+ VarsUi.BTPar1 = (UBYTE)0;
+ VarsUi.BTPar2 = (UBYTE)0;
+ pMapComm->pFunc(VarsUi.BTCommand,VarsUi.BTPar1,VarsUi.BTPar2,0,NULL,&(VarsUi.BTResult));
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 2 : // Send off command to AVR
+ {
+ if (VarsUi.BTResult != INPROGRESS)
+ {
+ pMapIoCtrl->PowerOn = POWERDOWN;
+ VarsUi.Timer = 0;
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 3 : // Wait for power off
+ {
+ if (++VarsUi.Timer >= ARM_WAIT_FOR_POWER_OFF)
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ case 4 : // Vitual off state (if still power) wait for on button
+ {
+ pMapIoCtrl->PowerOn = 0;
+ if (BUTTON_ENTER == cUiReadButtons())
+ {
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ default : // Turn on again
+ {
+ IOMapUi.State = INIT_DISPLAY;
+ VarsUi.State = 0;
+ }
+ break;
+
+ }
+ }
+
+ return (VarsUi.State);
+}
+
+
+
+//******* FUNCTIONS **********************************************************
+
+enum FUNC_NO // Must reffer to entry in Functions
+{ // used in Menus to repressent function
+ FUNC_NO_NOT_USED = 0x00,
+ FUNC_NO_TEST_PROGRAM = 0x01,
+ FUNC_NO_OFF = 0x02,
+ FUNC_NO_BT_ON = 0x03,
+ FUNC_NO_POWER_OFF_TIME = 0x04,
+ FUNC_NO_FILES_DELETE = 0x05,
+ FUNC_NO_FILE_LIST = 0x06,
+ FUNC_NO_VOLUME = 0x07,
+ FUNC_NO_FILE_RUN = 0x08,
+ FUNC_NO_FILE_DELETE = 0x09,
+ FUNC_NO_FREE1 = 0x0A,
+ FUNC_NO_ON_BRICK_PROGRAMMING = 0x0B,
+ FUNC_NO_FREE2 = 0x0C,
+ FUNC_NO_BT_CONNECT_REQUEST = 0x0D,
+ FUNC_NO_VIEW = 0x0E,
+ FUNC_NO_GET_USER_STRING = 0x0F,
+ FUNC_NO_BT_CONNECT = 0x10,
+ FUNC_NO_BT_VISIABILITY = 0x11,
+ FUNC_NO_BT_SEARCH = 0x12,
+ FUNC_NO_BT_DEVICE_LIST = 0x13,
+ FUNC_NO_BT_CONNECT_LIST = 0x14,
+ FUNC_NO_MAX
+};
+
+FUNCTION Functions[] = // Use same index as FUNC_NO
+{
+ 0,
+ TestPrg,
+ cUiOff,
+ cUiBtOn,
+ cUiPowerOffTime,
+ cUiFilesDelete,
+ cUiFileList,
+ cUiVolume,
+ cUiFileRun,
+ cUiFileDelete,
+ 0,
+ cUiOnBrickProgramming,
+ 0,
+ cUiBTConnectRequest,
+ cUiView,
+ cUiGetUserString,
+ cUiBtConnect,
+ cUiBtVisiability,
+ cUiBtSearch,
+ cUiBtDeviceList,
+ cUiBtConnectList
+};
+
+
diff --git a/AT91SAM7S256/Source/Icons.txt b/AT91SAM7S256/Source/Icons.txt
new file mode 100644
index 0000000..34218e2
--- /dev/null
+++ b/AT91SAM7S256/Source/Icons.txt
@@ -0,0 +1,297 @@
+const ICON Icons[] =
+{
+ 0x04,0x00, // Graphics Format
+ 0x1B,0x00, // Graphics DataSize
+ 0x01, // Graphics Count X
+ 0x60, // Graphics Count Y
+ 0x18, // Graphics Width
+ 0x18, // Graphics Height
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xA0,0x50,0xB0,0x50,0xB0,0x50,0xA0,0xC0,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x20,0x10,0x88,0x47,0x2F,0x1F,0x1E,0x1F,0x1E,0x1D,0x0E,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x06,0x09,0x08,0x04,0x02,0x01,0x08,0x14,0x1F,0x00,0x1F,0x15,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xA0,0x50,0xB0,0x50,0xB0,0x50,0xA0,0xC0,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x20,0x10,0x88,0x47,0x2F,0x1F,0x1E,0x1F,0x1E,0x1D,0x0E,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x06,0x09,0x08,0x04,0x02,0x01,0x08,0x14,0x1F,0x00,0x1F,0x15,0x0A,0x00,0x1E,0x09,0x1E,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x40,0x40,0x20,0x20,0x20,0x40,0x40,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x02,0x42,0x20,0x07,0x18,0x60,0x80,0x00,0x00,0x00,0x80,0x60,0x18,0x07,0x00,0x10,0x22,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x15,0x35,0x25,0x35,0x15,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0xC0,0x60,0xA0,0x60,0xC0,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1A,0x75,0xAA,0x55,0xAA,0x55,0xAA,0x75,0x1A,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x15,0x35,0x25,0x35,0x15,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xFE,0x02,0xC3,0xC2,0xC2,0x02,0xC3,0x42,0xC2,0x03,0x02,0x02,0x02,0x03,0x02,0xFE,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x1F,0x1C,0x1D,0x1D,0x1D,0x1C,0x1D,0x1D,0x1D,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
+ 0x00,0x00,0x08,0x04,0x04,0x02,0x09,0x09,0x4C,0x4E,0xCB,0xC8,0xC8,0xC8,0xC8,0x70,0x00,0x00,0xF8,0x04,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x18,0x18,0x30,0x30,0x30,0x34,0x35,0x1D,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x80,0xC0,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xBA,0xC6,0x01,0x11,0x38,0x6C,0x38,0x11,0x01,0xC6,0xBA,0x10,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x02,0x06,0x02,0x01,0x03,0x00,0x00,0x1E,0x12,0x0C,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x80,0xC0,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xBA,0xC6,0x01,0x11,0x38,0x6C,0x38,0x11,0x01,0xC6,0xBA,0x10,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x02,0x06,0x02,0x01,0x03,0x00,0x00,0x1E,0x0A,0x14,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xF8,0x06,0x01,0x01,0x00,0x03,0x01,0x00,0x00,0x01,0x01,0x06,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x04,0x04,0x08,0x08,0x08,0x08,0x08,0x04,0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x20,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xE0,0x3C,0xC3,0x00,0x00,0x00,0xFF,0x10,0x10,0x82,0x6C,0x10,0x01,0xC6,0x38,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x01,0x02,0x04,0x07,0x00,0x00,0x1C,0x00,0x1C,0x05,0x08,0x1C,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x20,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xE0,0x3C,0xC3,0x00,0x00,0x00,0xFF,0x10,0x10,0x82,0x6C,0x10,0x01,0xC6,0x38,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x01,0x02,0x04,0x07,0x00,0x1C,0x14,0x00,0x1C,0x05,0x08,0x04,0x1C,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x08,0xF0,0x00,0x00,0x00,0x00,0x60,0x90,0x90,0x60,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x7F,0x04,0x7F,0x80,0x00,0x00,0x00,0xC0,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x08,0x10,0x10,0x10,0x08,0x07,0x00,0x00,0x03,0x04,0x04,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x08,0xF0,0x00,0x00,0x00,0x00,0x60,0x90,0x90,0x60,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x7F,0x04,0x7F,0x80,0x00,0x00,0x00,0xE0,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x08,0x10,0x10,0x10,0x08,0x07,0x00,0x00,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x9E,0x91,0x51,0x51,0x51,0x91,0x9E,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3C,0x3C,0x3C,0x24,0x25,0x3D,0x25,0x24,0x3C,0x24,0x24,0x3F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x9E,0x91,0x51,0x51,0x51,0x91,0x9E,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x24,0x24,0x3C,0x3C,0x3D,0x3D,0x25,0x24,0x3C,0x24,0x24,0x3F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x9E,0x91,0x51,0x51,0x51,0x91,0x9E,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x24,0x24,0x3C,0x24,0x25,0x3D,0x3D,0x3C,0x3C,0x24,0x24,0x3F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x9E,0x91,0x51,0x51,0x51,0x91,0x9E,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x24,0x24,0x3C,0x24,0x25,0x3D,0x25,0x24,0x3C,0x3C,0x3C,0x3F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x78,0x78,0x78,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x9E,0x91,0x51,0x51,0x51,0x91,0x9E,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x24,0x24,0x3C,0x24,0x25,0x3D,0x25,0x24,0x3C,0x24,0x24,0x3F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x48,0x48,0x78,0x78,0x78,0x78,0x48,0x48,0x78,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x9E,0x91,0x51,0x51,0x51,0x91,0x9E,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x24,0x24,0x3C,0x24,0x25,0x3D,0x25,0x24,0x3C,0x24,0x24,0x3F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x48,0x48,0x78,0x48,0x48,0x78,0x78,0x78,0x78,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x9E,0x91,0x51,0x51,0x51,0x91,0x9E,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x24,0x24,0x3C,0x24,0x25,0x3D,0x25,0x24,0x3C,0x24,0x24,0x3F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xF0,0x10,0xF0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xF0,0x10,0xF0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x1F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x1F,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x08,0x10,0x10,0x10,0x10,0x1F,0x11,0x1D,0x1D,0x11,0x11,0x11,0x1F,0x10,0x10,0x10,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xF0,0x10,0xF0,0x10,0x10,0x10,0x10,0x90,0x90,0x50,0x50,0xD0,0x10,0x10,0x10,0xF0,0x10,0xF0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x1F,0x20,0x20,0x20,0x2C,0x2F,0x20,0x20,0x26,0x27,0x20,0x20,0x20,0x1F,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x08,0x10,0x10,0x10,0x10,0x1F,0x11,0x1D,0x1D,0x11,0x11,0x11,0x1F,0x10,0x10,0x10,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xF0,0x10,0xF0,0x10,0x10,0x10,0xD0,0x50,0x50,0x50,0x50,0xD0,0x10,0x10,0x10,0xF0,0x10,0xF0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x1F,0x20,0x20,0x20,0x2F,0x28,0x23,0x23,0x28,0x2F,0x20,0x20,0x20,0x1F,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x08,0x10,0x10,0x10,0x10,0x1F,0x11,0x1D,0x1D,0x11,0x11,0x11,0x1F,0x10,0x10,0x10,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xF0,0x10,0xF0,0x10,0xD0,0x50,0xD0,0x90,0x50,0x50,0x90,0xD0,0x50,0xD0,0x10,0xF0,0x10,0xF0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x3F,0x40,0x41,0x41,0x41,0x40,0x41,0x41,0x40,0x41,0x41,0x41,0x40,0x3F,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x08,0x10,0x10,0x10,0x10,0x1F,0x11,0x1D,0x1D,0x11,0x11,0x11,0x1F,0x10,0x10,0x10,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xF0,0x10,0xF0,0x10,0x10,0x10,0x90,0x50,0x70,0x50,0x70,0x50,0x90,0x10,0x10,0xF0,0x10,0xF0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x1F,0x20,0x20,0x20,0x2F,0x30,0x25,0x28,0x25,0x30,0x2F,0x20,0x20,0x1F,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x08,0x10,0x10,0x10,0x10,0x1F,0x11,0x1D,0x1D,0x11,0x11,0x11,0x1F,0x10,0x10,0x10,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xF0,0x10,0xF0,0x10,0xD0,0x10,0x90,0x10,0xD0,0x10,0x10,0x10,0x10,0x10,0x10,0xF0,0x10,0xF0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x3F,0x40,0x5F,0x50,0x5F,0x50,0x5F,0x50,0x5C,0x50,0x5F,0x50,0x40,0x3F,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x08,0x10,0x10,0x10,0x10,0x1F,0x11,0x1D,0x1D,0x11,0x11,0x11,0x1F,0x10,0x10,0x10,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0xFD,0x00,0x00,0x00,0x00,0xFD,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x10,0x10,0x10,0x10,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x40,0x80,0x00,0x00,0x00,0x58,0x68,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06,0xFD,0x00,0x00,0x00,0x00,0xFD,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x10,0x10,0x10,0x10,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0xE0,0x00,0x68,0x58,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x60,0x90,0x08,0x04,0x0E,0x08,0x08,0x0F,0x00,0x00,0x00,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x07,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0xE0,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x06,0x09,0x10,0x20,0x70,0x10,0x10,0xF0,0x00,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x04,0x04,0x04,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0xE0,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x68,0x58,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x06,0x09,0x10,0x20,0x70,0x10,0x10,0xF0,0x00,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x04,0x04,0x04,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x0F,0x08,0x08,0x0E,0x04,0x08,0x90,0x60,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x07,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xE0,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x01,0x00,0x00,0x00,0xF0,0x10,0x10,0x70,0x20,0x10,0x09,0x06,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x04,0x04,0x04,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x68,0x58,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xE0,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x01,0x00,0x00,0x00,0xF0,0x10,0x10,0x70,0x20,0x10,0x09,0x06,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x04,0x04,0x04,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x60,0x90,0x08,0x04,0x0E,0x08,0x08,0x0F,0x00,0x00,0x00,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x07,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x40,0x40,0x00,0x00,0x00,0xC0,0x60,0x20,0x20,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x7F,0x00,0x00,0x80,0xC0,0xC0,0xC0,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x40,0x40,0x40,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x05,0x08,0x10,0x10,0x08,0x05,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x40,0x40,0x40,0x40,0xC0,0x00,0x00,0x58,0x68,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x05,0x08,0x10,0x10,0x08,0x05,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x68,0x58,0x00,0xE0,0x20,0x20,0x20,0x20,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x00,0x0F,0x08,0x08,0x0E,0x04,0x08,0x90,0x60,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x07,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x40,0xA0,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x20,0x10,0xA0,0x40,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x82,0x44,0x28,0x11,0x82,0x44,0x82,0x11,0x28,0x44,0x82,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x04,0x0A,0x11,0x08,0x04,0x02,0x01,0x00,0x00,0x00,0x01,0x02,0x04,0x08,0x11,0x0A,0x04,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x10,0x90,0x60,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xC0,0x20,0x20,0x40,0x40,0x80,0x80,0x80,0x60,0x18,0x86,0x61,0x18,0x06,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x18,0x06,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xA8,0xA8,0x54,0x54,0x2A,0x2A,0x00,0x3F,0x21,0x32,0x2C,0x24,0x24,0x24,0x2C,0x32,0x21,0x3F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x60,0x60,0x60,0x40,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x08,0x0F,0x08,0x0F,0x08,0x0F,0x08,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x01,0x01,0x02,0x02,0x04,0x04,0x88,0x88,0x50,0x50,0x20,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x08,0x04,0x04,0x02,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x20,0x50,0x50,0x88,0x88,0x04,0x04,0x02,0x02,0x01,0x01,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x04,0x04,0x08,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xFF,0x01,0x01,0x01,0x01,0x7F,0x40,0x48,0x4C,0x7A,0x01,0x00,0x00,0x01,0xFA,0x0C,0x08,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x03,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x04,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0x80,0x80,0x60,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xF8,0xFE,0x07,0x21,0x21,0x20,0x20,0xE0,0x00,0x00,0x01,0x01,0x07,0xFE,0xF9,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0C,0x0C,0x18,0x18,0x1B,0x18,0x18,0x0C,0x0C,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x80,0x00,0x20,0xC0,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x78,0x48,0x48,0x84,0x02,0x01,0xFF,0x00,0x00,0x86,0x78,0x01,0x86,0x78,0x01,0x86,0x78,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x07,0x00,0x00,0x01,0x00,0x06,0x01,0x10,0x0E,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0xE0,0xE0,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x78,0xFE,0x87,0x01,0x01,0x00,0x07,0x07,0x00,0x01,0x01,0x87,0xFE,0x78,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x06,0x06,0x0C,0x0C,0x0C,0x0C,0x06,0x06,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xF8,0x08,0xF8,0x48,0xC8,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x78,0x48,0xF8,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x02,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x02,0xFF,0x02,0xFE,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x01,0x07,0x08,0x3F,0x40,0x80,0x81,0xF9,0x89,0xE9,0x89,0x89,0x89,0xF9,0x81,0x80,0x80,0x7F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0x20,0x20,0x20,0xE0,0x80,0x80,0xE0,0x20,0x20,0x20,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x03,0x00,0x00,0x03,0x02,0x82,0xCA,0xFB,0x78,0x78,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x7C,0x44,0x44,0x44,0x7C,0x00,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xC0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xC0,0x80,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x92,0x00,0xFF,0x80,0xFE,0x80,0x80,0xFC,0x80,0xF0,0x80,0xFF,0x80,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x0F,0x18,0x18,0x18,0x1A,0x18,0x18,0x1A,0x18,0x18,0x1A,0x18,0x18,0x1A,0x18,0x18,0x1F,0x1F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x30,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x80,0xC0,0xA0,0x90,0x08,0x08,0x90,0xA0,0xC0,0x80,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x01,0x03,0x02,0x02,0x02,0x02,0x02,0x1F,0x10,0x10,0x1F,0x02,0x02,0x02,0x02,0x02,0x03,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xFE,0xFF,0xFF,0xE3,0xE1,0xE0,0xF0,0x78,0x38,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x1C,0x1E,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0xE0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xFE,0x01,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x0F,0x10,0x20,0x20,0x20,0x22,0x24,0x24,0x24,0x24,0x22,0x20,0x20,0x20,0x10,0x0F,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xF8,0x06,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x03,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x08,0x08,0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x20,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xE0,0x3C,0xC3,0x00,0x00,0x00,0xFF,0x10,0x10,0x82,0x6C,0x10,0x01,0xC6,0x38,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x01,0x02,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xA0,0x50,0xB0,0x50,0xB0,0x50,0xA0,0xC0,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x20,0x10,0x88,0x47,0x2F,0x1F,0x1F,0x1F,0x1E,0x1F,0x0E,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x06,0x09,0x08,0x04,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
+ 0x00,0x00,0x08,0x04,0x04,0x02,0x09,0x09,0x4C,0x4E,0xCB,0xC8,0xC8,0xC8,0xC8,0x70,0x00,0x00,0xF8,0x04,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x18,0x18,0x30,0x30,0x30,0x34,0x35,0x1D,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x38,0xC8,0x08,0x08,0x08,0x08,0xA8,0x68,0x08,0x08,0x08,0x08,0xC8,0x38,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x42,0x24,0x98,0x85,0x85,0x98,0x24,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x1C,0x13,0x14,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x14,0x13,0x1C,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x38,0xC8,0x08,0x08,0x08,0x08,0x68,0xA8,0x08,0x08,0x08,0x08,0xC8,0x38,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x42,0x24,0x18,0x05,0x05,0x18,0x24,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x1C,0x13,0x14,0x16,0x17,0x17,0x17,0x17,0x17,0x17,0x16,0x14,0x13,0x1C,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x38,0xC8,0x08,0x08,0x48,0xE8,0x08,0xC8,0x28,0xC8,0x08,0x08,0xC8,0x38,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x42,0x24,0x19,0x04,0x04,0x19,0x24,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x1C,0x13,0x18,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x18,0x13,0x1C,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xF8,0x06,0xF9,0x56,0xAA,0x55,0xAB,0x55,0xAB,0x55,0xAA,0x56,0xF9,0x06,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x03,0x04,0x0B,0x0A,0x15,0x16,0x15,0x16,0x15,0x0A,0x0B,0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x5C,0x74,0x00,0x04,0x7C,0x04,0x00,0x38,0x44,0x38,0x00,0x7C,0x14,0x08,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x04,0x02,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x40,0x40,0x60,0xFC,0xF8,0xF0,0x60,0x00,0x00,0x40,0x40,0x80,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x81,0x7E,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x03,0x04,0x04,0x00,0x00,0x0C,0x1E,0x3F,0x7F,0x04,0x04,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0x78,0x48,0x48,0xF8,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x9E,0x91,0x51,0x51,0x51,0x91,0x9E,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x24,0x24,0x24,0x3C,0x25,0x25,0x25,0x3C,0x24,0x24,0x24,0x3F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,0x30,0x10,0x10,0x90,0x10,0x10,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x82,0x44,0x28,0xFF,0x11,0xAA,0x44,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x03,0x06,0x0C,0x18,0x10,0x10,0x13,0x11,0x10,0x18,0x0C,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x40,0xC0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0x00,0x55,0x00,0x55,0x55,0x55,0x00,0x55,0xFF,0x00,0x01,0x00,0x01,0x01,0x01,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x0F,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x12,0x15,0x17,0x12,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x04,0x04,0x02,0x42,0xC6,0x88,0x10,0x60,0xC0,0x01,0x81,0x81,0x81,0x00,0x00,
+ 0x00,0x00,0x01,0x01,0x01,0x02,0x04,0x08,0x0A,0x0C,0x09,0x0B,0x0E,0x0C,0x05,0x07,0x02,0x03,0x01,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,0xE2,0xB2,0xF6,0xF6,0x76,0x2C,0x6C,0xDC,0x9C,0x38,0x30,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x04,0x05,0x05,0x05,0x04,0x02,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0xE0,0xE0,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x78,0x86,0x01,0x00,0x88,0x50,0xFD,0xA9,0x50,0x00,0x00,0x01,0x86,0x78,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x04,0x04,0x08,0x09,0x08,0x08,0x04,0x04,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xC0,0xE0,0x70,0x38,0x98,0x18,0xD8,0x98,0x18,0x38,0x70,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x1F,0x3F,0x70,0xE0,0xC8,0xC5,0xDF,0xCA,0xC5,0x60,0x70,0xFF,0xCF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x18,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x82,0x44,0x28,0xFF,0x11,0xAA,0x44,0x00,0x00,0x06,0x01,0x00,0x40,0x20,0x11,0x0E,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x82,0x44,0x28,0xFF,0x11,0xAA,0x44,0x00,0x00,0x00,0x00,0x01,0x82,0x44,0x28,0x10,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x83,0xC6,0x6C,0xFF,0x39,0xBA,0x6C,0xC6,0x83,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x03,0x01,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,0xE2,0xB2,0xF6,0xF6,0x76,0x2C,0x6C,0xDC,0x9C,0x38,0x30,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x04,0x05,0x05,0x05,0x04,0x02,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xC0,0xE0,0x80,0x00,0x02,0x02,0x06,0x06,0x06,0x0C,0x0C,0x9C,0xDC,0xB8,0x30,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x02,0x02,0x02,0x02,0x02,0x03,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0xE0,0xE0,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x78,0x86,0x01,0x00,0x88,0x50,0xFD,0xA9,0x50,0x00,0x00,0x01,0x86,0x78,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x04,0x04,0x08,0x09,0x08,0x08,0x04,0x04,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x80,0x40,0x20,0x10,0x20,0x40,0x80,0xE0,0xE0,0x00,0x80,0x40,0x20,0x10,0x20,0x40,0x80,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x79,0x86,0x44,0x28,0x10,0x00,0x01,0x83,0x01,0x00,0x10,0x28,0x44,0xFA,0x01,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x05,0x08,0x10,0x08,0x04,0x0A,0x09,0x08,0x09,0x06,0x04,0x08,0x10,0x08,0x05,0x02,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/Info.txt b/AT91SAM7S256/Source/Info.txt
new file mode 100644
index 0000000..d56d7e2
--- /dev/null
+++ b/AT91SAM7S256/Source/Info.txt
@@ -0,0 +1,12 @@
+const BMPMAP Info[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0x48, // Graphics DataSize
+ 0x00, // Graphics Start X
+ 0x08, // Graphics Start Y
+ 0x18, // Graphics Width
+ 0x18, // Graphics Height
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xA0,0x90,0x20,0x20,0x40,0x40,0x30,0x8C,0x73,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/LowBattery.txt b/AT91SAM7S256/Source/LowBattery.txt
new file mode 100644
index 0000000..e5a0769
--- /dev/null
+++ b/AT91SAM7S256/Source/LowBattery.txt
@@ -0,0 +1,16 @@
+const BMPMAP LowBattery[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x02,0xA0, // Graphics DataSize
+ 0x02, // Graphics Start X
+ 0x08, // Graphics Start Y
+ 0x60, // Graphics Width
+ 0x38, // Graphics Height
+ 0x02,0xF2,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xF2,0x82,0x02,
+ 0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x20,0x18,0x04,0x02,0x02,0x01,0x01,0x01,0x00,0xF0,0xF8,0xFC,0xFC,0xF8,0xF0,0x00,0x01,0x01,0x01,0x02,0x02,0x04,0x18,0x20,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,
+ 0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x7F,0xFF,0xFF,0x7F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,
+ 0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0E,0x10,0x60,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xF0,0xF0,0xF0,0xF0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x10,0x0E,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,
+ 0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0xE0,0x10,0x10,0x10,0xE0,0x00,0xF0,0x00,0xC0,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0xF2,0x92,0x92,0x94,0x64,0x04,0xE4,0x14,0x14,0x14,0xE4,0x02,0x12,0x12,0xF1,0x11,0x10,0x00,0x10,0x10,0xF0,0x10,0x10,0x00,0xF0,0x90,0x90,0x90,0x10,0x00,0xF0,0x90,0x90,0x90,0x60,0x00,0x70,0x80,0x00,0x80,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,
+ 0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x04,0x04,0x04,0x04,0x00,0x03,0x04,0x04,0x04,0x03,0x00,0x03,0x04,0x03,0x04,0x03,0x00,0x00,0x00,0x00,0xC0,0x40,0xF0,0x17,0x14,0x14,0x14,0x13,0x10,0x17,0x11,0x11,0x11,0x17,0x10,0x10,0xD0,0xD7,0x10,0xF0,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x04,0x04,0x04,0x04,0x00,0x07,0x00,0x00,0x01,0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,
+ 0x00,0x3F,0x20,0x20,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x63,0x62,0x6F,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x6B,0x6B,0x68,0x6F,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x7F,0x00
+};
diff --git a/AT91SAM7S256/Source/Mainmenu.rms b/AT91SAM7S256/Source/Mainmenu.rms
new file mode 100644
index 0000000..f26e744
--- /dev/null
+++ b/AT91SAM7S256/Source/Mainmenu.rms
@@ -0,0 +1,65 @@
+const UBYTE MAINMENU[] =
+{
+ 0x07,0x00, // Menu Format
+ 0x00,0xE8, // Menu DataSize
+ 0x1D, // Menu item size
+ 0x08, // Menu items
+ 0x18, // Menu icon Width
+ 0x18, // Menu icon Height
+
+ // Turn_off?
+ 0x00,0x00,0x00,0x01, // 0x00000001
+ 0x10,0x20,0x04,0x01, // 0x10200401
+ 0x02,0x00,0x00,0x01, // 2 ,0 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x6F,0x66,0x66,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x31, // 31
+
+ // Turn_off?
+ 0x00,0x00,0x00,0x02, // 0x00000002
+ 0x10,0x20,0x00,0x01, // 0x10200001
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x6F,0x66,0x66,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x30, // 30
+
+ // My_Files
+ 0x00,0x00,0x00,0x11, // 0x00000011
+ 0x01,0x04,0x00,0x00, // 0x01040000
+ 0x00,0x00,0x01,0x01, // 0 ,0 ,1 ,1
+ 0x4D,0x79,0x20,0x46,0x69,0x6C,0x65,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x3B, // 3B
+
+ // NXT_Program
+ 0x00,0x00,0x00,0x21, // 0x00000021
+ 0x01,0x04,0x00,0x00, // 0x01040000
+ 0x00,0x00,0x02,0x01, // 0 ,0 ,2 ,1
+ 0x4E,0x58,0x54,0x20,0x50,0x72,0x6F,0x67,0x72,0x61,0x6D,0x00,0x00,0x00,0x00,0x00,
+ 0x3C, // 3C
+
+ // View
+ 0x00,0x00,0x00,0x31, // 0x00000031
+ 0x01,0x04,0x00,0x00, // 0x01040000
+ 0x00,0x00,0x04,0x01, // 0 ,0 ,4 ,1
+ 0x56,0x69,0x65,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x3E, // 3E
+
+ // Bluetooth
+ 0x00,0x00,0x00,0x41, // 0x00000041
+ 0x01,0x04,0x00,0x00, // 0x01040000
+ 0x00,0x00,0x07,0x02, // 0 ,0 ,7 ,2
+ 0x42,0x6C,0x75,0x65,0x74,0x6F,0x6F,0x74,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x51, // 51
+
+ // Settings
+ 0x00,0x00,0x00,0x51, // 0x00000051
+ 0x01,0x04,0x00,0x00, // 0x01040000
+ 0x00,0x00,0x05,0x01, // 0 ,0 ,5 ,1
+ 0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x3F, // 3F
+
+ // Try_Me
+ 0x00,0x00,0x00,0x61, // 0x00000061
+ 0x01,0x04,0x00,0x00, // 0x01040000
+ 0x00,0x00,0x06,0x01, // 0 ,0 ,6 ,1
+ 0x54,0x72,0x79,0x20,0x4D,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40, // 40
+};
diff --git a/AT91SAM7S256/Source/Ok.txt b/AT91SAM7S256/Source/Ok.txt
new file mode 100644
index 0000000..3a4b186
--- /dev/null
+++ b/AT91SAM7S256/Source/Ok.txt
@@ -0,0 +1,11 @@
+const BMPMAP Ok[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0x20, // Graphics DataSize
+ 0x2A, // Graphics Start X
+ 0x30, // Graphics Start Y
+ 0x10, // Graphics Width
+ 0x10, // Graphics Height
+ 0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x38,0xC4,0x34,0x08,0x00,0xFF,
+ 0xFF,0x04,0x0A,0x19,0x12,0x22,0x24,0x24,0x23,0x18,0x07,0x00,0x00,0x00,0x00,0xFF
+};
diff --git a/AT91SAM7S256/Source/Port.txt b/AT91SAM7S256/Source/Port.txt
new file mode 100644
index 0000000..9367003
--- /dev/null
+++ b/AT91SAM7S256/Source/Port.txt
@@ -0,0 +1,10 @@
+const ICON Port[] =
+{
+ 0x04,0x00, // Graphics Format
+ 0x00,0x18, // Graphics DataSize
+ 0x08, // Graphics Count X
+ 0x01, // Graphics Count Y
+ 0x03, // Graphics Width
+ 0x08, // Graphics Height
+ 0x70,0x88,0x70,0x90,0xF8,0x80,0xC8,0xA8,0x90,0x88,0xA8,0x50,0x38,0x20,0xF8,0xF0,0x28,0xF0,0xF8,0xA8,0x50,0x70,0x88,0x50
+};
diff --git a/AT91SAM7S256/Source/RCXintro_1.txt b/AT91SAM7S256/Source/RCXintro_1.txt
new file mode 100644
index 0000000..5ae955c
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_1.txt
@@ -0,0 +1,17 @@
+const BMPMAP RCXintro_1[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x02,0x00, // Graphics DataSize
+ 0x10, // Graphics Start X
+ 0x00, // Graphics Start Y
+ 0x40, // Graphics Width
+ 0x40, // Graphics Height
+ 0xFF,0x01,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0x01,0xFF,
+ 0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x1F,0x8F,0xC7,0xE7,0x67,0x33,0x33,0x33,0x67,0xE7,0x8F,0xCF,0xE7,0x67,0x63,0x33,0x33,0x33,0x33,0x33,0x27,0x67,0xCF,0xCF,0xE7,0x67,0x63,0x33,0x33,0x33,0x33,0x33,0x63,0x67,0xC7,0x8F,0x8F,0xCF,0x67,0x67,0x23,0x33,0x33,0x33,0x33,0x63,0x67,0xC7,0x8F,0x1F,0x33,0xF3,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0xFF,0x7F,0x0F,0x83,0xE0,0x78,0x1E,0x07,0x01,0x00,0x00,0x80,0xE0,0xF8,0x7E,0x1F,0x07,0x01,0x00,0x00,0x00,0x18,0x18,0x18,0xF8,0xF8,0x1C,0x06,0x03,0x00,0x00,0xC0,0x70,0x3C,0x3C,0x30,0x20,0x20,0xE0,0xF0,0x3D,0x0F,0x03,0x00,0x00,0xC0,0xF0,0xFC,0x3C,0x00,0x00,0x00,0x00,0xC0,0xFF,0x1E,0x00,0xC0,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0x01,0x00,0xFC,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x0E,0x0F,0xFF,0xC7,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x0E,0xFE,0xC7,0x80,0x00,0x00,0x00,0x00,0x1F,0x1F,0x0E,0x00,0x00,0x80,0xC0,0xF0,0xFF,0x83,0x00,0x00,0x00,0x1C,0x1F,0x0F,0x03,0x00,0x80,0xC0,0xE0,0x78,0x1E,0x87,0xC1,0xF0,0xFE,0xFF,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0xFE,0xFC,0xF8,0xF3,0xF3,0xE6,0xE6,0xE6,0xE6,0xE6,0xF2,0xF3,0xF9,0xF9,0xF3,0xF6,0xE6,0xE6,0xE6,0xE6,0xE6,0xF3,0xF3,0xF9,0xF9,0xF3,0xF3,0xE6,0xE6,0xE6,0xE6,0xE6,0xE6,0xF3,0xF3,0xF9,0xFC,0xFC,0xF9,0xF3,0xF3,0xE6,0xE6,0xE6,0xE6,0xE6,0xE6,0xF3,0xF3,0xF9,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,
+ 0xFF,0x80,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0x80,0xFF
+};
diff --git a/AT91SAM7S256/Source/RCXintro_10.txt b/AT91SAM7S256/Source/RCXintro_10.txt
new file mode 100644
index 0000000..e5349cc
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_10.txt
@@ -0,0 +1,11 @@
+const BMPMAP RCXintro_10[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0x20, // Graphics DataSize
+ 0x38, // Graphics Start X
+ 0x20, // Graphics Start Y
+ 0x0A, // Graphics Width
+ 0x10, // Graphics Height
+ 0xFE,0xFE,0x06,0x06,0x66,0x66,0x06,0x06,0xFE,0xFE,
+ 0x07,0x07,0x06,0x06,0x00,0x00,0x06,0x06,0x07,0x07
+};
diff --git a/AT91SAM7S256/Source/RCXintro_11.txt b/AT91SAM7S256/Source/RCXintro_11.txt
new file mode 100644
index 0000000..a8891b5
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_11.txt
@@ -0,0 +1,11 @@
+const BMPMAP RCXintro_11[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0x10, // Graphics DataSize
+ 0x3A, // Graphics Start X
+ 0x20, // Graphics Start Y
+ 0x08, // Graphics Width
+ 0x10, // Graphics Height
+ 0xF8,0xF8,0x18,0xD8,0xD8,0x18,0xF8,0xF8,
+ 0x07,0x07,0x06,0x00,0x00,0x06,0x07,0x07
+};
diff --git a/AT91SAM7S256/Source/RCXintro_12.txt b/AT91SAM7S256/Source/RCXintro_12.txt
new file mode 100644
index 0000000..386beb2
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_12.txt
@@ -0,0 +1,11 @@
+const BMPMAP RCXintro_12[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0xC0, // Graphics DataSize
+ 0x03, // Graphics Start X
+ 0x20, // Graphics Start Y
+ 0x5E, // Graphics Width
+ 0x10, // Graphics Height
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x18,0xD8,0xD8,0x18,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x06,0x06,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x06,0x00,0x00,0x06,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x06,0x06,0x00,0x00,0x00,0x07,0x07
+};
diff --git a/AT91SAM7S256/Source/RCXintro_13.txt b/AT91SAM7S256/Source/RCXintro_13.txt
new file mode 100644
index 0000000..84b1753
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_13.txt
@@ -0,0 +1,11 @@
+const BMPMAP RCXintro_13[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0xC0, // Graphics DataSize
+ 0x03, // Graphics Start X
+ 0x20, // Graphics Start Y
+ 0x5E, // Graphics Width
+ 0x10, // Graphics Height
+ 0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x18,0xD8,0xD8,0x18,0xF8,0xF8,0x00,0x00,0xE0,0xE0,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0xE0,0xE0,0x00,0x00,0x00,0xC0,0xC0,
+ 0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x06,0x06,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x06,0x00,0x00,0x06,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x06,0x06,0x00,0x00,0x00,0x07,0x07
+};
diff --git a/AT91SAM7S256/Source/RCXintro_14.txt b/AT91SAM7S256/Source/RCXintro_14.txt
new file mode 100644
index 0000000..dc4254a
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_14.txt
@@ -0,0 +1,11 @@
+const BMPMAP RCXintro_14[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0xC0, // Graphics DataSize
+ 0x03, // Graphics Start X
+ 0x20, // Graphics Start Y
+ 0x5E, // Graphics Width
+ 0x10, // Graphics Height
+ 0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0x00,0x00,0xFE,0xFE,0x00,0x00,0xF8,0xF8,0x00,0x00,0x00,0xD8,0xD8,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x18,0xD8,0xD8,0x18,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0x00,0x00,0x38,0x38,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0x00,0xD8,0xD8,
+ 0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x06,0x06,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x06,0x00,0x00,0x06,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x06,0x06,0x00,0x00,0x00,0x07,0x07
+};
diff --git a/AT91SAM7S256/Source/RCXintro_15.txt b/AT91SAM7S256/Source/RCXintro_15.txt
new file mode 100644
index 0000000..ae03d45
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_15.txt
@@ -0,0 +1,11 @@
+const BMPMAP RCXintro_15[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0xC0, // Graphics DataSize
+ 0x03, // Graphics Start X
+ 0x20, // Graphics Start Y
+ 0x5E, // Graphics Width
+ 0x10, // Graphics Height
+ 0xF8,0xF8,0x18,0x00,0xF8,0xF8,0x18,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x18,0x18,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x18,0x18,0x00,0x00,0xFE,0xFE,0x00,0x00,0xF8,0xF8,0x18,0x00,0xC0,0xD8,0xD8,0x00,0x00,0x18,0x18,0x00,0xF8,0xF8,0x18,0x00,0x00,0x00,0x00,0xF8,0xF8,0x18,0xD8,0xD8,0x18,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x18,0x00,0x00,0x18,0x38,0x38,0x00,0x00,0xF8,0xF8,0x18,0x00,0xF8,0xF8,0x18,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x18,0x00,0xC0,0xD8,0xD8,
+ 0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x06,0x06,0x07,0x07,0x00,0x00,0x06,0x06,0x06,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x06,0x00,0x00,0x06,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x06,0x06,0x06,0x00,0x00,0x07,0x07
+};
diff --git a/AT91SAM7S256/Source/RCXintro_16.txt b/AT91SAM7S256/Source/RCXintro_16.txt
new file mode 100644
index 0000000..47504a8
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_16.txt
@@ -0,0 +1,11 @@
+const BMPMAP RCXintro_16[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0xC0, // Graphics DataSize
+ 0x03, // Graphics Start X
+ 0x20, // Graphics Start Y
+ 0x5E, // Graphics Width
+ 0x10, // Graphics Height
+ 0xF8,0xF8,0x18,0x18,0xF8,0xF8,0x18,0x18,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x18,0x18,0x18,0x18,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x18,0x18,0x18,0x18,0xFE,0xFE,0x00,0x00,0xF8,0xF8,0xD8,0xD8,0xD8,0xD8,0xD8,0x00,0x00,0x18,0x18,0x18,0xF8,0xF8,0x18,0x18,0x18,0x00,0x00,0xF8,0xF8,0x18,0xD8,0xD8,0x18,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0x18,0x18,0x18,0x18,0x38,0x38,0x00,0x00,0xF8,0xF8,0x18,0x18,0xF8,0xF8,0x18,0x18,0xF8,0xF8,0x00,0x00,0xF8,0xF8,0xD8,0xD8,0xD8,0xD8,0xD8,
+ 0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x06,0x06,0x06,0x06,0x07,0x07,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x06,0x00,0x00,0x06,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x07,0x07
+};
diff --git a/AT91SAM7S256/Source/RCXintro_2.txt b/AT91SAM7S256/Source/RCXintro_2.txt
new file mode 100644
index 0000000..42698ea
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_2.txt
@@ -0,0 +1,17 @@
+const BMPMAP RCXintro_2[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x02,0x00, // Graphics DataSize
+ 0x10, // Graphics Start X
+ 0x00, // Graphics Start Y
+ 0x40, // Graphics Width
+ 0x40, // Graphics Height
+ 0xFC,0x02,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0x02,0xFC,
+ 0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x1F,0x8F,0xC7,0xE7,0x67,0x30,0x30,0x30,0x60,0xE0,0x80,0xC0,0xE0,0x60,0x60,0x30,0x30,0x30,0x30,0x30,0x20,0x60,0xC0,0xC0,0xE0,0x60,0x60,0x30,0x30,0x30,0x30,0x30,0x60,0x60,0xC0,0x80,0x80,0xC0,0x60,0x60,0x20,0x33,0x33,0x33,0x33,0x63,0x67,0xC7,0x8F,0x1F,0x33,0xF3,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0xFF,0x7F,0x0F,0x83,0xE0,0x78,0x1E,0x07,0x01,0x00,0x00,0x80,0xE0,0xF8,0x7E,0x1F,0x07,0x01,0x00,0x00,0x00,0x18,0x18,0x18,0xF8,0xF8,0x1C,0x06,0x03,0x00,0x00,0xC0,0x70,0x3C,0x3C,0x30,0x20,0x20,0xE0,0xF0,0x3D,0x0F,0x03,0x00,0x00,0xC0,0xF0,0xFC,0x3C,0x00,0x00,0x00,0x00,0xC0,0xFF,0x1E,0x00,0xC0,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0x01,0x00,0xFC,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x0E,0x0F,0xFF,0xC7,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x0E,0xFE,0xC7,0x80,0x00,0x00,0x00,0x00,0x1F,0x1F,0x0E,0x00,0x00,0x80,0xC0,0xF0,0xFF,0x83,0x00,0x00,0x00,0x1C,0x1F,0x0F,0x03,0x00,0x80,0xC0,0xE0,0x78,0x1E,0xC7,0xE1,0xF8,0xFF,0xFF,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0xFE,0xFE,0xFC,0xF3,0xF3,0xE6,0xE6,0xE6,0xE6,0xE6,0xF2,0x83,0x01,0x01,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x01,0x01,0x03,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x01,0x00,0x00,0x01,0x03,0x03,0x06,0x06,0x06,0x06,0x06,0x86,0xF3,0xFB,0xF9,0xFC,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,
+ 0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,
+ 0x3F,0x40,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0x40,0x3F
+};
diff --git a/AT91SAM7S256/Source/RCXintro_3.txt b/AT91SAM7S256/Source/RCXintro_3.txt
new file mode 100644
index 0000000..308de3a
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_3.txt
@@ -0,0 +1,17 @@
+const BMPMAP RCXintro_3[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x02,0x00, // Graphics DataSize
+ 0x10, // Graphics Start X
+ 0x00, // Graphics Start Y
+ 0x40, // Graphics Width
+ 0x40, // Graphics Height
+ 0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x1F,0x07,0x07,0xC3,0xF1,0x79,0x1F,0x00,0x00,0x00,0x00,0xF8,0x7E,0x07,0x03,0x19,0x18,0xF8,0xFC,0xFC,0xFC,0xFF,0xFF,0xFF,0xFF,0xFD,0xFD,0xFC,0xF8,0x31,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x07,0x81,0xE0,0x3C,0x01,0x01,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x80,0x80,0x80,0x80,0x8F,0xDF,0x70,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x80,0x80,0xCE,0xCE,0x5F,0x7F,0xFF,0xFF,0xBF,0xBF,0x3F,0x3F,0x3F,0x3F,0xBF,0xDF,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x63,0xC0,0x80,0xC6,0xE3,0xC0,0xE0,0xF8,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F
+};
diff --git a/AT91SAM7S256/Source/RCXintro_4.txt b/AT91SAM7S256/Source/RCXintro_4.txt
new file mode 100644
index 0000000..cf969c2
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_4.txt
@@ -0,0 +1,17 @@
+const BMPMAP RCXintro_4[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x02,0x00, // Graphics DataSize
+ 0x10, // Graphics Start X
+ 0x00, // Graphics Start Y
+ 0x40, // Graphics Width
+ 0x40, // Graphics Height
+ 0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F
+};
diff --git a/AT91SAM7S256/Source/RCXintro_5.txt b/AT91SAM7S256/Source/RCXintro_5.txt
new file mode 100644
index 0000000..f5bdbd3
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_5.txt
@@ -0,0 +1,17 @@
+const BMPMAP RCXintro_5[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x01,0xC0, // Graphics DataSize
+ 0x17, // Graphics Start X
+ 0x00, // Graphics Start Y
+ 0x34, // Graphics Width
+ 0x40, // Graphics Height
+ 0x80,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
+ 0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/RCXintro_6.txt b/AT91SAM7S256/Source/RCXintro_6.txt
new file mode 100644
index 0000000..103a310
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_6.txt
@@ -0,0 +1,15 @@
+const BMPMAP RCXintro_6[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x01,0x20, // Graphics DataSize
+ 0x1C, // Graphics Start X
+ 0x08, // Graphics Start Y
+ 0x2C, // Graphics Width
+ 0x30, // Graphics Height
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x03,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x07,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x07
+};
diff --git a/AT91SAM7S256/Source/RCXintro_7.txt b/AT91SAM7S256/Source/RCXintro_7.txt
new file mode 100644
index 0000000..2451fe4
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_7.txt
@@ -0,0 +1,14 @@
+const BMPMAP RCXintro_7[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0xC8, // Graphics DataSize
+ 0x23, // Graphics Start X
+ 0x10, // Graphics Start Y
+ 0x22, // Graphics Width
+ 0x28, // Graphics Height
+ 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x0F,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01
+};
diff --git a/AT91SAM7S256/Source/RCXintro_8.txt b/AT91SAM7S256/Source/RCXintro_8.txt
new file mode 100644
index 0000000..51107b0
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_8.txt
@@ -0,0 +1,12 @@
+const BMPMAP RCXintro_8[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0x48, // Graphics DataSize
+ 0x2C, // Graphics Start X
+ 0x18, // Graphics Start Y
+ 0x16, // Graphics Width
+ 0x18, // Graphics Height
+ 0xFE,0xFF,0xFF,0xFF,0x1F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x1F,0xFF,0xFF,0xFF,0xFE,
+ 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x1E,0x1E,0x1E,0x1E,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
+ 0x1F,0x3F,0x3F,0x3F,0x3E,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x3E,0x3F,0x3F,0x3F,0x1F
+};
diff --git a/AT91SAM7S256/Source/RCXintro_9.txt b/AT91SAM7S256/Source/RCXintro_9.txt
new file mode 100644
index 0000000..479704c
--- /dev/null
+++ b/AT91SAM7S256/Source/RCXintro_9.txt
@@ -0,0 +1,12 @@
+const BMPMAP RCXintro_9[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0x30, // Graphics DataSize
+ 0x34, // Graphics Start X
+ 0x18, // Graphics Start Y
+ 0x0E, // Graphics Width
+ 0x18, // Graphics Height
+ 0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
+ 0xFF,0xFF,0xFF,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0xFF,0xFF,0xFF,
+ 0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07
+};
diff --git a/AT91SAM7S256/Source/Running.txt b/AT91SAM7S256/Source/Running.txt
new file mode 100644
index 0000000..963e372
--- /dev/null
+++ b/AT91SAM7S256/Source/Running.txt
@@ -0,0 +1,57 @@
+const ICON Running[] =
+{
+ 0x04,0x00, // Graphics Format
+ 0x04,0x80, // Graphics DataSize
+ 0x01, // Graphics Count X
+ 0x10, // Graphics Count Y
+ 0x18, // Graphics Width
+ 0x18, // Graphics Height
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x06,0x0E,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xC3,0xC3,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x60,0x70,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x80,0x80,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0x70,0x60,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xC3,0xC3,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1C,0x0E,0x06,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x01,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xE0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0xF0,0xE0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x1C,0x0F,0x07,0x00,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/Status.txt b/AT91SAM7S256/Source/Status.txt
new file mode 100644
index 0000000..7434a7a
--- /dev/null
+++ b/AT91SAM7S256/Source/Status.txt
@@ -0,0 +1,15 @@
+const ICON Status[] =
+{
+ 0x04,0x00, // Graphics Format
+ 0x01,0xB0, // Graphics DataSize
+ 0x06, // Graphics Count X
+ 0x06, // Graphics Count Y
+ 0x0C, // Graphics Width
+ 0x08, // Graphics Height
+ 0x00,0x00,0x7E,0x81,0x81,0x19,0x19,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,0x7E,0x01,0x01,0x99,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,0x1E,0x81,0x81,0x99,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,0x66,0x81,0x81,0x99,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,0x78,0x81,0x81,0x99,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,0x7E,0x80,0x80,0x99,0x99,0x81,0x81,0x7E,0x00,0x00,
+ 0x00,0x00,0x7E,0x81,0x81,0x98,0x98,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,0x7E,0x81,0x81,0x99,0x99,0x80,0x80,0x7E,0x00,0x00,0x00,0x00,0x7E,0x81,0x81,0x99,0x99,0x81,0x81,0x78,0x00,0x00,0x00,0x00,0x7E,0x81,0x81,0x99,0x99,0x81,0x81,0x66,0x00,0x00,0x00,0x00,0x7E,0x81,0x81,0x99,0x99,0x81,0x81,0x1E,0x00,0x00,0x00,0x00,0x7E,0x81,0x81,0x99,0x99,0x01,0x01,0x7E,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x24,0x24,0x24,0x24,0x24,0x3C,0x3C,0x00,0x00,0x00,0x00,0x18,0x24,0x24,0x24,0x24,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x18,0x24,0x24,0x3C,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x24,0x24,0x24,0x24,0x24,0x3C,0x3C,0x00,0x00,0x00,0x00,0x18,0x24,0x24,0x24,0x24,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x18,0x24,0x24,0x3C,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x22,0x14,0x7F,0x2A,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x14,0x7F,0x2A,0x14,0x00,0x08,0x14,0x22,0x00,0x00,0x00,0x22,0x14,0x7F,0x2A,0x14,0x00,0x00,0x00,0x22,0x14,0x08,0x00,0x22,0x14,0x7F,0x2A,0x14,0x00,0x08,0x14,0x22,0x14,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x22,0x1C,0x00,0x3E,0x0A,0x02,0x00,0x3E,0x20,0x3E,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x14,0x1C,0x08,0x08,0x08,0x08,0x08,0x1C,0x14,0x14,0x00,0x3E,0x20,0x3E,0x00,0x2E,0x2A,0x3A,0x00,0x3E,0x2A,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/Step.txt b/AT91SAM7S256/Source/Step.txt
new file mode 100644
index 0000000..dcec616
--- /dev/null
+++ b/AT91SAM7S256/Source/Step.txt
@@ -0,0 +1,17 @@
+const ICON Step[] =
+{
+ 0x04,0x00, // Graphics Format
+ 0x02,0xC0, // Graphics DataSize
+ 0x08, // Graphics Count X
+ 0x04, // Graphics Count Y
+ 0x0B, // Graphics Width
+ 0x10, // Graphics Height
+ 0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x11,0x19,0x7D,0x19,0x11,0x01,0x01,0xFF,0xFF,0x01,0x01,0x11,0x19,0x7D,0x19,0x11,0x05,0x01,0xFF,0xFF,0x01,0x11,0x39,0x7D,0x11,0x1D,0x01,0x05,0x01,0xFF,0xFF,0x01,0x11,0x39,0x7D,0x11,0x71,0x01,0x01,0x01,0xFF,0xFF,0x01,0x11,0x39,0x7D,0x11,0x71,0x01,0x05,0x01,0xFF,0xFF,0x01,0x01,0x01,0x1D,0x11,0x7D,0x39,0x11,0x01,0xFF,0xFF,0x01,0x01,0x01,0x71,0x11,0x7D,0x39,0x11,0x01,0xFF,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0xFF,0x01,0x05,0x01,0x71,0x11,0x7D,0x39,0x11,0x01,0xFF,0xFF,0x01,0x11,0x39,0x7D,0x11,0x1D,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x21,0x71,0x71,0x3D,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x21,0x71,0x71,0x3D,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x11,0x31,0x7D,0x31,0x11,0x01,0x01,0xFF,0xFF,0x01,0x01,0x11,0x31,0x7D,0x31,0x11,0x05,0x01,0xFF,0xFF,0x01,0x05,0x01,0x1D,0x11,0x7D,0x39,0x11,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x39,0x45,0x45,0x45,0x39,0x01,0x01,0xFF,0xFF,0x01,0xF1,0x39,0x45,0xFF,0x11,0x45,0x39,0x01,0xFF,0xFF,0x01,0x39,0x29,0x29,0x39,0x45,0x45,0x39,0x01,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0x39,0x45,0xFF,0x01,0xFF,0xFF,0x01,0x01,0xC7,0xAB,0x93,0xAB,0xC7,0x01,0x01,0xFF,0xFF,0x01,0x01,0xC7,0xAB,0x93,0xAB,0xC7,0x01,0x01,0xFF,0xFF,0x01,0x01,0xC7,0xAB,0x93,0xAB,0xC7,0x01,0x01,0xFF,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0xFF,0x01,0x01,0x39,0x7D,0x7D,0x7D,0x39,0x01,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x01,0x39,0x41,0x45,0x4F,0x45,0x39,0x01,0x01,0xFF,0xFF,0x01,0x49,0x55,0x25,0x01,0x05,0x7D,0x05,0x01,0xFF,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
+};
diff --git a/AT91SAM7S256/Source/Submenu01.rms b/AT91SAM7S256/Source/Submenu01.rms
new file mode 100644
index 0000000..aadf93d
--- /dev/null
+++ b/AT91SAM7S256/Source/Submenu01.rms
@@ -0,0 +1,128 @@
+const UBYTE SUBMENU01[] =
+{
+ 0x07,0x00, // Menu Format
+ 0x01,0xED, // Menu DataSize
+ 0x1D, // Menu item size
+ 0x11, // Menu items
+ 0x18, // Menu icon Width
+ 0x18, // Menu icon Height
+
+ // Software_files
+ 0x00,0x00,0x00,0x01, // 0x00000001
+ 0x10,0x00,0x80,0x01, // 0x10008001
+ 0x06,0x02,0x00,0x01, // 6 ,2 ,0 ,1
+ 0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,
+ 0x1C, // 1C
+
+ // NXT_files
+ 0x00,0x00,0x00,0x02, // 0x00000002
+ 0x10,0x00,0x80,0x01, // 0x10008001
+ 0x06,0x03,0x00,0x01, // 6 ,3 ,0 ,1
+ 0x4E,0x58,0x54,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x1D, // 1D
+
+ // Sound_files
+ 0x00,0x00,0x00,0x03, // 0x00000003
+ 0x10,0x00,0x80,0x01, // 0x10008001
+ 0x06,0x01,0x00,0x01, // 6 ,1 ,0 ,1
+ 0x53,0x6F,0x75,0x6E,0x64,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,0x00,0x00,0x00,
+ 0x1B, // 1B
+
+ // Datalog_files
+ 0x00,0x00,0x00,0x04, // 0x00000004
+ 0x00,0x80,0x80,0x00, // 0x00808000
+ 0x06,0x05,0x00,0x02, // 6 ,5 ,0 ,2
+ 0x44,0x61,0x74,0x61,0x6C,0x6F,0x67,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,0x00,
+ 0x1F, // 1F
+
+ // _
+ 0x00,0x00,0x00,0x11, // 0x00000011
+ 0x00,0x00,0x03,0x00, // 0x00000300
+ 0x06,0xF2,0x00,0x01, // 6 ,242,0 ,1
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, // 00
+
+ // _
+ 0x00,0x00,0x00,0x14, // 0x00000014
+ 0x00,0x00,0x03,0x00, // 0x00000300
+ 0x06,0xF2,0x00,0x01, // 6 ,242,0 ,1
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, // 00
+
+ // Run
+ 0x00,0x00,0x01,0x11, // 0x00000111
+ 0x00,0x00,0x01,0x20, // 0x00000120
+ 0x08,0xF8,0x00,0x00, // 8 ,248,0 ,0
+ 0x52,0x75,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x32, // 32
+
+ // Send
+ 0x00,0x00,0x02,0x11, // 0x00000211
+ 0x00,0x40,0x00,0x00, // 0x00400000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x53,0x65,0x6E,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x33, // 33
+
+ // Delete
+ 0x00,0x00,0x03,0x11, // 0x00000311
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x02, // 0 ,0 ,0 ,2
+ 0x44,0x65,0x6C,0x65,0x74,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x34, // 34
+
+ // Delete
+ 0x00,0x00,0x01,0x14, // 0x00000114
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x02, // 0 ,0 ,0 ,2
+ 0x44,0x65,0x6C,0x65,0x74,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x34, // 34
+
+ // Send
+ 0x00,0x00,0x02,0x14, // 0x00000214
+ 0x00,0x40,0x00,0x00, // 0x00400000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x53,0x65,0x6E,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x33, // 33
+
+ // _
+ 0x00,0x00,0x12,0x11, // 0x00001211
+ 0x00,0x00,0x03,0x00, // 0x00000300
+ 0x10,0xF9,0x00,0x00, // 16 ,249,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, // 00
+
+ // Are_you_sure?
+ 0x00,0x00,0x13,0x11, // 0x00001311
+ 0x00,0x00,0x00,0x08, // 0x00000008
+ 0x09,0x00,0x00,0x00, // 9 ,0 ,0 ,0
+ 0x41,0x72,0x65,0x20,0x79,0x6F,0x75,0x20,0x73,0x75,0x72,0x65,0x3F,0x00,0x00,0x00,
+ 0x31, // 31
+
+ // Are_you_sure?
+ 0x00,0x00,0x23,0x11, // 0x00002311
+ 0x00,0x00,0x00,0x04, // 0x00000004
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x41,0x72,0x65,0x20,0x79,0x6F,0x75,0x20,0x73,0x75,0x72,0x65,0x3F,0x00,0x00,0x00,
+ 0x30, // 30
+
+ // Are_you_sure?
+ 0x00,0x00,0x11,0x14, // 0x00001114
+ 0x00,0x00,0x00,0x08, // 0x00000008
+ 0x09,0x00,0x00,0x00, // 9 ,0 ,0 ,0
+ 0x41,0x72,0x65,0x20,0x79,0x6F,0x75,0x20,0x73,0x75,0x72,0x65,0x3F,0x00,0x00,0x00,
+ 0x31, // 31
+
+ // Are_you_sure?
+ 0x00,0x00,0x21,0x14, // 0x00002114
+ 0x00,0x00,0x00,0x04, // 0x00000004
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x41,0x72,0x65,0x20,0x79,0x6F,0x75,0x20,0x73,0x75,0x72,0x65,0x3F,0x00,0x00,0x00,
+ 0x30, // 30
+
+ // _
+ 0x00,0x00,0x12,0x14, // 0x00001214
+ 0x00,0x00,0x03,0x00, // 0x00000300
+ 0x10,0xF9,0x00,0x00, // 16 ,249,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, // 00
+};
diff --git a/AT91SAM7S256/Source/Submenu02.rms b/AT91SAM7S256/Source/Submenu02.rms
new file mode 100644
index 0000000..a30478f
--- /dev/null
+++ b/AT91SAM7S256/Source/Submenu02.rms
@@ -0,0 +1,401 @@
+const UBYTE SUBMENU02[] =
+{
+ 0x07,0x00, // Menu Format
+ 0x06,0x58, // Menu DataSize
+ 0x1D, // Menu item size
+ 0x38, // Menu items
+ 0x18, // Menu icon Width
+ 0x18, // Menu icon Height
+
+ // _
+ 0x00,0x00,0x00,0x01, // 0x00000001
+ 0x00,0x00,0x03,0x00, // 0x00000300
+ 0x0B,0xF7,0x00,0x01, // 11 ,247,0 ,1
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, // 00
+
+ // Forward_5
+ 0x00,0x00,0x00,0x11, // 0x00000011
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x23,0x00,0x01, // 11 ,35 ,0 ,1
+ 0x46,0x6F,0x72,0x77,0x61,0x72,0x64,0x20,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x23, // 23
+
+ // Forward
+ 0x00,0x00,0x00,0x21, // 0x00000021
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x22,0x00,0x01, // 11 ,34 ,0 ,1
+ 0x46,0x6F,0x72,0x77,0x61,0x72,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x22, // 22
+
+ // Turn_right_2
+ 0x00,0x00,0x00,0x31, // 0x00000031
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x29,0x00,0x01, // 11 ,41 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x72,0x69,0x67,0x68,0x74,0x20,0x32,0x00,0x00,0x00,0x00,
+ 0x29, // 29
+
+ // Turn_right
+ 0x00,0x00,0x00,0x41, // 0x00000041
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x28,0x00,0x01, // 11 ,40 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x72,0x69,0x67,0x68,0x74,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x28, // 28
+
+ // Back_right_2
+ 0x00,0x00,0x00,0x51, // 0x00000051
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2F,0x00,0x01, // 11 ,47 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x20,0x72,0x69,0x67,0x68,0x74,0x20,0x32,0x00,0x00,0x00,0x00,
+ 0x2F, // 2F
+
+ // Back_right
+ 0x00,0x00,0x00,0x61, // 0x00000061
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x27,0x00,0x01, // 11 ,39 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x20,0x72,0x69,0x67,0x68,0x74,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x27, // 27
+
+ // Tone_1
+ 0x00,0x00,0x00,0x71, // 0x00000071
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2B,0x00,0x01, // 11 ,43 ,0 ,1
+ 0x54,0x6F,0x6E,0x65,0x20,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2B, // 2B
+
+ // Tone_2
+ 0x00,0x00,0x00,0x81, // 0x00000081
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2C,0x00,0x01, // 11 ,44 ,0 ,1
+ 0x54,0x6F,0x6E,0x65,0x20,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2C, // 2C
+
+ // Back_left_2
+ 0x00,0x00,0x00,0x91, // 0x00000091
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x24,0x00,0x01, // 11 ,36 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x20,0x6C,0x65,0x66,0x74,0x20,0x32,0x00,0x00,0x00,0x00,0x00,
+ 0x24, // 24
+
+ // Back_left
+ 0x00,0x00,0x00,0xA1, // 0x000000A1
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2A,0x00,0x01, // 11 ,42 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x20,0x6C,0x65,0x66,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2A, // 2A
+
+ // Turn_left
+ 0x00,0x00,0x00,0xB1, // 0x000000B1
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x25,0x00,0x01, // 11 ,37 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x6C,0x65,0x66,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x25, // 25
+
+ // Turn_left_2
+ 0x00,0x00,0x00,0xC1, // 0x000000C1
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x26,0x00,0x01, // 11 ,38 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x6C,0x65,0x66,0x74,0x20,0x32,0x00,0x00,0x00,0x00,0x00,
+ 0x26, // 26
+
+ // Empty
+ 0x00,0x00,0x00,0xD1, // 0x000000D1
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x21,0x00,0x01, // 11 ,33 ,0 ,1
+ 0x45,0x6D,0x70,0x74,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x21, // 21
+
+ // Backward
+ 0x00,0x00,0x00,0xE1, // 0x000000E1
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2D,0x00,0x01, // 11 ,45 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x77,0x61,0x72,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2D, // 2D
+
+ // Backward_5
+ 0x00,0x00,0x00,0xF1, // 0x000000F1
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2E,0x00,0x01, // 11 ,46 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x77,0x61,0x72,0x64,0x20,0x35,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2E, // 2E
+
+ // Empty
+ 0x00,0x00,0x01,0x11, // 0x00000111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x41,0x00,0x01, // 11 ,65 ,0 ,1
+ 0x45,0x6D,0x70,0x74,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x21, // 21
+
+ // Wait_2
+ 0x00,0x00,0x02,0x11, // 0x00000211
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x46,0x00,0x01, // 11 ,70 ,0 ,1
+ 0x57,0x61,0x69,0x74,0x20,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x46, // 46
+
+ // Wait_5
+ 0x00,0x00,0x03,0x11, // 0x00000311
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x47,0x00,0x01, // 11 ,71 ,0 ,1
+ 0x57,0x61,0x69,0x74,0x20,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x47, // 47
+
+ // Wait_10
+ 0x00,0x00,0x04,0x11, // 0x00000411
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x48,0x00,0x01, // 11 ,72 ,0 ,1
+ 0x57,0x61,0x69,0x74,0x20,0x31,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x48, // 48
+
+ // Object
+ 0x00,0x00,0x05,0x11, // 0x00000511
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x43,0x00,0x01, // 11 ,67 ,0 ,1
+ 0x4F,0x62,0x6A,0x65,0x63,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x43, // 43
+
+ // Sound
+ 0x00,0x00,0x06,0x11, // 0x00000611
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x44,0x00,0x01, // 11 ,68 ,0 ,1
+ 0x53,0x6F,0x75,0x6E,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x44, // 44
+
+ // Light
+ 0x00,0x00,0x07,0x11, // 0x00000711
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x42,0x00,0x01, // 11 ,66 ,0 ,1
+ 0x4C,0x69,0x67,0x68,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x42, // 42
+
+ // Dark
+ 0x00,0x00,0x08,0x11, // 0x00000811
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x49,0x00,0x01, // 11 ,73 ,0 ,1
+ 0x44,0x61,0x72,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x49, // 49
+
+ // Touch
+ 0x00,0x00,0x09,0x11, // 0x00000911
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x45,0x00,0x01, // 11 ,69 ,0 ,1
+ 0x54,0x6F,0x75,0x63,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x45, // 45
+
+ // Forward_5
+ 0x00,0x00,0x11,0x11, // 0x00001111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x23,0x00,0x01, // 11 ,35 ,0 ,1
+ 0x46,0x6F,0x72,0x77,0x61,0x72,0x64,0x20,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x23, // 23
+
+ // Forward
+ 0x00,0x00,0x21,0x11, // 0x00002111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x22,0x00,0x01, // 11 ,34 ,0 ,1
+ 0x46,0x6F,0x72,0x77,0x61,0x72,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x22, // 22
+
+ // Turn_right_2
+ 0x00,0x00,0x31,0x11, // 0x00003111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x29,0x00,0x01, // 11 ,41 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x72,0x69,0x67,0x68,0x74,0x20,0x32,0x00,0x00,0x00,0x00,
+ 0x29, // 29
+
+ // Turn_right
+ 0x00,0x00,0x41,0x11, // 0x00004111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x28,0x00,0x01, // 11 ,40 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x72,0x69,0x67,0x68,0x74,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x28, // 28
+
+ // Back_right_2
+ 0x00,0x00,0x51,0x11, // 0x00005111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2F,0x00,0x01, // 11 ,47 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x20,0x72,0x69,0x67,0x68,0x74,0x20,0x32,0x00,0x00,0x00,0x00,
+ 0x2F, // 2F
+
+ // Back_right
+ 0x00,0x00,0x61,0x11, // 0x00006111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x27,0x00,0x01, // 11 ,39 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x20,0x72,0x69,0x67,0x68,0x74,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x27, // 27
+
+ // Tone_1
+ 0x00,0x00,0x71,0x11, // 0x00007111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2B,0x00,0x01, // 11 ,43 ,0 ,1
+ 0x54,0x6F,0x6E,0x65,0x20,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2B, // 2B
+
+ // Tone_2
+ 0x00,0x00,0x81,0x11, // 0x00008111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2C,0x00,0x01, // 11 ,44 ,0 ,1
+ 0x54,0x6F,0x6E,0x65,0x20,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2C, // 2C
+
+ // Back_left_2
+ 0x00,0x00,0x91,0x11, // 0x00009111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x24,0x00,0x01, // 11 ,36 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x20,0x6C,0x65,0x66,0x74,0x20,0x32,0x00,0x00,0x00,0x00,0x00,
+ 0x24, // 24
+
+ // Back_left
+ 0x00,0x00,0xA1,0x11, // 0x0000A111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2A,0x00,0x01, // 11 ,42 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x20,0x6C,0x65,0x66,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2A, // 2A
+
+ // Turn_left
+ 0x00,0x00,0xB1,0x11, // 0x0000B111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x25,0x00,0x01, // 11 ,37 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x6C,0x65,0x66,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x25, // 25
+
+ // Turn_left_2
+ 0x00,0x00,0xC1,0x11, // 0x0000C111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x26,0x00,0x01, // 11 ,38 ,0 ,1
+ 0x54,0x75,0x72,0x6E,0x20,0x6C,0x65,0x66,0x74,0x20,0x32,0x00,0x00,0x00,0x00,0x00,
+ 0x26, // 26
+
+ // Empty
+ 0x00,0x00,0xD1,0x11, // 0x0000D111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x21,0x00,0x01, // 11 ,33 ,0 ,1
+ 0x45,0x6D,0x70,0x74,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x21, // 21
+
+ // Backward
+ 0x00,0x00,0xE1,0x11, // 0x0000E111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2D,0x00,0x01, // 11 ,45 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x77,0x61,0x72,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2D, // 2D
+
+ // Backward_5
+ 0x00,0x00,0xF1,0x11, // 0x0000F111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x2E,0x00,0x01, // 11 ,46 ,0 ,1
+ 0x42,0x61,0x63,0x6B,0x77,0x61,0x72,0x64,0x20,0x35,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2E, // 2E
+
+ // Empty
+ 0x00,0x01,0x11,0x11, // 0x00011111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x41,0x00,0x01, // 11 ,65 ,0 ,1
+ 0x45,0x6D,0x70,0x74,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x21, // 21
+
+ // Wait_2
+ 0x00,0x02,0x11,0x11, // 0x00021111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x46,0x00,0x01, // 11 ,70 ,0 ,1
+ 0x57,0x61,0x69,0x74,0x20,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x46, // 46
+
+ // Wait_5
+ 0x00,0x03,0x11,0x11, // 0x00031111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x47,0x00,0x01, // 11 ,71 ,0 ,1
+ 0x57,0x61,0x69,0x74,0x20,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x47, // 47
+
+ // Wait_10
+ 0x00,0x04,0x11,0x11, // 0x00041111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x48,0x00,0x01, // 11 ,72 ,0 ,1
+ 0x57,0x61,0x69,0x74,0x20,0x31,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x48, // 48
+
+ // Object
+ 0x00,0x05,0x11,0x11, // 0x00051111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x43,0x00,0x01, // 11 ,67 ,0 ,1
+ 0x4F,0x62,0x6A,0x65,0x63,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x43, // 43
+
+ // Sound
+ 0x00,0x06,0x11,0x11, // 0x00061111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x44,0x00,0x01, // 11 ,68 ,0 ,1
+ 0x53,0x6F,0x75,0x6E,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x44, // 44
+
+ // Light
+ 0x00,0x07,0x11,0x11, // 0x00071111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x42,0x00,0x01, // 11 ,66 ,0 ,1
+ 0x4C,0x69,0x67,0x68,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x42, // 42
+
+ // Dark
+ 0x00,0x08,0x11,0x11, // 0x00081111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x49,0x00,0x01, // 11 ,73 ,0 ,1
+ 0x44,0x61,0x72,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x49, // 49
+
+ // Touch
+ 0x00,0x09,0x11,0x11, // 0x00091111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0x45,0x00,0x01, // 11 ,69 ,0 ,1
+ 0x54,0x6F,0x75,0x63,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x45, // 45
+
+ // Stop
+ 0x00,0x11,0x11,0x11, // 0x00111111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0xFB,0x00,0x01, // 11 ,251,0 ,1
+ 0x53,0x74,0x6F,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x4D, // 4D
+
+ // Loop
+ 0x00,0x21,0x11,0x11, // 0x00211111
+ 0x10,0x00,0x00,0x61, // 0x10000061
+ 0x0B,0xFC,0x00,0x01, // 11 ,252,0 ,1
+ 0x4C,0x6F,0x6F,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x4E, // 4E
+
+ // Run
+ 0x01,0x11,0x11,0x11, // 0x01111111
+ 0x00,0x00,0x00,0x60, // 0x00000060
+ 0x0B,0xF8,0x00,0x00, // 11 ,248,0 ,0
+ 0x52,0x75,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x32, // 32
+
+ // Main_menu
+ 0x02,0x11,0x11,0x11, // 0x02111111
+ 0x00,0x00,0x20,0x60, // 0x00002060
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x4D,0x61,0x69,0x6E,0x20,0x6D,0x65,0x6E,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x37, // 37
+
+ // Save
+ 0x04,0x11,0x11,0x11, // 0x04111111
+ 0x00,0x00,0x00,0x60, // 0x00000060
+ 0x0B,0xFA,0x00,0x02, // 11 ,250,0 ,2
+ 0x53,0x61,0x76,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x1D, // 1D
+
+ // Yes
+ 0x14,0x11,0x11,0x11, // 0x14111111
+ 0x00,0x00,0x20,0x20, // 0x00002020
+ 0x0B,0xED,0x00,0x00, // 11 ,237,0 ,0
+ 0x59,0x65,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x31, // 31
+
+ // No
+ 0x24,0x11,0x11,0x11, // 0x24111111
+ 0x00,0x08,0x00,0x24, // 0x00080024
+ 0x0B,0xF6,0x00,0x00, // 11 ,246,0 ,0
+ 0x4E,0x6F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x30, // 30
+};
diff --git a/AT91SAM7S256/Source/Submenu03.rms b/AT91SAM7S256/Source/Submenu03.rms
new file mode 100644
index 0000000..0dd4b6c
--- /dev/null
+++ b/AT91SAM7S256/Source/Submenu03.rms
@@ -0,0 +1,324 @@
+const UBYTE SUBMENU03[] =
+{
+ 0x07,0x00, // Menu Format
+ 0x05,0x19, // Menu DataSize
+ 0x1D, // Menu item size
+ 0x2D, // Menu items
+ 0x18, // Menu icon Width
+ 0x18, // Menu icon Height
+
+ // Sound_dB
+ 0x00,0x00,0x00,0x01, // 0x00000001
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x02,0x00,0x01, // 10 ,2 ,0 ,1
+ 0x53,0x6F,0x75,0x6E,0x64,0x20,0x64,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02, // 02
+
+ // Sound_dBA
+ 0x00,0x00,0x00,0x02, // 0x00000002
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x03,0x00,0x01, // 10 ,3 ,0 ,1
+ 0x53,0x6F,0x75,0x6E,0x64,0x20,0x64,0x42,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03, // 03
+
+ // Reflected_light
+ 0x00,0x00,0x00,0x03, // 0x00000003
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x04,0x00,0x01, // 10 ,4 ,0 ,1
+ 0x52,0x65,0x66,0x6C,0x65,0x63,0x74,0x65,0x64,0x20,0x6C,0x69,0x67,0x68,0x74,0x00,
+ 0x04, // 04
+
+ // Ambient_light
+ 0x00,0x00,0x00,0x04, // 0x00000004
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x05,0x00,0x01, // 10 ,5 ,0 ,1
+ 0x41,0x6D,0x62,0x69,0x65,0x6E,0x74,0x20,0x6C,0x69,0x67,0x68,0x74,0x00,0x00,0x00,
+ 0x05, // 05
+
+ // Light_sensor*
+ 0x00,0x00,0x00,0x05, // 0x00000005
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x06,0x00,0x01, // 10 ,6 ,0 ,1
+ 0x4C,0x69,0x67,0x68,0x74,0x20,0x73,0x65,0x6E,0x73,0x6F,0x72,0x2A,0x00,0x00,0x00,
+ 0x06, // 06
+
+ // Temperature_`C*
+ 0x00,0x00,0x00,0x06, // 0x00000006
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x0D,0x00,0x01, // 10 ,13 ,0 ,1
+ 0x54,0x65,0x6D,0x70,0x65,0x72,0x61,0x74,0x75,0x72,0x65,0x20,0x60,0x43,0x2A,0x00,
+ 0x0D, // 0D
+
+ // Temperature_`F*
+ 0x00,0x00,0x00,0x07, // 0x00000007
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x0E,0x00,0x01, // 10 ,14 ,0 ,1
+ 0x54,0x65,0x6D,0x70,0x65,0x72,0x61,0x74,0x75,0x72,0x65,0x20,0x60,0x46,0x2A,0x00,
+ 0x0E, // 0E
+
+ // Rotation*
+ 0x00,0x00,0x00,0x08, // 0x00000008
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x0A,0x00,0x01, // 10 ,10 ,0 ,1
+ 0x52,0x6F,0x74,0x61,0x74,0x69,0x6F,0x6E,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x0A, // 0A
+
+ // Motor_Rotations
+ 0x00,0x00,0x00,0x09, // 0x00000009
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0A,0x09,0x00,0x01, // 10 ,9 ,0 ,1
+ 0x4D,0x6F,0x74,0x6F,0x72,0x20,0x52,0x6F,0x74,0x61,0x74,0x69,0x6F,0x6E,0x73,0x00,
+ 0x09, // 09
+
+ // Motor_Degrees
+ 0x00,0x00,0x00,0x0A, // 0x0000000A
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0A,0x08,0x00,0x01, // 10 ,8 ,0 ,1
+ 0x4D,0x6F,0x74,0x6F,0x72,0x20,0x44,0x65,0x67,0x72,0x65,0x65,0x73,0x00,0x00,0x00,
+ 0x08, // 08
+
+ // Touch
+ 0x00,0x00,0x00,0x0B, // 0x0000000B
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x07,0x00,0x01, // 10 ,7 ,0 ,1
+ 0x54,0x6F,0x75,0x63,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x07, // 07
+
+ // UltraSonic_inch
+ 0x00,0x00,0x00,0x0C, // 0x0000000C
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x0B,0x00,0x01, // 10 ,11 ,0 ,1
+ 0x55,0x6C,0x74,0x72,0x61,0x53,0x6F,0x6E,0x69,0x63,0x20,0x69,0x6E,0x63,0x68,0x00,
+ 0x0B, // 0B
+
+ // UltraSonic_cm
+ 0x00,0x00,0x00,0x0D, // 0x0000000D
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x0C,0x00,0x01, // 10 ,12 ,0 ,1
+ 0x55,0x6C,0x74,0x72,0x61,0x53,0x6F,0x6E,0x69,0x63,0x20,0x63,0x6D,0x00,0x00,0x00,
+ 0x0C, // 0C
+
+ // Done
+ 0x00,0x00,0x00,0x0E, // 0x0000000E
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0A,0xEE,0x00,0x01, // 10 ,238,0 ,1
+ 0x44,0x6F,0x6E,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x31, // 31
+
+ // Port_1
+ 0x00,0x00,0x00,0x11, // 0x00000011
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x12,0x00,0x01, // 10 ,18 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x12, // 12
+
+ // Port_2
+ 0x00,0x00,0x00,0x21, // 0x00000021
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x13,0x00,0x01, // 10 ,19 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x13, // 13
+
+ // Port_3
+ 0x00,0x00,0x00,0x31, // 0x00000031
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x14,0x00,0x01, // 10 ,20 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x14, // 14
+
+ // Port_4
+ 0x00,0x00,0x00,0x41, // 0x00000041
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x15,0x00,0x01, // 10 ,21 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x15, // 15
+
+ // Port_A
+ 0x00,0x00,0x00,0x19, // 0x00000019
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x16,0x00,0x01, // 10 ,22 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x16, // 16
+
+ // Port_B
+ 0x00,0x00,0x00,0x29, // 0x00000029
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x17,0x00,0x01, // 10 ,23 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x17, // 17
+
+ // Port_C
+ 0x00,0x00,0x00,0x39, // 0x00000039
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x18,0x00,0x01, // 10 ,24 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x18, // 18
+
+ // Port_A
+ 0x00,0x00,0x00,0x1A, // 0x0000001A
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x16,0x00,0x01, // 10 ,22 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x16, // 16
+
+ // Port_B
+ 0x00,0x00,0x00,0x2A, // 0x0000002A
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x17,0x00,0x01, // 10 ,23 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x17, // 17
+
+ // Port_C
+ 0x00,0x00,0x00,0x3A, // 0x0000003A
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0A,0x18,0x00,0x01, // 10 ,24 ,0 ,1
+ 0x50,0x6F,0x72,0x74,0x20,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x17, // 17
+
+ // Logging_time
+ 0x00,0x00,0x00,0x1E, // 0x0000001E
+ 0x00,0x00,0x03,0xE0, // 0x000003E0
+ 0x0C,0xEF,0x00,0x01, // 12 ,239,0 ,1
+ 0x4C,0x6F,0x67,0x67,0x69,0x6E,0x67,0x20,0x74,0x69,0x6D,0x65,0x00,0x00,0x00,0x00,
+ 0x38, // 38
+
+ // _
+ 0x00,0x00,0x00,0x2E, // 0x0000002E
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x35, // 35
+
+ // _
+ 0x00,0x00,0x00,0x3E, // 0x0000003E
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x36, // 36
+
+ // Logging_Rate
+ 0x00,0x00,0x01,0x11, // 0x00000111
+ 0x00,0x00,0x03,0x68, // 0x00000368
+ 0x0C,0xEF,0x00,0x01, // 12 ,239,0 ,1
+ 0x4C,0x6F,0x67,0x67,0x69,0x6E,0x67,0x20,0x52,0x61,0x74,0x65,0x00,0x00,0x00,0x00,
+ 0x38, // 38
+
+ // _
+ 0x00,0x00,0x02,0x11, // 0x00000211
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x35, // 35
+
+ // _
+ 0x00,0x00,0x03,0x11, // 0x00000311
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x36, // 36
+
+ // Logging_Rate
+ 0x00,0x00,0x01,0x19, // 0x00000119
+ 0x00,0x00,0x03,0x68, // 0x00000368
+ 0x0C,0xEF,0x00,0x01, // 12 ,239,0 ,1
+ 0x4C,0x6F,0x67,0x67,0x69,0x6E,0x67,0x20,0x52,0x61,0x74,0x65,0x00,0x00,0x00,0x00,
+ 0x38, // 38
+
+ // _
+ 0x00,0x00,0x02,0x19, // 0x00000219
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x35, // 35
+
+ // _
+ 0x00,0x00,0x03,0x19, // 0x00000319
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x36, // 36
+
+ // Logging_Rate
+ 0x00,0x00,0x01,0x1A, // 0x0000011A
+ 0x00,0x00,0x03,0x68, // 0x00000368
+ 0x0C,0xEF,0x00,0x01, // 12 ,239,0 ,1
+ 0x4C,0x6F,0x67,0x67,0x69,0x6E,0x67,0x20,0x52,0x61,0x74,0x65,0x00,0x00,0x00,0x00,
+ 0x38, // 38
+
+ // _
+ 0x00,0x00,0x02,0x1A, // 0x0000021A
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x35, // 35
+
+ // _
+ 0x00,0x00,0x03,0x1A, // 0x0000031A
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x36, // 36
+
+ // _
+ 0x00,0x00,0x01,0x1E, // 0x0000011E
+ 0x00,0x00,0x10,0x00, // 0x00001000
+ 0x0A,0xF7,0x00,0x01, // 10 ,247,0 ,1
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, // 00
+
+ // _
+ 0x00,0x00,0x11,0x11, // 0x00001111
+ 0x0E,0x05,0x10,0x00, // 0x0E051000
+ 0x0A,0xF2,0x00,0x00, // 10 ,242,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, // 00
+
+ // _
+ 0x00,0x00,0x11,0x19, // 0x00001119
+ 0x0E,0x05,0x10,0x00, // 0x0E051000
+ 0x0A,0xF2,0x00,0x00, // 10 ,242,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, // 00
+
+ // _
+ 0x00,0x00,0x11,0x1A, // 0x0000111A
+ 0x0E,0x05,0x10,0x00, // 0x0E051000
+ 0x0A,0xF2,0x00,0x00, // 10 ,242,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, // 00
+
+ // Run
+ 0x00,0x00,0x11,0x1E, // 0x0000111E
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0A,0xF8,0x00,0x02, // 10 ,248,0 ,2
+ 0x52,0x75,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x32, // 32
+
+ // Main_menu
+ 0x00,0x01,0x11,0x1E, // 0x0001111E
+ 0x00,0x02,0x20,0x00, // 0x00022000
+ 0x0A,0xF1,0x00,0x00, // 10 ,241,0 ,0
+ 0x4D,0x61,0x69,0x6E,0x20,0x6D,0x65,0x6E,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x37, // 37
+
+ // Save
+ 0x00,0x02,0x11,0x1E, // 0x0002111E
+ 0x00,0x02,0x00,0x00, // 0x00020000
+ 0x0A,0xFA,0x00,0x02, // 10 ,250,0 ,2
+ 0x53,0x61,0x76,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x1E, // 1E
+
+ // Yes
+ 0x00,0x12,0x11,0x1E, // 0x0012111E
+ 0x00,0x00,0x20,0x20, // 0x00002020
+ 0x0A,0xED,0x00,0x00, // 10 ,237,0 ,0
+ 0x59,0x65,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x31, // 31
+
+ // No
+ 0x00,0x22,0x11,0x1E, // 0x0022111E
+ 0x00,0x08,0x00,0x24, // 0x00080024
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x4E,0x6F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x30, // 30
+};
diff --git a/AT91SAM7S256/Source/Submenu04.rms b/AT91SAM7S256/Source/Submenu04.rms
new file mode 100644
index 0000000..0bfec3e
--- /dev/null
+++ b/AT91SAM7S256/Source/Submenu04.rms
@@ -0,0 +1,170 @@
+const UBYTE SUBMENU04[] =
+{
+ 0x07,0x00, // Menu Format
+ 0x02,0x9B, // Menu DataSize
+ 0x1D, // Menu item size
+ 0x17, // Menu items
+ 0x18, // Menu icon Width
+ 0x18, // Menu icon Height
+
+ // Sound_dB
+ 0x00,0x00,0x00,0x01, // 0x00000001
+ 0x10,0x00,0x01,0x21, // 0x10000121
+ 0x0E,0x02,0x00,0x01, // 14 ,2 ,0 ,1
+ 0x53,0x6F,0x75,0x6E,0x64,0x20,0x64,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02, // 02
+
+ // Sound_dBA
+ 0x00,0x00,0x00,0x02, // 0x00000002
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x03,0x00,0x01, // 14 ,3 ,0 ,1
+ 0x53,0x6F,0x75,0x6E,0x64,0x20,0x64,0x42,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x03, // 03
+
+ // Reflected_light
+ 0x00,0x00,0x00,0x03, // 0x00000003
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x04,0x00,0x01, // 14 ,4 ,0 ,1
+ 0x52,0x65,0x66,0x6C,0x65,0x63,0x74,0x65,0x64,0x20,0x6C,0x69,0x67,0x68,0x74,0x00,
+ 0x04, // 04
+
+ // Ambient_light
+ 0x00,0x00,0x00,0x04, // 0x00000004
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x05,0x00,0x01, // 14 ,5 ,0 ,1
+ 0x41,0x6D,0x62,0x69,0x65,0x6E,0x74,0x20,0x6C,0x69,0x67,0x68,0x74,0x00,0x00,0x00,
+ 0x05, // 05
+
+ // Light_Sensor*
+ 0x00,0x00,0x00,0x05, // 0x00000005
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x06,0x00,0x01, // 14 ,6 ,0 ,1
+ 0x4C,0x69,0x67,0x68,0x74,0x20,0x53,0x65,0x6E,0x73,0x6F,0x72,0x2A,0x00,0x00,0x00,
+ 0x06, // 06
+
+ // Temperature_`C*
+ 0x00,0x00,0x00,0x06, // 0x00000006
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x0D,0x00,0x01, // 14 ,13 ,0 ,1
+ 0x54,0x65,0x6D,0x70,0x65,0x72,0x61,0x74,0x75,0x72,0x65,0x20,0x60,0x43,0x2A,0x00,
+ 0x0D, // 0D
+
+ // Temperature_`F*
+ 0x00,0x00,0x00,0x07, // 0x00000007
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x0E,0x00,0x01, // 14 ,14 ,0 ,1
+ 0x54,0x65,0x6D,0x70,0x65,0x72,0x61,0x74,0x75,0x72,0x65,0x20,0x60,0x46,0x2A,0x00,
+ 0x0E, // 0E
+
+ // Rotation*
+ 0x00,0x00,0x00,0x08, // 0x00000008
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x0A,0x00,0x01, // 14 ,10 ,0 ,1
+ 0x52,0x6F,0x74,0x61,0x74,0x69,0x6F,0x6E,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x0A, // 0A
+
+ // Motor_rotations
+ 0x00,0x00,0x00,0x09, // 0x00000009
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x09,0x00,0x01, // 14 ,9 ,0 ,1
+ 0x4D,0x6F,0x74,0x6F,0x72,0x20,0x72,0x6F,0x74,0x61,0x74,0x69,0x6F,0x6E,0x73,0x00,
+ 0x09, // 09
+
+ // Motor_degrees
+ 0x00,0x00,0x00,0x0A, // 0x0000000A
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x08,0x00,0x01, // 14 ,8 ,0 ,1
+ 0x4D,0x6F,0x74,0x6F,0x72,0x20,0x64,0x65,0x67,0x72,0x65,0x65,0x73,0x00,0x00,0x00,
+ 0x08, // 08
+
+ // Touch
+ 0x00,0x00,0x00,0x0B, // 0x0000000B
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x07,0x00,0x01, // 14 ,7 ,0 ,1
+ 0x54,0x6F,0x75,0x63,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x07, // 07
+
+ // Ultrasonic_inch
+ 0x00,0x00,0x00,0x0C, // 0x0000000C
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x0B,0x00,0x01, // 14 ,11 ,0 ,1
+ 0x55,0x6C,0x74,0x72,0x61,0x73,0x6F,0x6E,0x69,0x63,0x20,0x69,0x6E,0x63,0x68,0x00,
+ 0x0B, // 0B
+
+ // Ultrasonic_cm
+ 0x00,0x00,0x00,0x0D, // 0x0000000D
+ 0x10,0x00,0x00,0x21, // 0x10000021
+ 0x0E,0x0C,0x00,0x01, // 14 ,12 ,0 ,1
+ 0x55,0x6C,0x74,0x72,0x61,0x73,0x6F,0x6E,0x69,0x63,0x20,0x63,0x6D,0x00,0x00,0x00,
+ 0x0C, // 0C
+
+ // Port_1
+ 0x00,0x00,0x00,0x11, // 0x00000011
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x12,0x00,0x00, // 14 ,18 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x12, // 12
+
+ // Port_2
+ 0x00,0x00,0x00,0x21, // 0x00000021
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x13,0x00,0x00, // 14 ,19 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x13, // 13
+
+ // Port_3
+ 0x00,0x00,0x00,0x31, // 0x00000031
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x14,0x00,0x00, // 14 ,20 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x14, // 14
+
+ // Port_4
+ 0x00,0x00,0x00,0x41, // 0x00000041
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x15,0x00,0x00, // 14 ,21 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x15, // 15
+
+ // Port_A
+ 0x00,0x00,0x00,0x19, // 0x00000019
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x16,0x00,0x00, // 14 ,22 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x16, // 16
+
+ // Port_B
+ 0x00,0x00,0x00,0x29, // 0x00000029
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x17,0x00,0x00, // 14 ,23 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x17, // 17
+
+ // Port_C
+ 0x00,0x00,0x00,0x39, // 0x00000039
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x18,0x00,0x00, // 14 ,24 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x18, // 18
+
+ // Port_A
+ 0x00,0x00,0x00,0x1A, // 0x0000001A
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x16,0x00,0x00, // 14 ,22 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x16, // 16
+
+ // Port_B
+ 0x00,0x00,0x00,0x2A, // 0x0000002A
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x17,0x00,0x00, // 14 ,23 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x17, // 17
+
+ // Port_C
+ 0x00,0x00,0x00,0x3A, // 0x0000003A
+ 0x00,0x00,0x00,0x20, // 0x00000020
+ 0x0E,0x18,0x00,0x00, // 14 ,24 ,0 ,0
+ 0x50,0x6F,0x72,0x74,0x20,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x18, // 18
+};
diff --git a/AT91SAM7S256/Source/Submenu05.rms b/AT91SAM7S256/Source/Submenu05.rms
new file mode 100644
index 0000000..5e03396
--- /dev/null
+++ b/AT91SAM7S256/Source/Submenu05.rms
@@ -0,0 +1,128 @@
+const UBYTE SUBMENU05[] =
+{
+ 0x07,0x00, // Menu Format
+ 0x01,0xED, // Menu DataSize
+ 0x1D, // Menu item size
+ 0x11, // Menu items
+ 0x18, // Menu icon Width
+ 0x18, // Menu icon Height
+
+ // Volume
+ 0x00,0x00,0x00,0x01, // 0x00000001
+ 0x00,0x00,0x80,0x00, // 0x00008000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x56,0x6F,0x6C,0x75,0x6D,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x39, // 39
+
+ // Sleep
+ 0x00,0x00,0x00,0x02, // 0x00000002
+ 0x00,0x00,0x80,0x00, // 0x00008000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x53,0x6C,0x65,0x65,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x3A, // 3A
+
+ // NXT_Version
+ 0x00,0x00,0x00,0x03, // 0x00000003
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x01,0x00,0x00,0x00, // 1 ,0 ,0 ,0
+ 0x4E,0x58,0x54,0x20,0x56,0x65,0x72,0x73,0x69,0x6F,0x6E,0x00,0x00,0x00,0x00,0x00,
+ 0x4F, // 4F
+
+ // Delete_files
+ 0x00,0x00,0x00,0x04, // 0x00000004
+ 0x00,0x00,0x80,0x00, // 0x00008000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x44,0x65,0x6C,0x65,0x74,0x65,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,0x00,0x00,
+ 0x34, // 34
+
+ // _
+ 0x00,0x00,0x00,0x11, // 0x00000011
+ 0x00,0x00,0x03,0x60, // 0x00000360
+ 0x07,0xEF,0x00,0x00, // 7 ,239,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x39, // 39
+
+ // _
+ 0x00,0x00,0x00,0x21, // 0x00000021
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x35, // 35
+
+ // _
+ 0x00,0x00,0x00,0x31, // 0x00000031
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x36, // 36
+
+ // _
+ 0x00,0x00,0x00,0x12, // 0x00000012
+ 0x00,0x00,0x03,0x20, // 0x00000320
+ 0x04,0xEF,0x00,0x00, // 4 ,239,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x3A, // 3A
+
+ // _
+ 0x00,0x00,0x00,0x22, // 0x00000022
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x35, // 35
+
+ // _
+ 0x00,0x00,0x00,0x32, // 0x00000032
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x36, // 36
+
+ // Software_files
+ 0x00,0x00,0x00,0x14, // 0x00000014
+ 0x10,0x00,0x00,0x01, // 0x10000001
+ 0x05,0x02,0x00,0x02, // 5 ,2 ,0 ,2
+ 0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,
+ 0x1C, // 1C
+
+ // NXT_files
+ 0x00,0x00,0x00,0x24, // 0x00000024
+ 0x10,0x00,0x00,0x01, // 0x10000001
+ 0x05,0x03,0x00,0x02, // 5 ,3 ,0 ,2
+ 0x4E,0x58,0x54,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x1D, // 1D
+
+ // Sound_files
+ 0x00,0x00,0x00,0x34, // 0x00000034
+ 0x10,0x00,0x00,0x01, // 0x10000001
+ 0x05,0x01,0x00,0x02, // 5 ,1 ,0 ,2
+ 0x53,0x6F,0x75,0x6E,0x64,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,0x00,0x00,0x00,
+ 0x1B, // 1B
+
+ // Datalog_files
+ 0x00,0x00,0x00,0x44, // 0x00000044
+ 0x10,0x80,0x00,0x01, // 0x10800001
+ 0x05,0x05,0x00,0x02, // 5 ,5 ,0 ,2
+ 0x44,0x61,0x74,0x61,0x6C,0x6F,0x67,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,0x00,
+ 0x1F, // 1F
+
+ // Try_me_files
+ 0x00,0x00,0x00,0x54, // 0x00000054
+ 0x10,0x00,0x00,0x01, // 0x10000001
+ 0x05,0x04,0x00,0x02, // 5 ,4 ,0 ,2
+ 0x54,0x72,0x79,0x20,0x6D,0x65,0x20,0x66,0x69,0x6C,0x65,0x73,0x00,0x00,0x00,0x00,
+ 0x1E, // 1E
+
+ // Are_you_sure?
+ 0x00,0x00,0x01,0x14, // 0x00000114
+ 0x00,0x00,0x01,0x08, // 0x00000108
+ 0x05,0xF1,0x00,0x00, // 5 ,241,0 ,0
+ 0x41,0x72,0x65,0x20,0x79,0x6F,0x75,0x20,0x73,0x75,0x72,0x65,0x3F,0x00,0x00,0x00,
+ 0x31, // 31
+
+ // Are_you_sure?
+ 0x00,0x00,0x02,0x14, // 0x00000214
+ 0x00,0x00,0x01,0x04, // 0x00000104
+ 0x05,0x00,0x00,0x00, // 5 ,0 ,0 ,0
+ 0x41,0x72,0x65,0x20,0x79,0x6F,0x75,0x20,0x73,0x75,0x72,0x65,0x3F,0x00,0x00,0x00,
+ 0x30, // 30
+};
diff --git a/AT91SAM7S256/Source/Submenu06.rms b/AT91SAM7S256/Source/Submenu06.rms
new file mode 100644
index 0000000..5cd1b06
--- /dev/null
+++ b/AT91SAM7S256/Source/Submenu06.rms
@@ -0,0 +1,51 @@
+const UBYTE SUBMENU06[] =
+{
+ 0x07,0x00, // Menu Format
+ 0x00,0xAE, // Menu DataSize
+ 0x1D, // Menu item size
+ 0x06, // Menu items
+ 0x18, // Menu icon Width
+ 0x18, // Menu icon Height
+
+ // _
+ 0x00,0x00,0x00,0x01, // 0x00000001
+ 0x00,0x00,0x10,0x00, // 0x00001000
+ 0x06,0x04,0x00,0x01, // 6 ,4 ,0 ,1
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x1E, // 1E
+
+ // _
+ 0x00,0x00,0x00,0x11, // 0x00000011
+ 0x00,0x00,0x03,0x80, // 0x00000380
+ 0x06,0xF2,0x00,0x02, // 6 ,242,0 ,2
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x1E, // 1E
+
+ // Delete
+ 0x00,0x00,0x01,0x11, // 0x00000111
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x02, // 0 ,0 ,0 ,2
+ 0x44,0x65,0x6C,0x65,0x74,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x34, // 34
+
+ // Run
+ 0x00,0x00,0x02,0x11, // 0x00000211
+ 0x00,0x00,0x01,0x20, // 0x00000120
+ 0x08,0xF8,0x00,0x00, // 8 ,248,0 ,0
+ 0x52,0x75,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x32, // 32
+
+ // Are_you_sure?
+ 0x00,0x00,0x11,0x11, // 0x00001111
+ 0x00,0x00,0x00,0x08, // 0x00000008
+ 0x09,0x00,0x00,0x00, // 9 ,0 ,0 ,0
+ 0x41,0x72,0x65,0x20,0x79,0x6F,0x75,0x20,0x73,0x75,0x72,0x65,0x3F,0x00,0x00,0x00,
+ 0x31, // 31
+
+ // Are_you_sure?
+ 0x00,0x00,0x21,0x11, // 0x00002111
+ 0x00,0x00,0x00,0x04, // 0x00000004
+ 0x00,0x00,0x00,0x00, // 0 ,0 ,0 ,0
+ 0x41,0x72,0x65,0x20,0x79,0x6F,0x75,0x20,0x73,0x75,0x72,0x65,0x3F,0x00,0x00,0x00,
+ 0x30, // 30
+};
diff --git a/AT91SAM7S256/Source/Submenu07.rms b/AT91SAM7S256/Source/Submenu07.rms
new file mode 100644
index 0000000..43c292e
--- /dev/null
+++ b/AT91SAM7S256/Source/Submenu07.rms
@@ -0,0 +1,142 @@
+const UBYTE SUBMENU07[] =
+{
+ 0x07,0x00, // Menu Format
+ 0x02,0x27, // Menu DataSize
+ 0x1D, // Menu item size
+ 0x13, // Menu items
+ 0x18, // Menu icon Width
+ 0x18, // Menu icon Height
+
+ // Search
+ 0x00,0x00,0x00,0x01, // 0x00000001
+ 0x00,0x40,0x80,0x00, // 0x00408000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x53,0x65,0x61,0x72,0x63,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x56, // 56
+
+ // My_contacts
+ 0x00,0x00,0x00,0x02, // 0x00000002
+ 0x00,0x40,0x80,0x00, // 0x00408000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x4D,0x79,0x20,0x63,0x6F,0x6E,0x74,0x61,0x63,0x74,0x73,0x00,0x00,0x00,0x00,0x00,
+ 0x52, // 52
+
+ // Connections
+ 0x00,0x00,0x00,0x03, // 0x00000003
+ 0x00,0x40,0x80,0x00, // 0x00408000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x43,0x6F,0x6E,0x6E,0x65,0x63,0x74,0x69,0x6F,0x6E,0x73,0x00,0x00,0x00,0x00,0x00,
+ 0x53, // 53
+
+ // Visibility
+ 0x00,0x00,0x00,0x04, // 0x00000004
+ 0x00,0x40,0x80,0x00, // 0x00408000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x56,0x69,0x73,0x69,0x62,0x69,0x6C,0x69,0x74,0x79,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x54, // 54
+
+ // On/Off
+ 0x00,0x00,0x00,0x05, // 0x00000005
+ 0x00,0x00,0x80,0x00, // 0x00008000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x4F,0x6E,0x2F,0x4F,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x55, // 55
+
+ // _
+ 0x00,0x00,0x00,0x11, // 0x00000011
+ 0x00,0x00,0x03,0x00, // 0x00000300
+ 0x12,0xFF,0x00,0x01, // 18 ,255,0 ,1
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x57, // 57
+
+ // _
+ 0x00,0x00,0x00,0x12, // 0x00000012
+ 0x00,0x00,0x10,0x00, // 0x00001000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x57, // 57
+
+ // _
+ 0x00,0x00,0x00,0x13, // 0x00000013
+ 0x00,0x00,0x03,0x00, // 0x00000300
+ 0x14,0xF6,0x00,0x01, // 20 ,246,0 ,1
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x57, // 57
+
+ // Visible
+ 0x00,0x00,0x00,0x14, // 0x00000014
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x11,0xEB,0x00,0x00, // 17 ,235,0 ,0
+ 0x56,0x69,0x73,0x69,0x62,0x6C,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5A, // 5A
+
+ // Invisible
+ 0x00,0x00,0x00,0x24, // 0x00000024
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x11,0xEA,0x00,0x00, // 17 ,234,0 ,0
+ 0x49,0x6E,0x76,0x69,0x73,0x69,0x62,0x6C,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5B, // 5B
+
+ // On
+ 0x00,0x00,0x00,0x15, // 0x00000015
+ 0x00,0x00,0x00,0x80, // 0x00000080
+ 0x03,0xEB,0x00,0x00, // 3 ,235,0 ,0
+ 0x4F,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5C, // 5C
+
+ // Off
+ 0x00,0x00,0x00,0x25, // 0x00000025
+ 0x00,0x40,0x00,0x80, // 0x00400080
+ 0x03,0xEA,0x00,0x00, // 3 ,234,0 ,0
+ 0x4F,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5D, // 5D
+
+ // _
+ 0x00,0x00,0x01,0x11, // 0x00000111
+ 0x00,0x00,0x03,0x08, // 0x00000308
+ 0x13,0xF2,0x00,0x01, // 19 ,242,0 ,1
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x57, // 57
+
+ // _
+ 0x00,0x00,0x01,0x12, // 0x00000112
+ 0x00,0x10,0x02,0x08, // 0x00100208
+ 0x13,0xF2,0x00,0x02, // 19 ,242,0 ,2
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x57, // 57
+
+ // Disconnect
+ 0x00,0x00,0x01,0x13, // 0x00000113
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x14,0xF0,0x00,0x00, // 20 ,240,0 ,0
+ 0x44,0x69,0x73,0x63,0x6F,0x6E,0x6E,0x65,0x63,0x74,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x59, // 59
+
+ // _
+ 0x00,0x00,0x11,0x11, // 0x00001111
+ 0x00,0x00,0x03,0x00, // 0x00000300
+ 0x10,0xF5,0x00,0x00, // 16 ,245,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x57, // 57
+
+ // Delete
+ 0x00,0x00,0x11,0x12, // 0x00001112
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x13,0xF1,0x00,0x00, // 19 ,241,0 ,0
+ 0x44,0x65,0x6C,0x65,0x74,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x34, // 34
+
+ // Connect
+ 0x00,0x00,0x21,0x12, // 0x00002112
+ 0x00,0x00,0x00,0x00, // 0x00000000
+ 0x00,0x00,0x00,0x01, // 0 ,0 ,0 ,1
+ 0x43,0x6F,0x6E,0x6E,0x65,0x63,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x58, // 58
+
+ // _
+ 0x00,0x01,0x21,0x12, // 0x00012112
+ 0x00,0x00,0x03,0x08, // 0x00000308
+ 0x10,0xF5,0x00,0x00, // 16 ,245,0 ,0
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x57, // 57
+};
diff --git a/AT91SAM7S256/Source/Test1.txt b/AT91SAM7S256/Source/Test1.txt
new file mode 100644
index 0000000..9c1d663
--- /dev/null
+++ b/AT91SAM7S256/Source/Test1.txt
@@ -0,0 +1,17 @@
+const BMPMAP Test1[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x04,0x00, // Graphics DataSize
+ 0x00, // Graphics Start X
+ 0x00, // Graphics Start Y
+ 0x80, // Graphics Width
+ 0x40, // Graphics Height
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+};
diff --git a/AT91SAM7S256/Source/Test2.txt b/AT91SAM7S256/Source/Test2.txt
new file mode 100644
index 0000000..2419c27
--- /dev/null
+++ b/AT91SAM7S256/Source/Test2.txt
@@ -0,0 +1,17 @@
+const BMPMAP Test2[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x04,0x00, // Graphics DataSize
+ 0x00, // Graphics Start X
+ 0x00, // Graphics Start Y
+ 0x80, // Graphics Width
+ 0x40, // Graphics Height
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/Ui.txt b/AT91SAM7S256/Source/Ui.txt
new file mode 100644
index 0000000..e3f736d
--- /dev/null
+++ b/AT91SAM7S256/Source/Ui.txt
@@ -0,0 +1,60 @@
+const TXT Ui[] =
+{
+ 0x05,0x00, // Text Format
+ 0x03,0x63, // Text DataSize
+ 0x01, // ItemsX
+ 0x33, // ItemsY
+ 0x11, // ItemCharsX
+ 0x01, // ItemCharsY
+ 'C','o','n','n','e','c','t','i','n','g', 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'L','i','n','e',' ','i','s',' ','b','u','s','y', 0 , 0 , 0 , 0 , 0 ,
+ 'F','a','i','l','e','d','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'C','o','n','n','e','c','t','i','o','n','?', 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'S','e','n','d','i','n','g',' ','f','i','l','e', 0 , 0 , 0 , 0 , 0 ,
+ 'F','a','i','l','e','d','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'T','u','r','n','i','n','g',' ','o','n', 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'F','a','i','l','e','d','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'T','u','r','n','i','n','g',' ','o','f','f', 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'F','a','i','l','e','d','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'S','e','a','r','c','h','i','n','g', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'A','b','o','r','t','e','d','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'F','a','i','l','e','d','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'F','a','i','l','e','d','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'F','a','i','l','e','d','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'M','e','m','o','r','y',' ','f','u','l','l','!', 0 , 0 , 0 , 0 , 0 ,
+ 'F','i','l','e',' ','s','a','v','e','d', 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'F','i','l','e',' ','e','x','i','s','t','s', 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'o','v','e','r','w','r','i','t','e','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'F','i','l','e',' ','d','e','l','e','t','e','d', 0 , 0 , 0 , 0 , 0 ,
+ 'F','i','l','e','s', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'd','e','l','e','t','e','d', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'R','u','n','n','i','n','g', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'A','b','o','r','t','e','d','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'D','o','n','e', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'F','i','l','e',' ','e','r','r','o','r','!', 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'D','e','l','e','t','i','n','g',' ','a','l','l', 0 , 0 , 0 , 0 , 0 ,
+ '%','s',' ','f','i','l','e','s','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'S','o','u','n','d', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'S','o','f','t','w','a','r','e', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'N','X','T', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'T','r','y',' ','M','e', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'D','a','t','a','l','o','g', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'P','a','s','s','k','e','y',':', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'F','i','l','e',' ','n','a','m','e',':', 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'P','l','e','a','s','e',' ','u','s','e',' ','p','o','r','t',':', 0 ,
+ '1',' ','-',' ','T','o','u','c','h',' ','S','e','n','s','o','r', 0 ,
+ '2',' ','-',' ','S','o','u','n','d',' ','S','e','n','s','o','r', 0 ,
+ '3',' ','-',' ','L','i','g','h','t',' ','S','e','n','s','o','r', 0 ,
+ '4',' ','-',' ','U','l','t','r','a','s','o','n','i','c',' ',' ', 0 ,
+ 'B','/','C',' ','-',' ','L','/','R',' ','m','o','t','o','r','s', 0 ,
+ 'S','e','l','e','c','t', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'S','e','l','e','c','t', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'S','e','l','e','c','t', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'B','T',' ','s','a','v','e',' ','d','a','t','a', 0 , 0 , 0 , 0 , 0 ,
+ 'e','r','r','o','r','!', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'B','T',' ','s','t','o','r','e',' ','i','s', 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'f','u','l','l',' ','e','r','r','o','r','!', 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'B','T',' ','u','n','k','n','o','w','n', 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 'a','d','d','r','.',' ','e','r','r','o','r','!', 0 , 0 , 0 , 0 , 0 ,
+ 'N','e','v','e','r', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
+};
diff --git a/AT91SAM7S256/Source/Wait.txt b/AT91SAM7S256/Source/Wait.txt
new file mode 100644
index 0000000..a29d06b
--- /dev/null
+++ b/AT91SAM7S256/Source/Wait.txt
@@ -0,0 +1,12 @@
+const BMPMAP Wait[] =
+{
+ 0x02,0x00, // Graphics Format
+ 0x00,0x48, // Graphics DataSize
+ 0x00, // Graphics Start X
+ 0x08, // Graphics Start Y
+ 0x18, // Graphics Width
+ 0x18, // Graphics Height
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC3,0x24,0x98,0xC2,0x98,0x24,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
diff --git a/AT91SAM7S256/Source/c_button.c b/AT91SAM7S256/Source/c_button.c
new file mode 100644
index 0000000..d702dd1
--- /dev/null
+++ b/AT91SAM7S256/Source/c_button.c
@@ -0,0 +1,134 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:58 $
+//
+// Filename $Workfile:: c_button.c $
+//
+// Version $Revision:: 16 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_button.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "modules.h"
+#include "c_button.h"
+#include "c_button.iom"
+#include "c_button.h"
+#include "d_button.h"
+
+#define BTN_PRESCALER 2
+
+enum
+{
+ LONG_TIME = (2000/BTN_PRESCALER)
+};
+
+static IOMAPBUTTON IOMapButton;
+static VARSBUTTON VarsButton;
+static UBYTE BtnCnt;
+
+const HEADER cButton =
+{
+ 0x00040001L,
+ "Button",
+ cButtonInit,
+ cButtonCtrl,
+ cButtonExit,
+ (void *)&IOMapButton,
+ (void *)&VarsButton,
+ (UWORD)sizeof(IOMapButton),
+ (UWORD)sizeof(VarsButton),
+ 0x0000 //Code size - not used so far
+};
+
+
+void cButtonInit(void* pHeader)
+{
+ UBYTE Tmp;
+
+ for (Tmp = 0; Tmp < NO_OF_BTNS; Tmp++)
+ {
+ IOMapButton.State[Tmp] = 0;
+ IOMapButton.BtnCnt[Tmp].PressedCnt = 0;
+ IOMapButton.BtnCnt[Tmp].LongPressCnt = 0;
+ IOMapButton.BtnCnt[Tmp].ShortRelCnt = 0;
+ IOMapButton.BtnCnt[Tmp].LongRelCnt = 0;
+ VarsButton.Cnt[Tmp] = 0;
+ }
+ VarsButton.OldState = 0;
+ BtnCnt = 0;
+ dButtonInit(BTN_PRESCALER);
+}
+
+void cButtonCtrl(void)
+{
+ UBYTE ButtonState, Tmp, ButtonNo;
+
+ for (Tmp = 0; Tmp < NO_OF_BTNS; Tmp++)
+ {
+ IOMapButton.State[Tmp] &= ~PRESSED_EV;
+ }
+ if (++BtnCnt >= BTN_PRESCALER)
+ {
+ BtnCnt = 0;
+ dButtonRead(&ButtonState);
+
+ ButtonNo = 0x01;
+ for (Tmp = 0; Tmp < NO_OF_BTNS; Tmp++)
+ {
+ if (ButtonState & ButtonNo)
+ {
+ if (LONG_TIME >= (VarsButton.Cnt[Tmp]))
+ {
+ (VarsButton.Cnt[Tmp])++;
+ }
+ IOMapButton.State[Tmp] = PRESSED_STATE;
+ if (!((VarsButton.OldState) & ButtonNo))
+ {
+
+ /* Button just pressed */
+ (IOMapButton.State[Tmp]) |= PRESSED_EV;
+ (IOMapButton.BtnCnt[Tmp].PressedCnt)++;
+ VarsButton.Cnt[Tmp] = 0;
+ }
+ else
+ {
+ if (LONG_TIME == VarsButton.Cnt[Tmp])
+ {
+ IOMapButton.State[Tmp] |= LONG_PRESSED_EV;
+ (IOMapButton.BtnCnt[Tmp].LongPressCnt)++;
+ }
+ }
+ }
+ else
+ {
+ IOMapButton.State[Tmp] = 0x00;
+ if ((VarsButton.OldState) & ButtonNo)
+ {
+ if (VarsButton.Cnt[Tmp] > LONG_TIME)
+ {
+ IOMapButton.State[Tmp] = LONG_RELEASED_EV;
+ (IOMapButton.BtnCnt[Tmp].LongRelCnt)++;
+
+ }
+ else
+ {
+ IOMapButton.State[Tmp] = SHORT_RELEASED_EV;
+ (IOMapButton.BtnCnt[Tmp].ShortRelCnt)++;
+ }
+ }
+ }
+ ButtonNo <<= 1;
+ IOMapButton.BtnCnt[Tmp].RelCnt = ((IOMapButton.BtnCnt[Tmp].ShortRelCnt) + (IOMapButton.BtnCnt[Tmp].LongRelCnt));
+ }
+ VarsButton.OldState = ButtonState;
+ }
+}
+
+void cButtonExit(void)
+{
+ dButtonExit();
+}
diff --git a/AT91SAM7S256/Source/c_button.h b/AT91SAM7S256/Source/c_button.h
new file mode 100644
index 0000000..abb1b2b
--- /dev/null
+++ b/AT91SAM7S256/Source/c_button.h
@@ -0,0 +1,37 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:58 $
+//
+// Filename $Workfile:: c_button.h $
+//
+// Version $Revision:: 6 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_button.h $
+//
+// Platform C
+//
+
+#ifndef C_BUTTON
+#define C_BUTTON
+
+#ifdef INCLUDE_OS
+extern const HEADER cButton;
+#endif
+
+#include "c_button.iom"
+
+
+typedef struct
+{
+ UWORD Cnt[NO_OF_BTNS];
+ UBYTE OldState;
+}VARSBUTTON;
+
+void cButtonInit(void* pHeader);
+void cButtonCtrl(void);
+void cButtonExit(void);
+
+extern const HEADER cButton;
+
+#endif
diff --git a/AT91SAM7S256/Source/c_button.iom b/AT91SAM7S256/Source/c_button.iom
new file mode 100644
index 0000000..24064a2
--- /dev/null
+++ b/AT91SAM7S256/Source/c_button.iom
@@ -0,0 +1,61 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:58 $
+//
+// Filename $Workfile:: c_button.iom $
+//
+// Version $Revision:: 10 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_button.i $
+//
+// Platform C
+//
+
+#ifndef CBUTTON_IOM
+#define CBUTTON_IOM
+
+#define pMapButton ((IOMAPBUTTON*)(pHeaders[ENTRY_BUTTON]->pIOMap))
+
+enum
+{
+ BTN1,
+ BTN2,
+ BTN3,
+ BTN4,
+ NO_OF_BTNS
+};
+
+/* Costants related to State */
+enum
+{
+ PRESSED_EV = 0x01,
+ SHORT_RELEASED_EV = 0x02,
+ LONG_PRESSED_EV = 0x04,
+ LONG_RELEASED_EV = 0x08,
+ PRESSED_STATE = 0x80
+};
+
+typedef struct
+{
+ UBYTE PressedCnt;
+ UBYTE LongPressCnt;
+ UBYTE ShortRelCnt;
+ UBYTE LongRelCnt;
+ UBYTE RelCnt;
+ UBYTE SpareOne;
+ UBYTE SpareTwo;
+ UBYTE SpareThree;
+}BTNCNT;
+
+typedef struct
+{
+ BTNCNT BtnCnt[NO_OF_BTNS];
+ UBYTE State[NO_OF_BTNS];
+}IOMAPBUTTON;
+
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_cmd.c b/AT91SAM7S256/Source/c_cmd.c
new file mode 100644
index 0000000..9b83c14
--- /dev/null
+++ b/AT91SAM7S256/Source/c_cmd.c
@@ -0,0 +1,6292 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 28-03-07 14:53 $
+//
+// Filename $Workfile:: c_cmd.c $
+//
+// Version $Revision:: 67 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_cmd.c $
+//
+// Platform C
+//
+
+//
+// File Description:
+// This file contains the virtual machine implementation to run bytecode
+// programs compatible with LEGO MINDSTORMS NXT Software 1.0.
+//
+// This module (c_cmd) is also responsible for reading the system timer
+// (d_timer) and returning on 1 ms timer boundaries.
+//
+
+#include "stdconst.h"
+#include "modules.h"
+
+#include "c_cmd.iom"
+#include "c_output.iom"
+#include "c_input.iom"
+#include "c_loader.iom"
+#include "c_ui.iom"
+#include "c_sound.iom"
+#include "c_button.iom"
+#include "c_display.iom"
+#include "c_comm.iom"
+#include "c_lowspeed.iom"
+
+#include "c_cmd.h"
+#include "c_cmd_bytecodes.h"
+#include "d_timer.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+static IOMAPCMD IOMapCmd;
+static VARSCMD VarsCmd;
+static HEADER **pHeaders;
+
+const HEADER cCmd =
+{
+ 0x00010001L,
+ "Command",
+ cCmdInit,
+ cCmdCtrl,
+ cCmdExit,
+ (void *)&IOMapCmd,
+ (void *)&VarsCmd,
+ (UWORD)sizeof(IOMapCmd),
+ (UWORD)sizeof(VarsCmd),
+ 0x0000 //Code size - not used so far
+};
+
+#if ENABLE_VM
+
+// c_cmd_drawing.inc is just another C source file
+// (the graphics implementation was split off for practical file management reasons)
+#include "c_cmd_drawing.inc"
+
+
+//
+//Function pointers to sub-interpreters
+//This table is indexed by arity
+//Unary operations can have arity of 1 or 2 (some need a destination)
+//All instructions taking 4 or more operands are handled as "Other"
+//
+static pInterp InterpFuncs[INTERP_COUNT] =
+{
+ cCmdInterpNoArg,
+ cCmdInterpUnop1,
+ cCmdInterpUnop2,
+ cCmdInterpBinop,
+ cCmdInterpOther
+};
+
+//
+//Function pointers to SysCall implementations
+//See interpreter for OP_SYSCALL
+//
+static pSysCall SysCallFuncs[SYSCALL_COUNT] =
+{
+ cCmdWrapFileOpenRead,
+ cCmdWrapFileOpenWrite,
+ cCmdWrapFileOpenAppend,
+ cCmdWrapFileRead,
+ cCmdWrapFileWrite,
+ cCmdWrapFileClose,
+ cCmdWrapFileResolveHandle,
+ cCmdWrapFileRename,
+ cCmdWrapFileDelete,
+ cCmdWrapSoundPlayFile,
+ cCmdWrapSoundPlayTone,
+ cCmdWrapSoundGetState,
+ cCmdWrapSoundSetState,
+ cCmdWrapDrawText,
+ cCmdWrapDrawPoint,
+ cCmdWrapDrawLine,
+ cCmdWrapDrawCircle,
+ cCmdWrapDrawRect,
+ cCmdWrapDrawPicture,
+ cCmdWrapSetScreenMode,
+ cCmdWrapReadButton,
+ cCmdWrapCommLSWrite,
+ cCmdWrapCommLSRead,
+ cCmdWrapCommLSCheckStatus,
+ cCmdWrapRandomNumber,
+ cCmdWrapGetStartTick,
+ cCmdWrapMessageWrite,
+ cCmdWrapMessageRead,
+ cCmdWrapCommBTCheckStatus,
+ cCmdWrapCommBTWrite,
+ cCmdWrapCommBTRead,
+ cCmdWrapKeepAlive,
+ cCmdWrapIOMapRead,
+ cCmdWrapIOMapWrite
+};
+
+//
+//Next set of arrays are lookup tables for IOM access bytecodes
+//
+TYPE_CODE IO_TYPES_IN[IO_IN_FIELD_COUNT] =
+{
+ //IO_IN0
+ TC_UBYTE, //IO_IN_TYPE
+ TC_UBYTE, //IO_IN_MODE
+ TC_UWORD, //IO_IN_ADRAW
+ TC_UWORD, //IO_IN_NORMRAW
+ TC_SWORD, //IO_IN_SCALED_VAL
+ TC_UBYTE, //IO_IN_INVALID_DATA
+
+ //IO_IN1
+ TC_UBYTE, //IO_IN_TYPE
+ TC_UBYTE, //IO_IN_MODE
+ TC_UWORD, //IO_IN_ADRAW
+ TC_UWORD, //IO_IN_NORMRAW
+ TC_SWORD, //IO_IN_SCALED_VAL
+ TC_UBYTE, //IO_IN_INVALID_DATA
+
+ //IO_IN2
+ TC_UBYTE, //IO_IN_TYPE
+ TC_UBYTE, //IO_IN_MODE
+ TC_UWORD, //IO_IN_ADRAW
+ TC_UWORD, //IO_IN_NORMRAW
+ TC_SWORD, //IO_IN_SCALED_VAL
+ TC_UBYTE, //IO_IN_INVALID_DATA
+
+ //IO_IN3
+ TC_UBYTE, //IO_IN_TYPE
+ TC_UBYTE, //IO_IN_MODE
+ TC_UWORD, //IO_IN_ADRAW
+ TC_UWORD, //IO_IN_NORMRAW
+ TC_SWORD, //IO_IN_SCALED_VAL
+ TC_UBYTE, //IO_IN_INVALID_DATA
+};
+
+TYPE_CODE IO_TYPES_OUT[IO_OUT_FIELD_COUNT] =
+{
+ //IO_OUT0
+ TC_UBYTE, //IO_OUT_FLAGS
+ TC_UBYTE, //IO_OUT_MODE
+ TC_SBYTE, //IO_OUT_SPEED
+ TC_SBYTE, //IO_OUT_ACTUAL_SPEED
+ TC_SLONG, //IO_OUT_TACH_COUNT
+ TC_ULONG, //IO_OUT_TACH_LIMIT
+ TC_UBYTE, //IO_OUT_RUN_STATE
+ TC_SBYTE, //IO_OUT_TURN_RATIO
+ TC_UBYTE, //IO_OUT_REG_MODE
+ TC_UBYTE, //IO_OUT_OVERLOAD
+ TC_UBYTE, //IO_OUT_REG_P_VAL
+ TC_UBYTE, //IO_OUT_REG_I_VAL
+ TC_UBYTE, //IO_OUT_REG_D_VAL
+ TC_SLONG, //IO_OUT_BLOCK_TACH_COUNT
+ TC_SLONG, //IO_OUT_ROTATION_COUNT
+
+ //IO_OUT1
+ TC_UBYTE, //IO_OUT_FLAGS
+ TC_UBYTE, //IO_OUT_MODE
+ TC_SBYTE, //IO_OUT_SPEED
+ TC_SBYTE, //IO_OUT_ACTUAL_SPEED
+ TC_SLONG, //IO_OUT_TACH_COUNT
+ TC_ULONG, //IO_OUT_TACH_LIMIT
+ TC_UBYTE, //IO_OUT_RUN_STATE
+ TC_SBYTE, //IO_OUT_TURN_RATIO
+ TC_UBYTE, //IO_OUT_REG_MODE
+ TC_UBYTE, //IO_OUT_OVERLOAD
+ TC_UBYTE, //IO_OUT_REG_P_VAL
+ TC_UBYTE, //IO_OUT_REG_I_VAL
+ TC_UBYTE, //IO_OUT_REG_D_VAL
+ TC_SLONG, //IO_OUT_BLOCK_TACH_COUNT
+ TC_SLONG, //IO_OUT_ROTATION_COUNT
+
+ //IO_OUT2
+ TC_UBYTE, //IO_OUT_FLAGS
+ TC_UBYTE, //IO_OUT_MODE
+ TC_SBYTE, //IO_OUT_SPEED
+ TC_SBYTE, //IO_OUT_ACTUAL_SPEED
+ TC_SLONG, //IO_OUT_TACH_COUNT
+ TC_ULONG, //IO_OUT_TACH_LIMIT
+ TC_UBYTE, //IO_OUT_RUN_STATE
+ TC_SBYTE, //IO_OUT_TURN_RATIO
+ TC_UBYTE, //IO_OUT_REG_MODE
+ TC_UBYTE, //IO_OUT_OVERLOAD
+ TC_UBYTE, //IO_OUT_REG_P_VAL
+ TC_UBYTE, //IO_OUT_REG_I_VAL
+ TC_UBYTE, //IO_OUT_REG_D_VAL
+ TC_SLONG, //IO_OUT_BLOCK_TACH_COUNT
+ TC_SLONG, //IO_OUT_ROTATION_COUNT
+};
+
+
+TYPE_CODE * IO_TYPES[2] =
+{
+ IO_TYPES_IN,
+ IO_TYPES_OUT
+};
+
+//Actual pointers filled in during cCmdInit()
+void * IO_PTRS_IN[IO_IN_FIELD_COUNT];
+void * IO_PTRS_OUT[IO_OUT_FIELD_COUNT];
+
+void ** IO_PTRS[2] =
+{
+ IO_PTRS_IN,
+ IO_PTRS_OUT
+};
+
+
+//cCmdHandleRemoteCommands is the registered handler for "direct" command protocol packets
+//It is only intended to be called via c_comm's main protocol handler
+UWORD cCmdHandleRemoteCommands(UBYTE * pInBuf, UBYTE * pOutBuf, UBYTE * pLen)
+{
+ NXT_STATUS RCStatus = NO_ERR;
+ //Response packet length. Always includes RCStatus byte.
+ ULONG ResponseLen = 1;
+ //Boolean flag to send a response. TRUE unless overridden below.
+ ULONG SendResponse = TRUE;
+ //Boolean flag if we are handling a reply telegram. FALSE unless overridden.
+ ULONG IncomingReply = FALSE;
+ ULONG i, FirstPort, LastPort;
+ UWORD LStatus;
+ UWORD Count, QueueID;
+ UBYTE * pData;
+
+ //Illegal call, give up
+ if (pInBuf == NULL || pLen == NULL)
+ {
+ NXT_BREAK;
+ return (0xFFFF);
+ }
+
+ //No output buffer provided, so skip any work related to returning a response
+ if (pOutBuf == NULL)
+ SendResponse = FALSE;
+
+ //If first byte identifies this as a reply telegram, we have different work to do.
+ if (pInBuf[0] == 0x02)
+ {
+ IncomingReply = TRUE;
+ //Reply telegrams never get responses, even if caller provided a buffer.
+ SendResponse = FALSE;
+ }
+
+ //Advance pInBuf past command type byte
+ pInBuf++;
+
+ if (!IncomingReply)
+ {
+ switch(pInBuf[0])
+ {
+ case RC_START_PROGRAM:
+ {
+ //Check that file exists. If not, return error
+ //!!! Should return standard loader file error in cases like this??
+ //!!! Proper solution would also check file mode to avoid confusing errors
+ if (LOADER_ERR(LStatus = pMapLoader->pFunc(FINDFIRST, (&pInBuf[1]), NULL, NULL)) != SUCCESS)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ //Close file handle returned by FINDFIRST
+ pMapLoader->pFunc(CLOSE, LOADER_HANDLE_P(LStatus), NULL, NULL);
+
+ //File must exist, so inform UI to attempt execution in the usual way (enables consistent feedback)
+ pMapUi->Flags |= UI_EXECUTE_LMS_FILE;
+ strncpy((PSZ)(pMapUi->LMSfilename), (PSZ)(&pInBuf[1]), FILENAME_LENGTH + 1);
+ }
+ break;
+
+ case RC_STOP_PROGRAM:
+ {
+ if (VarsCmd.ActiveProgHandle == NOT_A_HANDLE)
+ {
+ RCStatus = ERR_NO_PROG;
+ break;
+ }
+
+ IOMapCmd.DeactivateFlag = TRUE;
+ }
+ break;
+
+ case RC_PLAY_SOUND_FILE:
+ {
+ if (LOADER_ERR(pMapLoader->pFunc(FINDFIRST, (&pInBuf[2]), NULL, NULL)) != SUCCESS)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ //Close file handle returned by FINDFIRST
+ pMapLoader->pFunc(CLOSE, LOADER_HANDLE_P(LStatus), NULL, NULL);
+
+ if (pInBuf[1] == FALSE)
+ pMapSound->Mode = SOUND_ONCE;
+ else //Any non-zero value treated as TRUE
+ pMapSound->Mode = SOUND_LOOP;
+
+ strncpy((PSZ)pMapSound->SoundFilename, (PSZ)(&pInBuf[2]), FILENAME_LENGTH + 1);
+ pMapSound->Flags |= SOUND_UPDATE;
+ }
+ break;
+
+ case RC_PLAY_TONE:
+ {
+ pMapSound->Mode = SOUND_TONE;
+ //!!! Range check valid values?
+ memcpy((PSZ)(&(pMapSound->Freq)), (PSZ)(&pInBuf[1]), 2);
+ memcpy((PSZ)(&(pMapSound->Duration)), (PSZ)(&pInBuf[3]), 2);
+
+ pMapSound->Flags |= SOUND_UPDATE;
+ }
+ break;
+
+ case RC_SET_OUT_STATE:
+ {
+ //Don't do anything if illegal port specification is made
+ if (pInBuf[1] >= NO_OF_OUTPUTS && pInBuf[1] != 0xFF)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ //0xFF is protocol defined to mean "all ports".
+ if (pInBuf[1] == 0xFF)
+ {
+ FirstPort = 0;
+ LastPort = NO_OF_OUTPUTS - 1;
+ }
+ else
+ FirstPort = LastPort = pInBuf[1];
+
+ for (i = FirstPort; i <= LastPort; i++)
+ {
+ pMapOutPut->Outputs[i].Speed = pInBuf[2];
+ pMapOutPut->Outputs[i].Mode = pInBuf[3];
+ pMapOutPut->Outputs[i].RegMode = pInBuf[4];
+ pMapOutPut->Outputs[i].SyncTurnParameter = pInBuf[5];
+ pMapOutPut->Outputs[i].RunState = pInBuf[6];
+ memcpy((PSZ)(&(pMapOutPut->Outputs[i].TachoLimit)), (PSZ)(&pInBuf[7]), 4);
+
+ pMapOutPut->Outputs[i].Flags |= UPDATE_MODE | UPDATE_SPEED | UPDATE_TACHO_LIMIT;
+ }
+ }
+ break;
+
+ case RC_SET_IN_MODE:
+ {
+ i = pInBuf[1];
+
+ //Don't do anything if illegal port specification is made
+ //!!! Should check against legal Types and Modes? (bitmask for Modes?)
+ if (i >= NO_OF_INPUTS)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ pMapInput->Inputs[i].SensorType = pInBuf[2];
+ pMapInput->Inputs[i].SensorMode = pInBuf[3];
+
+ //Set InvalidData flag automatically since type may have changed
+ pMapInput->Inputs[i].InvalidData = TRUE;
+ }
+ break;
+
+ case RC_GET_OUT_STATE:
+ {
+ if (SendResponse == TRUE)
+ {
+ i = pInBuf[1];
+
+ //Return error and all zeros if illegal port specification is made
+ if (i >= NO_OF_OUTPUTS)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ memset(&(pOutBuf[ResponseLen]), 0, 22);
+ ResponseLen += 22;
+ break;
+ }
+
+ //Echo port
+ pOutBuf[ResponseLen] = i;
+ ResponseLen++;
+
+ //Power
+ pOutBuf[ResponseLen] = pMapOutPut->Outputs[i].Speed;
+ ResponseLen++;
+
+ //Mode
+ pOutBuf[ResponseLen] = pMapOutPut->Outputs[i].Mode;
+ ResponseLen++;
+
+ //RegMode
+ pOutBuf[ResponseLen] = pMapOutPut->Outputs[i].RegMode;
+ ResponseLen++;
+
+ //TurnRatio
+ pOutBuf[ResponseLen] = pMapOutPut->Outputs[i].SyncTurnParameter;
+ ResponseLen++;
+
+ //RunState
+ pOutBuf[ResponseLen] = pMapOutPut->Outputs[i].RunState;
+ ResponseLen++;
+
+ //TachoLimit ULONG
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)(&(pMapOutPut->Outputs[i].TachoLimit)), 4);
+ ResponseLen += 4;
+
+ //TachoCount SLONG
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)(&(pMapOutPut->Outputs[i].TachoCnt)), 4);
+ ResponseLen += 4;
+
+ //BlockTachoCount SLONG
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)(&(pMapOutPut->Outputs[i].BlockTachoCount)), 4);
+ ResponseLen += 4;
+
+ //RotationCount SLONG
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)(&(pMapOutPut->Outputs[i].RotationCount)), 4);
+ ResponseLen += 4;
+
+ NXT_ASSERT(ResponseLen == 23);
+ }
+ }
+ break;
+
+ case RC_GET_IN_VALS:
+ {
+ if (SendResponse == TRUE)
+ {
+ i = pInBuf[1];
+
+ //Return error and all zeros if illegal port specification is made
+ if (i >= NO_OF_INPUTS)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ memset(&(pOutBuf[ResponseLen]), 0, 13);
+ ResponseLen += 13;
+ break;
+ }
+
+ //Echo port
+ pOutBuf[ResponseLen] = i;
+ ResponseLen++;
+
+ //Set "Valid?" boolean
+ if (pMapInput->Inputs[i].InvalidData)
+ pOutBuf[ResponseLen] = FALSE;
+ else
+ pOutBuf[ResponseLen] = TRUE;
+
+ ResponseLen++;
+
+ //Set "Calibrated?" boolean
+ //!!! "Calibrated?" is a placeholder in the protocol. Always FALSE for now.
+ pOutBuf[ResponseLen] = FALSE;
+ ResponseLen++;
+
+ pOutBuf[ResponseLen] = pMapInput->Inputs[i].SensorType;
+ ResponseLen++;
+
+ pOutBuf[ResponseLen] = pMapInput->Inputs[i].SensorMode;
+ ResponseLen++;
+
+ //Set Raw, Normalized, and Scaled values
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)(&(pMapInput->Inputs[i].ADRaw)), 2);
+ ResponseLen += 2;
+
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)(&(pMapInput->Inputs[i].SensorRaw)), 2);
+ ResponseLen += 2;
+
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)(&(pMapInput->Inputs[i].SensorValue)), 2);
+ ResponseLen += 2;
+
+ //!!! Return normalized raw value in place of calibrated value for now -- see comment above
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)(&(pMapInput->Inputs[i].SensorRaw)), 2);
+ ResponseLen += 2;
+
+ NXT_ASSERT(ResponseLen == 14);
+ }
+ }
+ break;
+
+ case RC_RESET_IN_VAL:
+ {
+ i = pInBuf[1];
+
+ //Don't do anything if illegal port specification is made
+ if (i >= NO_OF_INPUTS)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ //Clear SensorValue to zero. Leave Raw and Normalized as-is, since they never accumulate running values.
+ pMapInput->Inputs[i].SensorValue = 0;
+ }
+ break;
+
+ case RC_MESSAGE_WRITE:
+ {
+ QueueID = pInBuf[1];
+ Count = pInBuf[2];
+ pData = &(pInBuf[3]);
+
+ //If Count is illegal or MsgData is not null-terminated,
+ // we can't accept it as a valid string
+ if (Count == 0 || Count > MAX_MESSAGE_SIZE || pData[Count - 1] != 0x00)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ RCStatus = cCmdMessageWrite(QueueID, pData, Count);
+
+ //ERR_MEM here means we must compact the dataspace and retry message write
+ if (RCStatus == ERR_MEM)
+ {
+ cCmdDSCompact();
+ RCStatus = cCmdMessageWrite(QueueID, pData, Count);
+ }
+ }
+ break;
+
+ case RC_RESET_POSITION:
+ {
+ i = pInBuf[1];
+
+ //Don't do anything if illegal port specification is made
+ if (i >= NO_OF_OUTPUTS)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ //pInBuf[2] is a selector
+ //FALSE: Position relative to start of last program
+ //TRUE: Position relative to start of last motor control block
+ if (pInBuf[2] == FALSE)
+ {
+ pMapOutPut->Outputs[i].Flags |= UPDATE_RESET_ROTATION_COUNT;
+ }
+ else
+ {
+ pMapOutPut->Outputs[i].Flags |= UPDATE_RESET_BLOCK_COUNT;
+ }
+ }
+ break;
+
+ case RC_GET_BATT_LVL:
+ {
+ if (SendResponse == TRUE)
+ {
+ //Return BatteryVoltage directly from IOMapUI, in mV
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)&(pMapUi->BatteryVoltage), 2);
+ ResponseLen += 2;
+ }
+ }
+ break;
+
+ case RC_STOP_SOUND:
+ {
+ //Tell sound module to stop playback, no questions asked
+ pMapSound->State = SOUND_STOP;
+ }
+ break;
+
+ case RC_KEEP_ALIVE:
+ {
+ pMapUi->Flags |= UI_RESET_SLEEP_TIMER;
+
+ if (SendResponse == TRUE)
+ {
+ //Convert to milliseconds to match external conventions
+ i = (pMapUi->SleepTimeout * 60 * 1000);
+ memcpy((PSZ)&(pOutBuf[ResponseLen]), (PSZ)&i, 4);
+ ResponseLen += 4;
+ }
+ }
+ break;
+
+ case RC_LS_GET_STATUS:
+ {
+ if (SendResponse == TRUE)
+ {
+ i = pInBuf[1];
+
+ //Don't do anything if illegal port specification is made
+ if (i >= NO_OF_LOWSPEED_COM_CHANNEL)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ RCStatus = cCmdLSCheckStatus(i);
+
+ pOutBuf[ResponseLen] = cCmdLSCalcBytesReady(i);
+ ResponseLen++;
+ }
+ }
+ break;
+
+ case RC_LS_WRITE:
+ {
+ i = pInBuf[1];
+ Count = pInBuf[2];
+
+ //Don't do anything if illegal port specification is made
+ if (i >= NO_OF_LOWSPEED_COM_CHANNEL)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ RCStatus = cCmdLSWrite(i, Count, &(pInBuf[4]), pInBuf[3]);
+ }
+ break;
+
+ case RC_LS_READ:
+ {
+ if (SendResponse == TRUE)
+ {
+ i = pInBuf[1];
+
+ //Don't do anything if illegal port specification is made
+ if (i >= NO_OF_LOWSPEED_COM_CHANNEL)
+ {
+ RCStatus = ERR_RC_ILLEGAL_VAL;
+ break;
+ }
+
+ //Get channel status and number of bytes available to read
+ RCStatus = cCmdLSCheckStatus(i);
+ Count = cCmdLSCalcBytesReady(i);
+
+ pOutBuf[ResponseLen] = (UBYTE)Count;
+ ResponseLen++;
+
+ //If channel is ready and has data ready for us, put the data into outgoing buffer
+ if (!IS_ERR(RCStatus) && Count > 0)
+ {
+ RCStatus = cCmdLSRead(i, (UBYTE)Count, &(pOutBuf[ResponseLen]));
+ ResponseLen += Count;
+ }
+
+ //Pad remaining data bytes with zeroes
+ Count = 16 - Count;
+ memset(&(pOutBuf[ResponseLen]), 0, Count);
+ ResponseLen += Count;
+ }
+ }
+ break;
+
+ case RC_GET_CURR_PROGRAM:
+ {
+ if (SendResponse == TRUE)
+ {
+ //If there's no active program, return error and empty name buffer
+ if (VarsCmd.ActiveProgHandle == NOT_A_HANDLE)
+ {
+ RCStatus = ERR_NO_PROG;
+ memset(&(pOutBuf[ResponseLen]), 0, FILENAME_LENGTH + 1);
+ }
+ //Else, copy out stashed program name
+ else
+ {
+ strncpy((PSZ)(&(pOutBuf[ResponseLen])), (PSZ)(VarsCmd.ActiveProgName), FILENAME_LENGTH + 1);
+ }
+
+ //Regardless, we've copied out a filename's worth of bytes...
+ ResponseLen += FILENAME_LENGTH + 1;
+ }
+ }
+ break;
+
+ case RC_MESSAGE_READ:
+ {
+ if (SendResponse == TRUE)
+ {
+ QueueID = pInBuf[1];
+
+ //Fill in response with remote mailbox number so remote device knows where to store this message.
+ pOutBuf[ResponseLen] = pInBuf[2];
+ ResponseLen++;
+
+ RCStatus = cCmdMessageGetSize(QueueID, &Count);
+ pOutBuf[ResponseLen] = Count;
+ ResponseLen++;
+
+ if (!IS_ERR(RCStatus) && Count > 0)
+ {
+ pData = &(pOutBuf[ResponseLen]);
+ RCStatus = cCmdMessageRead(QueueID, pData, Count, (pInBuf[3]));
+ //If cCmdMessageRead encountered an error, there is no real data in the buffer, so clear it out (below)
+ if (IS_ERR(RCStatus))
+ Count = 0;
+ else
+ ResponseLen += Count;
+ }
+
+ //Pad remaining data bytes with zeroes
+ Count = MAX_MESSAGE_SIZE - Count;
+ memset(&(pOutBuf[ResponseLen]), 0, Count);
+ ResponseLen += Count;
+ }
+ }
+ break;
+
+ default:
+ {
+ //Unknown remote command -- still inform client to not expect any response bytes
+ NXT_BREAK;
+ RCStatus = ERR_RC_UNKNOWN_CMD;
+ }
+ break;
+ };
+ }
+ //Handle reply telegrams
+ else
+ {
+ switch(pInBuf[0])
+ {
+ case RC_MESSAGE_READ:
+ {
+ QueueID = pInBuf[2];
+ Count = pInBuf[3];
+ pData = &(pInBuf[4]);
+
+ //This is a response to our request to read a message from a remote mailbox.
+ //If telegram looks valid, write the resulting message into our local mailbox.
+ //(If MsgData is not null-terminated, we can't accept it as a valid string.)
+ if (!IS_ERR((SBYTE)(pInBuf[1]))
+ && Count > 0
+ && Count <= MAX_MESSAGE_SIZE
+ && pData[Count - 1] == 0x00)
+ {
+ RCStatus = cCmdMessageWrite(QueueID, pData, Count);
+
+ //ERR_MEM here means we must compact the dataspace
+ if (RCStatus == ERR_MEM)
+ {
+ cCmdDSCompact();
+ RCStatus = cCmdMessageWrite(QueueID, pData, Count);
+ }
+ }
+
+ //If telegram doesn't check out, do nothing. No errors are ever returned for reply telegrams.
+ }
+ break;
+
+ default:
+ {
+ //Unhandled reply telegram. Do nothing.
+ //!!! Could/should stash unhandled/all replies somewhere so a syscall could read them
+ }
+ break;
+ };
+ }
+
+ if (SendResponse == TRUE)
+ {
+ //Return response length (pointer checked above)
+ *pLen = (UBYTE)ResponseLen;
+ //Fill in status byte
+ pOutBuf[0] = (UBYTE)(RCStatus);
+ }
+ else
+ *pLen = 0;
+
+ return (0);
+}
+
+
+//
+// Standard interface functions
+//
+
+void cCmdInit(void* pHeader)
+{
+ ULONG i;
+
+ pHeaders = pHeader;
+
+ IOMapCmd.pRCHandler = &cCmdHandleRemoteCommands;
+
+#if defined(ARM_DEBUG)
+ //Init run-time assert tracking variables
+ VarsCmd.AssertFlag = FALSE;
+ VarsCmd.AssertLine = 0;
+#endif
+
+ //Initialize IO_PTRS_OUT
+ for (i = 0; i < NO_OF_OUTPUTS; i++)
+ {
+ IO_PTRS_OUT[IO_OUT_FLAGS + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].Flags);
+ IO_PTRS_OUT[IO_OUT_MODE + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].Mode);
+ IO_PTRS_OUT[IO_OUT_SPEED + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].Speed);
+ IO_PTRS_OUT[IO_OUT_ACTUAL_SPEED + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].ActualSpeed);
+ IO_PTRS_OUT[IO_OUT_TACH_COUNT + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].TachoCnt);
+ IO_PTRS_OUT[IO_OUT_TACH_LIMIT + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].TachoLimit);
+ IO_PTRS_OUT[IO_OUT_RUN_STATE + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].RunState);
+ IO_PTRS_OUT[IO_OUT_TURN_RATIO + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].SyncTurnParameter);
+ IO_PTRS_OUT[IO_OUT_REG_MODE + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].RegMode);
+ IO_PTRS_OUT[IO_OUT_OVERLOAD + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].Overloaded);
+ IO_PTRS_OUT[IO_OUT_REG_P_VAL + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].RegPParameter);
+ IO_PTRS_OUT[IO_OUT_REG_I_VAL + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].RegIParameter);
+ IO_PTRS_OUT[IO_OUT_REG_D_VAL + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].RegDParameter);
+ IO_PTRS_OUT[IO_OUT_BLOCK_TACH_COUNT + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].BlockTachoCount);
+ IO_PTRS_OUT[IO_OUT_ROTATION_COUNT + i * IO_OUT_FPP] = (void*)&(pMapOutPut->Outputs[i].RotationCount);
+ }
+
+ //Initialize IO_PTRS_IN
+ for (i = 0; i < NO_OF_INPUTS; i++)
+ {
+ IO_PTRS_IN[IO_IN_TYPE + i * IO_IN_FPP] = (void*)&(pMapInput->Inputs[i].SensorType);
+ IO_PTRS_IN[IO_IN_MODE + i * IO_IN_FPP] = (void*)&(pMapInput->Inputs[i].SensorMode);
+ IO_PTRS_IN[IO_IN_ADRAW + i * IO_IN_FPP] = (void*)&(pMapInput->Inputs[i].ADRaw);
+ IO_PTRS_IN[IO_IN_NORMRAW + i * IO_IN_FPP] = (void*)&(pMapInput->Inputs[i].SensorRaw);
+ IO_PTRS_IN[IO_IN_SCALEDVAL + i * IO_IN_FPP] = (void*)&(pMapInput->Inputs[i].SensorValue);
+ IO_PTRS_IN[IO_IN_INVALID_DATA + i * IO_IN_FPP] = (void*)&(pMapInput->Inputs[i].InvalidData);
+ }
+
+ //Clear memory pool and initialize VarsCmd (cCmdDeactivateProgram effectively re-inits VarsCmd)
+ cCmdInitPool();
+ cCmdDeactivateProgram();
+
+ //Global state variables for BlueTooth communication.
+ VarsCmd.CommStat = (SWORD)SUCCESS;
+ VarsCmd.CommStatReset = (SWORD)BTBUSY;
+ VarsCmd.CommCurrConnection = 1;
+
+ //Global flags for various reset and bookkeeping scenarios
+ VarsCmd.DirtyComm = FALSE;
+ VarsCmd.DirtyDisplay = FALSE;
+
+ VarsCmd.VMState = VM_IDLE;
+
+#if defined (ARM_NXT)
+ //Make sure Pool is long-aligned
+ NXT_ASSERT(!((ULONG)(POOL_START) % SIZE_SLONG));
+#endif
+
+ IOMapCmd.ProgStatus = PROG_IDLE;
+ IOMapCmd.ActivateFlag = FALSE;
+ IOMapCmd.Awake = TRUE;
+
+ //Default offsets explicitly chosen to cause an error if used with IOMAPREAD/IOMAPWRITE
+ //Real values will be set when programs run and/or the DS is re-arranged.
+ IOMapCmd.OffsetDVA = 0xFFFF;
+ IOMapCmd.OffsetDS = 0xFFFF;
+
+ //Initialize format string and clear out FileName string
+ strncpy((PSZ)(IOMapCmd.FormatString), VM_FORMAT_STRING, VM_FORMAT_STRING_SIZE);
+ memset(IOMapCmd.FileName, 0, sizeof(IOMapCmd.FileName));
+
+ dTimerInit();
+ IOMapCmd.Tick = dTimerRead();
+
+ return;
+}
+
+
+void cCmdCtrl(void)
+{
+ UBYTE Continue = TRUE;
+ NXT_STATUS Status = NO_ERR;
+ ULONG i;
+ CLUMP_ID CurrClumpID;
+
+ switch (VarsCmd.VMState)
+ {
+ case VM_IDLE:
+ {
+ //If there's a new program to activate...
+ if (IOMapCmd.ActivateFlag == TRUE)
+ {
+ //Clear flag so we only activate once per new file
+ IOMapCmd.ActivateFlag = FALSE;
+
+ Status = cCmdActivateProgram(IOMapCmd.FileName);
+
+ //If we hit an activation error:
+ //1. Set PROG_ERROR status
+ //2. Proceed to VM_RESET1 (some unneeded work, yes, but preserves contract with UI
+ if (IS_ERR(Status))
+ {
+ IOMapCmd.ProgStatus = PROG_ERROR;
+ VarsCmd.VMState = VM_RESET1;
+ }
+ //Else start running program
+ else
+ {
+ VarsCmd.VMState = VM_RUN_FREE;
+ IOMapCmd.ProgStatus = PROG_RUNNING;
+ VarsCmd.StartTick = IOMapCmd.Tick;
+
+#if VM_BENCHMARK
+ //Re-init benchmark
+ VarsCmd.InstrCount = 0;
+ VarsCmd.Average = 0;
+ VarsCmd.OverTimeCount = 0;
+ VarsCmd.MaxOverTimeLength = 0;
+ VarsCmd.CmdCtrlCount = 0;
+ VarsCmd.CompactionCount = 0;
+ VarsCmd.LastCompactionTick = 0;
+ VarsCmd.MaxCompactionTime = 0;
+ memset(VarsCmd.OpcodeBenchmarks, 0, sizeof(VarsCmd.OpcodeBenchmarks));
+ memset(VarsCmd.SyscallBenchmarks, 0, sizeof(VarsCmd.SyscallBenchmarks));
+#endif
+ //Reset devices to a known state before we begin running
+ cCmdResetDevices();
+
+ pMapUi->Flags |= (UI_DISABLE_LEFT_RIGHT_ENTER | UI_DISABLE_EXIT);
+ }
+ }
+
+ break;
+ }
+
+ //Initialize VM internal state data and devices which must respond immediately to program ending
+ case VM_RESET1:
+ {
+ //If we aborted a program, reset devices (specifically, motors) immediately
+ //Otherwise, wait for UI to put us into PROG_RESET (gives motors a chance to brake before setting to coast)
+ //!!! This means cCmdResetDevices will get called twice on abort. Should not be a big deal.
+ if (IOMapCmd.ProgStatus == PROG_ABORT)
+ cCmdResetDevices();
+
+ //Reenable UI access to buttons
+ pMapUi->Flags &= ~(UI_DISABLE_LEFT_RIGHT_ENTER | UI_DISABLE_EXIT);
+
+#if VM_BENCHMARK
+ if (IOMapCmd.Tick != VarsCmd.StartTick)
+ VarsCmd.Average = VarsCmd.InstrCount / (IOMapCmd.Tick - VarsCmd.StartTick);
+ else
+ //It appears that we finished in 0 milliseconds. Very unlikely on ARM, so set a flag value.
+ VarsCmd.Average = 0xFFFFFFFF;
+
+ cCmdWriteBenchmarkFile();
+#endif
+
+ //Re-initialize program state data (contents of memory pool preserved)
+ //!!! Skip this step in simulator builds so helper access methods still work
+#ifndef SIM_NXT
+ cCmdDeactivateProgram();
+#endif //SIM_NXT
+
+ //If this program has taken over the display, reset it for the UI
+ cCmdRestoreDefaultScreen();
+
+ //Stop any currently playing sound and re-init volume according to UI prefs
+ pMapSound->State = SOUND_STOP;
+ pMapSound->Volume = pMapUi->Volume;
+
+ //Artificially set CommStatReset to BTBUSY to force at least one SETCMDMODE call (see VM_RESET2 case)
+ VarsCmd.CommStatReset = (SWORD)BTBUSY;
+
+ VarsCmd.VMState = VM_RESET2;
+ }
+ break;
+
+ case VM_RESET2:
+ {
+ //Reset BlueCore into "command mode" (close any open streams)
+ //Since SETCMDMODE subject to BTBUSY, we may need to make multiple calls
+ //Any CommStatReset value other than BTBUSY means our request was accepted
+ //Assumptions:
+ //Process should never take longer than UI timeout (see below), but if it does,
+ // we could be left with the stream open to an NXT peer and block out the PC.
+ //Also assuming that once SETCMDMODE request is accepted, it never fails.
+ if (VarsCmd.CommStatReset == (SWORD)BTBUSY && VarsCmd.DirtyComm == TRUE)
+ pMapComm->pFunc(SETCMDMODE, 0, 0, 0, NULL, (UWORD*)&(VarsCmd.CommStatReset));
+
+ //If UI is done displaying ending program status, move on.
+ if (IOMapCmd.ProgStatus == PROG_RESET)
+ {
+ //Reset devices whenever a program ends for any reason
+ cCmdResetDevices();
+
+ VarsCmd.DirtyComm = FALSE;
+
+ //Go to VM_IDLE state
+ VarsCmd.VMState = VM_IDLE;
+ IOMapCmd.ProgStatus = PROG_IDLE;
+ }
+ break;
+ }
+
+ case VM_RUN_FREE:
+ case VM_RUN_SINGLE:
+ {
+
+#if VM_BENCHMARK
+ //IOMapCmd.Tick currently holds the tick from the end of last cCmdCtrl call.
+ //If we don't come back here before dTimerRead() increments, the m_sched loop has taken *at least* 1 ms.
+ if (IOMapCmd.Tick != dTimerRead())
+ {
+ VarsCmd.OverTimeCount++;
+ //Record maximum magnitude of schedule loop overage, in millisecs
+ if (dTimerRead() - IOMapCmd.Tick > VarsCmd.MaxOverTimeLength)
+ VarsCmd.MaxOverTimeLength = dTimerRead() - IOMapCmd.Tick;
+ }
+ VarsCmd.CmdCtrlCount++;
+#endif
+ //Abort current program if cancel button is pressed
+ if (IOMapCmd.DeactivateFlag == TRUE || pMapButton->State[BTN1] & PRESSED_EV)
+ {
+ IOMapCmd.DeactivateFlag = FALSE;
+
+ //Clear pressed event so it doesn't get double-counted by UI
+ pMapButton->State[BTN1] &= ~PRESSED_EV;
+
+ //Go to VM_RESET1 state and report abort
+ VarsCmd.VMState = VM_RESET1;
+ IOMapCmd.ProgStatus = PROG_ABORT;
+ break;
+ }
+
+ //Assert that we have an active program
+ NXT_ASSERT(VarsCmd.ActiveProgHandle != NOT_A_HANDLE);
+
+ //Execute from at least one clump
+ do
+ {
+ if (cCmdIsClumpIDSane(VarsCmd.RunQ.Head))
+ {
+ //Stash and dequeue RunQ's head clump
+ CurrClumpID = VarsCmd.RunQ.Head;
+
+ //Execute at least one instruction from current clump
+ //Execute up to 'Priority' instructions as long as we are in VM_FREE_RUN mode
+ //Finishing/suspending a clump, BREAKOUT_REQ, or any errors will also end this loop
+ i = 0;
+ do
+ {
+ //Interpret one instruction per call, advancing PC as needed
+ Status = cCmdInterpFromClump(CurrClumpID);
+
+#if VM_BENCHMARK
+ VarsCmd.InstrCount++;
+#endif
+
+ NXT_ASSERT(!IS_ERR(Status));
+ if (IS_ERR(Status) || Status == CLUMP_DONE || Status == CLUMP_SUSPEND || Status == BREAKOUT_REQ || Status == STOP_REQ)
+ {
+ //We're done with this clump or breaking out prematurely,
+ //so break the multi-instruction loop
+ break;
+ }
+ else
+ {
+ //Count up one more instruction for this pass
+ i++;
+ }
+ } while (VarsCmd.VMState == VM_RUN_FREE && i < VarsCmd.pAllClumps[CurrClumpID].Priority);
+
+ //Only rotate RunQ on a "normal" finish, i.e. no error, clump end, or breakout request
+ if (!(IS_ERR(Status) || Status == CLUMP_DONE || Status == CLUMP_SUSPEND || Status == BREAKOUT_REQ))
+ cCmdRotateQ(&(VarsCmd.RunQ));
+ }
+
+ //Re-evaluate conditions for stopping the dataflow scheduler
+ //Halt program on all errors
+ if (IS_ERR(Status))
+ {
+ Continue = FALSE;
+
+ VarsCmd.VMState = VM_RESET1;
+ IOMapCmd.ProgStatus = PROG_ERROR;
+ }
+ else if (Status == BREAKOUT_REQ)
+ {
+ Continue = FALSE;
+ }
+ //If RunQ is empty or user requested early termination, program is done
+ else if (!cCmdIsClumpIDSane(VarsCmd.RunQ.Head) || Status == STOP_REQ)
+ {
+ Continue = FALSE;
+
+ VarsCmd.VMState = VM_RESET1;
+ IOMapCmd.ProgStatus = PROG_OK;
+ }
+ //VM_RUN_FREE means continue executing until a new ms tick rolls over
+ else if (VarsCmd.VMState == VM_RUN_FREE)
+ {
+ Continue = (IOMapCmd.Tick == dTimerRead());
+ }
+ //Otherwise execute only one pass per call
+ else //VarsCmd.VMState == VM_RUN_SINGLE
+ {
+ VarsCmd.VMState = VM_RUN_PAUSE;
+ Continue = FALSE;
+ }
+
+ } while (Continue == TRUE);
+
+ break;
+ }
+ }//END state machine switch
+
+ //Busy wait to always maintain 1ms period
+ BUSY_WAIT_NEXT_MS;
+
+ //Set tick to new value for next time 'round
+ IOMapCmd.Tick = dTimerRead();
+
+ return;
+}
+
+
+void cCmdExit(void)
+{
+ dTimerExit();
+
+ return;
+}
+
+
+NXT_STATUS cCmdReadFileHeader(UBYTE* pData, ULONG DataSize,
+ PROG_FILE_OFFSETS* pFileOffsets)
+{
+ ULONG i;
+ UBYTE * pCursor;
+ UWORD CurrOffset = 0;
+ UBYTE DepCount;
+ UWORD DopeVectorOffset;
+ UWORD FileClumpCount;
+ UBYTE FileMajor, FileMinor,
+ CompatibleMinor, CompatibleMajor,
+ CurrentMajor;
+
+ NXT_ASSERT(pData != NULL);
+
+ //Assign pCursor to point to version word inside file header
+ pCursor = (pData + VM_FORMAT_STRING_SIZE - 2);
+
+ //Decode version numbers into comparable bytes
+ FileMajor = *pCursor;
+ FileMinor = *(pCursor + 1);
+ CompatibleMajor = (UBYTE)(VM_OLDEST_COMPATIBLE_VERSION >> 8);
+ CompatibleMinor = (UBYTE)(VM_OLDEST_COMPATIBLE_VERSION);
+ CurrentMajor = (UBYTE)(FIRMWAREVERSION >> 8);
+ //CurrentMinor = (UBYTE)(FIRMWAREVERSION);
+
+ //Return ERR_VER if file lacks proper format string or version number
+ //!!! Only checking major version recommended for future development
+ if (strncmp((PSZ)pData, VM_FORMAT_STRING, VM_FORMAT_STRING_SIZE)
+ || FileMajor < CompatibleMajor || FileMinor < CompatibleMinor
+ || FileMajor > CurrentMajor)
+ {
+ NXT_BREAK;
+ return (ERR_VER);
+ }
+
+ //Advance CurrOffset past header information
+ CurrOffset += VM_FORMAT_STRING_SIZE;
+
+ //
+ //Initialize bookkeeping variables
+ //
+ VarsCmd.DataspaceCount = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ VarsCmd.DataspaceSize = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ VarsCmd.DSStaticSize = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ pFileOffsets->DSDefaultsSize = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ pFileOffsets->DynamicDefaults = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ pFileOffsets->DynamicDefaultsSize = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ VarsCmd.MemMgr.Head = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ VarsCmd.MemMgr.Tail = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ DopeVectorOffset = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ //!!! Odd code here to deal with type mismatch between file format and CLUMP_ID typedef.
+ //Neither is trivial to change, so it's best to just check the data for consistency here.
+ FileClumpCount = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ //Must have at least one clump and count can't exceed the NOT_A_CLUMP sentinel
+ if (FileClumpCount == 0 || FileClumpCount >= NOT_A_CLUMP)
+ return (ERR_FILE);
+ else
+ VarsCmd.AllClumpsCount = (CLUMP_ID)FileClumpCount;
+
+ VarsCmd.CodespaceCount = *((UWORD*)(pData + CurrOffset));
+ CurrOffset += 2;
+
+ //Can't have a valid program with no code
+ if (VarsCmd.CodespaceCount == 0)
+ return (ERR_FILE);
+
+ //
+ // Now, calculate offsets for each data segment in the file
+ //
+
+ CurrOffset += CurrOffset % 2;
+ pFileOffsets->DSTOC = CurrOffset;
+ CurrOffset += VarsCmd.DataspaceCount * sizeof(DS_TOC_ENTRY);
+
+ CurrOffset += CurrOffset % 2;
+ pFileOffsets->DSDefaults = CurrOffset;
+ CurrOffset += pFileOffsets->DSDefaultsSize;
+
+ //ClumpRecs must be aligned on even boundaries
+ CurrOffset += CurrOffset % 2;
+ pFileOffsets->Clumps = CurrOffset;
+
+ //Set cursor to start of clump records
+ pCursor = pData + CurrOffset;
+
+ //Set CurrOffset to start of dependent lists
+ CurrOffset += VarsCmd.AllClumpsCount * VM_FILE_CLUMP_REC_SIZE;
+
+ //Read dependent count from each clump record, advancing CurrOffset accordingly
+ for (i = 0; i < VarsCmd.AllClumpsCount; i++)
+ {
+ DepCount = *(pCursor + 1);
+ CurrOffset += DepCount;
+ pCursor += VM_FILE_CLUMP_REC_SIZE;
+ }
+
+ //Codespace must be aligned on even boundary
+ CurrOffset += CurrOffset % 2;
+ pFileOffsets->Codespace = CurrOffset;
+
+ //No need to read through codespace, but make sure CurrOffset ended up sane
+ //If not, something went wrong reading the header information
+ if (CurrOffset != (DataSize - VarsCmd.CodespaceCount * 2))
+ {
+ NXT_BREAK;
+ return (ERR_FILE);
+ }
+
+ //
+ // Finally, update VarsCmd fields
+ //
+
+ VarsCmd.RunQ.Head = NOT_A_CLUMP;
+ VarsCmd.RunQ.Tail = NOT_A_CLUMP;
+
+ //Reset codespace pointer
+ VarsCmd.pCodespace = (CODE_WORD*)(pData + pFileOffsets->Codespace);
+
+ //...placing clump records first...
+ VarsCmd.pAllClumps = (CLUMP_REC*)(VarsCmd.Pool + VarsCmd.PoolSize);
+ VarsCmd.PoolSize += VarsCmd.AllClumpsCount * sizeof(CLUMP_REC);
+
+ //...then DSTOC...
+ VarsCmd.pDataspaceTOC = (DS_TOC_ENTRY*)(pData + pFileOffsets->DSTOC);
+
+ //...then the dataspace itself
+ ALIGN_TO_MOD(VarsCmd.PoolSize, POOL_ALIGN);
+ VarsCmd.pDataspace = (VarsCmd.Pool + VarsCmd.PoolSize);
+ IOMapCmd.OffsetDS = (UWORD)((ULONG)(VarsCmd.pDataspace) - (ULONG)&(IOMapCmd));
+ VarsCmd.PoolSize += VarsCmd.DataspaceSize;
+
+ //init rest of MemMgr
+ VarsCmd.MemMgr.pDopeVectorArray = (DOPE_VECTOR *)(VarsCmd.pDataspace + DopeVectorOffset);
+ IOMapCmd.OffsetDVA = (UWORD)((ULONG)(VarsCmd.MemMgr.pDopeVectorArray) - (ULONG)&(IOMapCmd));
+ VarsCmd.MemMgr.FreeHead = NOT_A_DS_ID;
+
+
+ if (VarsCmd.PoolSize > POOL_MAX_SIZE)
+ {
+ NXT_BREAK;
+ return (ERR_FILE);
+ }
+
+ return (NO_ERR);
+}
+
+
+//!!! Recursive function
+NXT_STATUS cCmdInflateDSDefaults(UBYTE* pDSDefaults, UWORD *pDefaultsOffset, DS_ELEMENT_ID DSElementID)
+{
+ NXT_STATUS Status = NO_ERR;
+ TYPE_CODE TypeCode;
+ UWORD i, Count;
+ UBYTE *pVal;
+
+ NXT_ASSERT(cCmdIsDSElementIDSane(DSElementID));
+
+ TypeCode = cCmdDSType(DSElementID);
+
+ if (TypeCode == TC_CLUSTER)
+ {
+ Count = cCmdClusterCount(DSElementID);
+ //Advance DSElementID to sub-type
+ DSElementID = INC_ID(DSElementID);
+ //Loop through sub-types, inflate recursively
+ for (i = 0; i < Count; i++)
+ {
+ Status = cCmdInflateDSDefaults(pDSDefaults, pDefaultsOffset, DSElementID);
+ if (IS_ERR(Status))
+ return Status;
+ DSElementID = cCmdNextDSElement(DSElementID);
+ }
+ }
+ else
+ {
+ if (TypeCode == TC_ARRAY)
+ {
+ //Resolve pointer to DVIndex
+ pVal = VarsCmd.pDataspace + VarsCmd.pDataspaceTOC[DSElementID].DSOffset;
+ }
+ else
+ {
+ pVal = cCmdResolveDataArg(DSElementID, 0, NULL);
+ }
+
+ //Check if the element has the "default default"
+ if (VarsCmd.pDataspaceTOC[DSElementID].Flags & DS_DEFAULT_DEFAULT)
+ {
+ //Fill element with the "default default" of zero
+ memset(pVal, 0, cCmdSizeOf(TypeCode));
+ }
+ else
+ {
+ //Get default from stream
+ memmove(pVal, pDSDefaults + *pDefaultsOffset, cCmdSizeOf(TypeCode));
+ *pDefaultsOffset += cCmdSizeOf(TypeCode);
+ }
+ }
+
+ //!!! Currently will always return NO_ERR
+ return Status;
+}
+
+
+NXT_STATUS cCmdActivateProgram(UBYTE * pFileName)
+{
+ UWORD i, j;
+ UBYTE * pCursor;
+
+ NXT_STATUS Status = NO_ERR;
+ PROG_FILE_OFFSETS FileOffsets;
+
+ LOADER_STATUS LStatus;
+ ULONG DataSize;
+ UBYTE * pData;
+ ULONG pDataHolder;
+ UWORD DefaultsOffset;
+
+ LStatus = pMapLoader->pFunc(OPENREADLINEAR, pFileName, (UBYTE*)(&pDataHolder), &DataSize);
+ pData = (UBYTE*)(pDataHolder);
+
+ //If Loader returned error or bad file pointer, bail out
+ if (LOADER_ERR(LStatus) != SUCCESS || pData == NULL || DataSize == 0)
+ return (ERR_FILE);
+
+ //Deactivate current program and re-initialize memory pool
+ cCmdDeactivateProgram();
+ cCmdInitPool();
+
+ //Stash this program's handle since we hold it open while running
+ VarsCmd.ActiveProgHandle = LOADER_HANDLE(LStatus);
+
+ //Stash this program's name for easy reference later
+ strncpy((PSZ)(VarsCmd.ActiveProgName), (PSZ)(pFileName), FILENAME_LENGTH + 1);
+
+ //Consume activation record data stream.
+ //See TargettingVIs/NXT.PackAR.vi for data stream packing details
+
+ //Read header portion of the file, calculating offsets and initializing VarsCmd
+ Status = cCmdReadFileHeader(pData, DataSize, &FileOffsets);
+ if (IS_ERR(Status))
+ return Status;
+
+ //Do some spot checks to make sure bad file contents didn't leave us with obviously insane VarsCmd contents
+ //!!! Should add alignment checks on these pointers to avoid data abort exceptions later
+ if (((UBYTE*)(VarsCmd.pCodespace) < pData)
+ || ((UBYTE*)(VarsCmd.pCodespace) >= (pData + DataSize))
+ || ((UBYTE*)(VarsCmd.pAllClumps) < POOL_START)
+ || ((UBYTE*)(VarsCmd.pAllClumps) >= POOL_SENTINEL)
+ || ((UBYTE*)(VarsCmd.pDataspace) < POOL_START)
+ || ((UBYTE*)(VarsCmd.pDataspace) >= POOL_SENTINEL)
+ || (VarsCmd.DataspaceSize == 0) )
+ {
+ NXT_BREAK;
+ return ERR_FILE;
+ }
+
+ //Initialize CLUMP_RECs as contiguous list in RAM
+ pCursor = (pData + FileOffsets.Clumps);
+ for (i = 0; i < VarsCmd.AllClumpsCount; i++)
+ {
+ VarsCmd.pAllClumps[i].InitFireCount = *(UBYTE*)(pCursor + i * VM_FILE_CLUMP_REC_SIZE);
+ VarsCmd.pAllClumps[i].DependentCount = *(UBYTE*)(pCursor + (i * VM_FILE_CLUMP_REC_SIZE) + 1);
+ VarsCmd.pAllClumps[i].CodeStart = *(UWORD*)(pCursor + (i * VM_FILE_CLUMP_REC_SIZE) + 2);
+
+ //Initialize remaining CLUMP_REC fields
+ VarsCmd.pAllClumps[i].PC = 0;
+ VarsCmd.pAllClumps[i].Priority = 20;
+ VarsCmd.pAllClumps[i].Link = NOT_A_CLUMP;
+
+ //Activate any clumps with CurrFireCount of 0
+ VarsCmd.pAllClumps[i].CurrFireCount = VarsCmd.pAllClumps[i].InitFireCount;
+ if (VarsCmd.pAllClumps[i].CurrFireCount == 0)
+ cCmdEnQClump(&(VarsCmd.RunQ), (CLUMP_ID)i);
+ }
+
+ //Patch up dependents in separate pass (reuse of pCursor)
+ pCursor += VarsCmd.AllClumpsCount * VM_FILE_CLUMP_REC_SIZE;
+ for (i = 0; i < VarsCmd.AllClumpsCount; i++)
+ {
+ if (VarsCmd.pAllClumps[i].DependentCount > 0)
+ {
+ VarsCmd.pAllClumps[i].pDependents = (CLUMP_ID*)(pCursor);
+
+ pCursor += (VarsCmd.pAllClumps[i].DependentCount * sizeof(CLUMP_ID));
+ }
+ else
+ VarsCmd.pAllClumps[i].pDependents = NULL;
+
+ //Patch up CodeEnd value based on CodeStart of next clump or last overall codeword
+ if (i < (VarsCmd.AllClumpsCount - 1))
+ VarsCmd.pAllClumps[i].CodeEnd = VarsCmd.pAllClumps[i+1].CodeStart - 1;
+ else
+ VarsCmd.pAllClumps[i].CodeEnd = VarsCmd.CodespaceCount - 1;
+
+ //Test for empty/insane clump code definitions
+ NXT_ASSERT(VarsCmd.pAllClumps[i].CodeStart < VarsCmd.pAllClumps[i].CodeEnd);
+ }
+
+ //Programs with no active clumps constitutes an activation error
+ if (VarsCmd.RunQ.Head == NOT_A_CLUMP)
+ return (ERR_FILE);
+
+ //Initialize dataspace with default values from file
+ //!!! This would be a good place to enforce check against potentially
+ // unsafe nested types (deeply nested types mean deep recursive calls)
+ DefaultsOffset = 0;
+ for (i = 0; i != NOT_A_DS_ID; i = cCmdNextDSElement(i))
+ {
+
+ Status = cCmdInflateDSDefaults(pData + FileOffsets.DSDefaults, &DefaultsOffset, i);
+ if (IS_ERR(Status))
+ return Status;
+ }
+
+ if ((DefaultsOffset != FileOffsets.DynamicDefaults)
+ || (DefaultsOffset + FileOffsets.DynamicDefaultsSize != FileOffsets.DSDefaultsSize))
+ {
+ NXT_BREAK;
+ return (ERR_FILE);
+ }
+
+ //Copy Dynamic defaults from file
+ memmove(VarsCmd.pDataspace + VarsCmd.DSStaticSize, pData + FileOffsets.DSDefaults + FileOffsets.DynamicDefaults, FileOffsets.DynamicDefaultsSize);
+
+ //Verify the MemMgr ended up where we said it would
+ if ((UBYTE *)VarsCmd.MemMgr.pDopeVectorArray != VarsCmd.pDataspace + DV_ARRAY[0].Offset)
+ {
+ NXT_BREAK;
+ return (ERR_FILE);
+ }
+
+ //Initialize message queues
+ for (i = 0; i < MESSAGE_QUEUE_COUNT; i++)
+ {
+ VarsCmd.MessageQueues[i].ReadIndex = 0;
+ VarsCmd.MessageQueues[i].WriteIndex = 0;
+
+ for (j = 0; j < MESSAGES_PER_QUEUE; j++)
+ {
+ VarsCmd.MessageQueues[i].Messages[j] = NOT_A_DS_ID;
+ }
+ }
+
+ if (cCmdVerifyMemMgr() != TRUE)
+ return (ERR_FILE);
+
+ return (Status);
+}
+
+
+void cCmdDeactivateProgram()
+{
+ UBYTE i, tmp;
+
+ //Wipe away all references into the pool and clear all run-time data
+ VarsCmd.pCodespace = NULL;
+ VarsCmd.CodespaceCount = 0;
+
+ VarsCmd.pAllClumps = NULL;
+ VarsCmd.AllClumpsCount = 0;
+
+ VarsCmd.DataspaceCount = 0;
+ VarsCmd.pDataspaceTOC = NULL;
+ VarsCmd.pDataspace = NULL;
+ VarsCmd.DataspaceSize = 0;
+ VarsCmd.DSStaticSize = 0;
+
+ VarsCmd.MemMgr.Head = NOT_A_DS_ID;
+ VarsCmd.MemMgr.Tail = NOT_A_DS_ID;
+ VarsCmd.MemMgr.FreeHead = NOT_A_DS_ID;
+ VarsCmd.MemMgr.pDopeVectorArray = NULL;
+
+ VarsCmd.RunQ.Head = NOT_A_CLUMP;
+ VarsCmd.RunQ.Tail = NOT_A_CLUMP;
+ VarsCmd.ScratchPC = 0;
+ VarsCmd.CallerClump = NOT_A_CLUMP;
+
+ if (VarsCmd.ActiveProgHandle != NOT_A_HANDLE)
+ {
+ //Close handle that we've kept open for this program
+ pMapLoader->pFunc(CLOSE, &(VarsCmd.ActiveProgHandle), NULL, NULL);
+ VarsCmd.ActiveProgHandle = NOT_A_HANDLE;
+
+ //Clear internal stashed name
+ memset(VarsCmd.ActiveProgName, 0, FILENAME_LENGTH + 1);
+ }
+
+ //Close any files we had opened programatically
+ for (i = 0; i < MAX_HANDLES; i++)
+ {
+ //Copy i to tmp, because we pass a pointer to it to pFunc
+ tmp = i;
+ //Close file
+ if (*(VarsCmd.FileHandleTable[i]) != 0)
+ pMapLoader->pFunc(CLOSE, &tmp, NULL, NULL);
+ }
+
+ //Clear FileHandleTable
+ memset(VarsCmd.FileHandleTable, 0, sizeof(VarsCmd.FileHandleTable));
+
+ return;
+}
+
+
+void cCmdResetDevices(void)
+{
+ UBYTE i;
+
+ //Clear NXT button counts so 'bumped' will work on first run
+ for (i = 0; i < NO_OF_BTNS; i++)
+ {
+ pMapButton->BtnCnt[i].RelCnt = 0;
+ //Need to clear short and long counts too, because RelCnt depends on them. No known side effects.
+ pMapButton->BtnCnt[i].ShortRelCnt = 0;
+ pMapButton->BtnCnt[i].LongRelCnt = 0;
+ }
+
+ for (i = 0; i < NO_OF_INPUTS; i++)
+ {
+ //Clear type and mode to defaults
+ pMapInput->Inputs[i].SensorType = NO_SENSOR;
+ pMapInput->Inputs[i].SensorMode = RAWMODE;
+
+ //Reset input values to 0 prior to running (clear things like stale rotation counts)
+ pMapInput->Inputs[i].ADRaw = 0;
+ pMapInput->Inputs[i].SensorRaw = 0;
+ pMapInput->Inputs[i].SensorValue = 0;
+
+ //Assert invalid data flag so future code is aware of these changes
+ pMapInput->Inputs[i].InvalidData = TRUE;
+ }
+
+ for (i = 0; i < NO_OF_OUTPUTS; i++)
+ {
+ //Coast and reset all motor parameters
+ pMapOutPut->Outputs[i].Mode = 0;
+ pMapOutPut->Outputs[i].RegMode = REGULATION_MODE_IDLE;
+ pMapOutPut->Outputs[i].RunState = MOTOR_RUN_STATE_IDLE;
+ pMapOutPut->Outputs[i].Speed = 0;
+ pMapOutPut->Outputs[i].TachoLimit = 0;
+ pMapOutPut->Outputs[i].SyncTurnParameter = 0;
+ pMapOutPut->Outputs[i].Flags = UPDATE_MODE | UPDATE_SPEED | UPDATE_TACHO_LIMIT | UPDATE_RESET_COUNT | UPDATE_RESET_BLOCK_COUNT | UPDATE_RESET_ROTATION_COUNT;
+ }
+
+ //Lowspeed init, INSERT CODE !!!
+ for (i = 0; i < NO_OF_LOWSPEED_COM_CHANNEL; i++)
+ {
+ pMapLowSpeed->InBuf[i].InPtr = 0;
+ pMapLowSpeed->InBuf[i].OutPtr = 0;
+ pMapLowSpeed->InBuf[i].BytesToRx = 0;
+ pMapLowSpeed->OutBuf[i].InPtr = 0;
+ pMapLowSpeed->OutBuf[i].OutPtr = 0;
+ if (pMapLowSpeed->ChannelState[i] != LOWSPEED_IDLE)
+ {
+ pMapLowSpeed->ChannelState[i] = LOWSPEED_DONE;
+ pMapLowSpeed->State |= (0x01<<i);
+ }
+ }
+
+}
+
+
+//Add NewClump to end, updating Queue's head/tail as needed
+void cCmdEnQClump(CLUMP_Q * Queue, CLUMP_ID NewClump)
+{
+ //Make sure NewClump's ID is valid and not already on Q
+ NXT_ASSERT(cCmdIsClumpIDSane(NewClump));
+ NXT_ASSERT(cCmdIsQSane(Queue) == TRUE);
+ NXT_ASSERT(!cCmdIsClumpOnQ(Queue, NewClump));
+
+ VarsCmd.pAllClumps[NewClump].Link = NOT_A_CLUMP;
+
+ //If queue is empty, NewClump becomes both head and tail
+ if (Queue->Head == NOT_A_CLUMP)
+ {
+ NXT_ASSERT(Queue->Tail == NOT_A_CLUMP);
+
+ Queue->Head = NewClump;
+ Queue->Tail = NewClump;
+ }
+ //Otherwise, tack onto the end
+ else
+ {
+ VarsCmd.pAllClumps[Queue->Tail].Link = NewClump;
+ Queue->Tail = NewClump;
+ }
+
+ return;
+}
+
+//Dequeue specified clump
+//Normal usage is to dequeue only from the head (i.e. pass Queue.Head as arg)
+void cCmdDeQClump(CLUMP_Q * Queue, CLUMP_ID Clump)
+{
+ CLUMP_ID CurrID, LinkID;
+
+ //Make sure Clump's ID is valid and is already on Queue
+ NXT_ASSERT(cCmdIsClumpIDSane(Clump));
+ NXT_ASSERT(cCmdIsQSane(Queue) == TRUE);
+ NXT_ASSERT(cCmdIsClumpOnQ(Queue, Clump));
+
+ CurrID = Queue->Head;
+
+ //If our clump is the head, move up the next and disconnect
+ if (CurrID == Clump)
+ {
+ Queue->Head = VarsCmd.pAllClumps[Clump].Link;
+ VarsCmd.pAllClumps[Clump].Link = NOT_A_CLUMP;
+
+ //If we just removed the last clump, patch up the queue's tail
+ if (Queue->Head == NOT_A_CLUMP)
+ Queue->Tail = NOT_A_CLUMP;
+ }
+ //Else, look through rest of list looking for a link to our clump
+ else
+ {
+ do
+ {
+ LinkID = VarsCmd.pAllClumps[CurrID].Link;
+
+ //If we find a link to our clump, patch up predecessor's link
+ if (VarsCmd.pAllClumps[CurrID].Link == Clump)
+ {
+ VarsCmd.pAllClumps[CurrID].Link = VarsCmd.pAllClumps[Clump].Link;
+ VarsCmd.pAllClumps[Clump].Link = NOT_A_CLUMP;
+
+ //If we just removed the tail, patch tail
+ if (Clump == Queue->Tail)
+ Queue->Tail = CurrID;
+ }
+
+ CurrID = LinkID;
+ } while (CurrID != NOT_A_CLUMP);
+ }
+
+ return;
+}
+
+
+//Rotate head to tail and advance head for given Queue
+void cCmdRotateQ(CLUMP_Q * Queue)
+{
+ CLUMP_ID CurrID;
+ CLUMP_REC * pClumpRec;
+
+ //Make sure Queue is sane
+ NXT_ASSERT(cCmdIsQSane(Queue) == TRUE);
+
+ //If queue has at least two clumps
+ if (Queue->Head != Queue->Tail)
+ {
+ CurrID = Queue->Head;
+ pClumpRec = &(VarsCmd.pAllClumps[CurrID]);
+
+ //Disconnect head
+ Queue->Head = pClumpRec->Link;
+ pClumpRec->Link = NOT_A_CLUMP;
+
+ //Reconnect head as tail
+ pClumpRec = &(VarsCmd.pAllClumps[Queue->Tail]);
+ pClumpRec->Link = CurrID;
+ Queue->Tail = CurrID;
+
+ //Make sure we didn't make any really stupid mistakes
+ NXT_ASSERT(cCmdIsQSane(Queue) == TRUE);
+ }
+
+ return;
+}
+
+
+UBYTE cCmdIsClumpOnQ(CLUMP_Q * Queue, CLUMP_ID Clump)
+{
+ CLUMP_ID CurrID;
+
+ //Make sure Clump's ID is valid and is already on Queue
+ NXT_ASSERT(cCmdIsClumpIDSane(Clump));
+ NXT_ASSERT(cCmdIsQSane(Queue) == TRUE);
+
+ CurrID = Queue->Head;
+
+ while (CurrID != NOT_A_CLUMP)
+ {
+ if (CurrID == Clump)
+ return TRUE;
+
+ CurrID = VarsCmd.pAllClumps[CurrID].Link;
+ }
+
+ return FALSE;
+}
+
+
+UBYTE cCmdIsQSane(CLUMP_Q * Queue)
+{
+ CLUMP_ID Head, Tail;
+ CLUMP_REC * pHead;
+
+ if (Queue == NULL)
+ {
+ NXT_BREAK;
+ return FALSE;
+ }
+
+ Head = Queue->Head;
+ Tail = Queue->Tail;
+
+ if (Head == NOT_A_CLUMP && cCmdIsClumpIDSane(Tail))
+ return FALSE;
+
+ if (cCmdIsClumpIDSane(Head) && Tail == NOT_A_CLUMP)
+ return FALSE;
+
+ if (cCmdIsClumpIDSane(Head) && cCmdIsClumpIDSane(Tail))
+ {
+ pHead = &(VarsCmd.pAllClumps[Head]);
+
+ //!!! More comprehensive queue tests could go here
+
+ //Check for mislinked head if there are at least two queue members
+ if (Head != Tail && pHead->Link == NOT_A_CLUMP)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//
+// Mutex queuing functions
+//
+
+NXT_STATUS cCmdAcquireMutex(MUTEX_Q * Mutex, CLUMP_ID Clump)
+{
+ NXT_STATUS Status = NO_ERR;
+
+ NXT_ASSERT(Mutex != NULL && cCmdIsClumpIDSane(Clump));
+
+ if (Mutex->Owner == NOT_A_CLUMP)
+ {
+ //Mutex is open, so just take it
+ Mutex->Owner = Clump;
+
+ NXT_ASSERT(Mutex->WaitQ.Head == NOT_A_CLUMP && Mutex->WaitQ.Tail == NOT_A_CLUMP);
+ }
+ else
+ {
+ //Mutex is reserved by someone else, take self off RunQ and add to WaitQ
+ cCmdDeQClump(&(VarsCmd.RunQ), Clump);
+ cCmdEnQClump(&(Mutex->WaitQ), Clump);
+ Status = CLUMP_SUSPEND;
+ }
+
+ NXT_ASSERT(cCmdIsQSane(&(Mutex->WaitQ)));
+
+ return (Status);
+}
+
+
+NXT_STATUS cCmdReleaseMutex(MUTEX_Q * Mutex, CLUMP_ID Clump)
+{
+ NXT_ASSERT(Mutex != NULL);
+ //!!! don't actually need to pass in Owner clump, but provides nice error checking for now
+ // Might want to return an error/warning if we see a Release on an free mutex, though...
+ NXT_ASSERT(Clump != NOT_A_CLUMP && Mutex->Owner == Clump);
+
+ //Always set new Owner to WaitQ's Head, since NOT_A_CLUMP means mutex is free
+ Mutex->Owner = Mutex->WaitQ.Head;
+
+ if (Mutex->Owner != NOT_A_CLUMP)
+ {
+ cCmdDeQClump(&(Mutex->WaitQ), Mutex->Owner);
+ cCmdEnQClump(&(VarsCmd.RunQ), Mutex->Owner);
+ }
+
+ NXT_ASSERT(cCmdIsQSane(&(Mutex->WaitQ)));
+ NXT_ASSERT(cCmdIsQSane(&(VarsCmd.RunQ)));
+
+ return (NO_ERR);
+}
+
+
+NXT_STATUS cCmdSchedDependents(CLUMP_ID Clump, SWORD Begin, SWORD End)
+{
+ CLUMP_ID CurrDepClumpID;
+ SWORD i;
+
+ //Begin and End specify range of CLUMP_IDs in dependent list to schedule
+ //If either equals -1, both should equal -1, and no dependents will be scheduled
+ //Else schedule specified subset offset from pDependents
+
+ //Check for valid args
+ NXT_ASSERT(cCmdIsClumpIDSane(Clump));
+ NXT_ASSERT((Begin >= 0 && End >= 0 && End < VarsCmd.pAllClumps[Clump].DependentCount)
+ || (Begin == -1 && End == -1));
+
+ //If non-empty range
+ if (Begin != -1 || End != -1)
+ {
+ //update dependents, scheduling if their CurrFireCount reaches 0
+ for (i = Begin; i <= End; i++)
+ {
+ CurrDepClumpID = VarsCmd.pAllClumps[Clump].pDependents[i];
+
+ NXT_ASSERT(cCmdIsClumpIDSane(CurrDepClumpID));
+
+ VarsCmd.pAllClumps[CurrDepClumpID].CurrFireCount--;
+
+ if (VarsCmd.pAllClumps[CurrDepClumpID].CurrFireCount == 0)
+ cCmdEnQClump(&(VarsCmd.RunQ), CurrDepClumpID);
+ }
+ }
+
+ return (NO_ERR);
+}
+
+
+NXT_STATUS cCmdSchedDependent(CLUMP_ID Clump, CLUMP_ID TargetClump)
+{
+ //TargetClump specifies the clump number of the target to schedule explicitly.
+
+ //Check for valid args
+ NXT_ASSERT(cCmdIsClumpIDSane(Clump));
+ NXT_ASSERT(cCmdIsClumpIDSane(TargetClump));
+
+ VarsCmd.pAllClumps[TargetClump].CurrFireCount--;
+ if (VarsCmd.pAllClumps[TargetClump].CurrFireCount == 0)
+ cCmdEnQClump(&(VarsCmd.RunQ), TargetClump);
+
+ return (NO_ERR);
+}
+
+
+UBYTE cCmdIsClumpIDSane(CLUMP_ID Clump)
+{
+ if (Clump < VarsCmd.AllClumpsCount)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+//
+// Memory pool management functions
+//
+void cCmdInitPool(void)
+{
+ ULONG i;
+
+ //VarsCmd.Pool is a UBYTE pointer to ULONG array
+ //This was done to enforce portable alignment.
+ VarsCmd.Pool = (UBYTE*)(IOMapCmd.MemoryPool);
+
+ for (i = 0; i < (POOL_MAX_SIZE / 4); i++)
+ ((SLONG*)(POOL_START))[i] = 0xDEADBEEF;
+
+ VarsCmd.PoolSize = 0;
+}
+
+
+NXT_STATUS cCmdDSArrayAlloc(DS_ELEMENT_ID DSElementID, UWORD Offset, UWORD NewCount)
+{
+ NXT_STATUS Status = NO_ERR;
+ UWORD DVIndex;
+ UWORD OldCount;
+ UWORD i;
+
+ NXT_ASSERT(cCmdIsDSElementIDSane(DSElementID));
+
+ //Only arrays are valid here
+ //!!! Recommended to upgrade NXT_ASSERT to ERR_INSTR return
+ NXT_ASSERT(cCmdDSType(DSElementID) == TC_ARRAY);
+
+ DVIndex = cCmdGetDVIndex(DSElementID, Offset);
+ OldCount = DV_ARRAY[DVIndex].Count;
+
+ Status = cCmdDVArrayAlloc(DVIndex, NewCount);
+ if (Status < NO_ERR)
+ return Status;
+
+ if (OldCount > NewCount)
+ {
+ //Free dope vectors for sub-arrays.
+ for (i = NewCount; i < OldCount; i++)
+ {
+ Status = cCmdFreeSubArrayDopeVectors(INC_ID(DSElementID), ARRAY_ELEM_OFFSET(DVIndex, i));
+ if (IS_ERR(Status))
+ return Status;
+ }
+ }
+ else if (OldCount < NewCount)
+ {
+ //Alloc dope vectors for sub-arrays. Set up DVIndexes
+ for (i = OldCount; i < NewCount; i++)
+ {
+ Status = cCmdAllocSubArrayDopeVectors(INC_ID(DSElementID), ARRAY_ELEM_OFFSET(DVIndex, i));
+ if (IS_ERR(Status))
+ return Status;
+ }
+ }
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+
+ return Status;
+}
+
+NXT_STATUS cCmdDVArrayAlloc(DV_INDEX DVIndex, UWORD NewCount)
+{
+ NXT_STATUS Status = NO_ERR;
+ UBYTE *pData;
+ UWORD ArraySize, InplaceSize;
+ UWORD NextDVIndex;
+ UWORD OldCount;
+
+ OldCount = DV_ARRAY[DVIndex].Count;
+
+ if (OldCount == NewCount)
+ {
+ //Nothing to alloc. Return.
+ return Status;
+ }
+ else if (OldCount > NewCount)
+ {
+ //Already have the space. Shrink inplace.
+ DV_ARRAY[DVIndex].Count = NewCount;
+ return Status;
+ }
+ else // need to grow array
+ {
+ //Calculate new array size
+ ArraySize = NewCount * DV_ARRAY[DVIndex].ElemSize;
+
+ //Try growing inplace
+ // If the Offset == NOT_AN_OFFSET then the array has never been allocated and can't grow inplace.
+ if (DV_ARRAY[DVIndex].Offset != NOT_AN_OFFSET)
+ {
+ //Get pointer to next dope vector in dataspace
+ if (DV_ARRAY[DVIndex].Link != NOT_A_DS_ID)
+ {
+ NextDVIndex = DV_ARRAY[DVIndex].Link;
+ InplaceSize = DV_ARRAY[NextDVIndex].Offset - DV_ARRAY[DVIndex].Offset;
+ }
+ else
+ {
+ //Last element in dataspace.
+ NXT_ASSERT(DVIndex == VarsCmd.MemMgr.Tail);
+ InplaceSize = VarsCmd.DataspaceSize - DV_ARRAY[DVIndex].Offset;
+ }
+
+ if (ArraySize <= InplaceSize)
+ {
+ DV_ARRAY[DVIndex].Count = NewCount;
+ return Status;
+ }
+ }
+
+ //Can't grow inplace, have to allocate new space
+
+ //Make sure we properly align for type
+ //!!! This could also overflow memory (make PoolSize > POOL_MAX_SIZE) if we're within 3 bytes of the end.
+ // I don't think it matters because if it does happend, we'll trigger the ERR_MEM below and compact.
+ // During compaction, we'll reclaim these unused bytes.
+ //!!! Aligning beginning of ALL arrays to 4 byte address
+ ALIGN_TO_MOD(VarsCmd.PoolSize, SIZE_ULONG);
+ ALIGN_TO_MOD(VarsCmd.DataspaceSize, SIZE_ULONG);
+
+ if (VarsCmd.PoolSize + ArraySize >= POOL_MAX_SIZE)
+ {
+ //Not enough memory available
+ return ERR_MEM;
+ }
+
+ //Get data from end of pool
+ pData = VarsCmd.Pool + VarsCmd.PoolSize;
+ //Grow pool and dataspace
+ VarsCmd.PoolSize += ArraySize;
+ VarsCmd.DataspaceSize += ArraySize;
+
+ //Move Array Data
+ memmove(pData, VarsCmd.pDataspace + DV_ARRAY[DVIndex].Offset, (UWORD)(DV_ARRAY[DVIndex].ElemSize * DV_ARRAY[DVIndex].Count));
+ //!!! Clear mem so we make sure we don't reference stale data. Not strictly needed.
+ memset(VarsCmd.pDataspace + DV_ARRAY[DVIndex].Offset, 0xFF, (UWORD)(DV_ARRAY[DVIndex].ElemSize * DV_ARRAY[DVIndex].Count));
+
+ //Update dope vector
+ DV_ARRAY[DVIndex].Offset = pData - VarsCmd.pDataspace;
+ DV_ARRAY[DVIndex].Count = NewCount;
+
+ //Move dope vector to end of MemMgr list
+ Status = cCmdMemMgrMoveToTail(DVIndex);
+ if (IS_ERR(Status))
+ return Status;
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+ }
+
+ return Status;
+}
+
+
+//!!! Recursive function
+NXT_STATUS cCmdAllocSubArrayDopeVectors(DS_ELEMENT_ID DSElementID, UWORD Offset)
+{
+ // Walks a single array element to see if it contains arrays
+ // For any array it finds, a dope vector is allocated and the DVIndex is placed in the dataspace for the parent array.
+ // This is a non-recursive function. It only walks the immediate array element.
+ // DSElementID - ID of array sub-entry
+ // Offset - offset to array element in dataspace
+ NXT_STATUS Status = NO_ERR;
+ TYPE_CODE TypeCode;
+ DV_INDEX DVIndex;
+ UWORD i;
+ UWORD DVIndexOffset; //Offset to DVIndex field that points to the DopeVector from pDataspace
+ UWORD LoopCount = 1;
+ UWORD ElemSize;
+
+ for (i = 0; i < LoopCount; i++)
+ {
+ TypeCode = cCmdDSType((DS_ELEMENT_ID)(DSElementID + i));
+ if (TypeCode == TC_CLUSTER)
+ {
+ LoopCount += cCmdClusterCount(DSElementID);
+ }
+ else if (TypeCode == TC_ARRAY)
+ {
+ //!!! ElemSize is a static value, but we don't have anywhere we put it (another TOC sub-entry?)
+ // It'd be nice to not have to recalculate it.
+ ElemSize = cCmdCalcArrayElemSize((DS_ELEMENT_ID)(DSElementID + i));
+ DVIndexOffset = VarsCmd.pDataspaceTOC[DSElementID + i].DSOffset + Offset;
+ Status = cCmdAllocDopeVector(&DVIndex, ElemSize, DVIndexOffset);
+ if (IS_ERR(Status))
+ return Status;
+
+ *((UWORD *)(VarsCmd.pDataspace + DVIndexOffset)) = DVIndex;
+ }
+ }
+
+ return Status;
+}
+
+
+//!!! Recursive function
+NXT_STATUS cCmdFreeSubArrayDopeVectors(DS_ELEMENT_ID DSElementID, UWORD Offset)
+{
+ // Walks a single array element to see if it contains arrays
+ // Frees all dope vectors associated with the array element.
+ // Recursively deletes sub-arrays.
+ // DSElementID - ID of array sub-entry
+ // Offset - offset to array element in dataspace
+ NXT_STATUS Status = NO_ERR;
+ TYPE_CODE TypeCode;
+ DV_INDEX DVIndex;
+ UWORD i, Count;
+
+ TypeCode = cCmdDSType(DSElementID);
+
+ if (TypeCode == TC_ARRAY)
+ {
+ DVIndex = cCmdGetDVIndex(DSElementID, Offset);
+
+ NXT_ASSERT(DVIndex < DV_ARRAY[0].Count);
+
+ Count = DV_ARRAY[DVIndex].Count;
+ //Recur on sub-elements
+ for (i = 0; i < Count; i++)
+ {
+ Status = cCmdFreeSubArrayDopeVectors(INC_ID(DSElementID), ARRAY_ELEM_OFFSET(DVIndex, i));
+ if (IS_ERR(Status))
+ return Status;
+ }
+
+ //Free Dope Vector
+ Status = cCmdFreeDopeVector(DVIndex);
+ }
+ else if (TypeCode == TC_CLUSTER)
+ {
+ Count = cCmdClusterCount(DSElementID);
+ DSElementID = INC_ID(DSElementID);
+ //Recur on sub-elements
+ for (i = 0; i < Count; i++)
+ {
+ Status = cCmdFreeSubArrayDopeVectors((DS_ELEMENT_ID)(DSElementID + i), Offset);
+ if (IS_ERR(Status))
+ return Status;
+ }
+ }
+
+ return Status;
+}
+
+
+NXT_STATUS cCmdAllocDopeVector(DV_INDEX *pIndex, UWORD ElemSize, UWORD BackPtr)
+{
+ NXT_STATUS Status = NO_ERR;
+
+ if (VarsCmd.MemMgr.FreeHead == NOT_A_DS_ID)
+ {
+ //No free DVs. Need to grow DopeVector array.
+ Status = cCmdGrowDopeVectorArray(DV_ARRAY_GROWTH_COUNT);
+ if (IS_ERR(Status))
+ return Status;
+ }
+
+ NXT_ASSERT(VarsCmd.MemMgr.FreeHead != NOT_A_DS_ID);
+
+ //Remove DV from free list
+ *pIndex = VarsCmd.MemMgr.FreeHead;
+ VarsCmd.MemMgr.FreeHead = DV_ARRAY[VarsCmd.MemMgr.FreeHead].Link;
+ //Add DV to tail of MemMgr list
+ Status = cCmdMemMgrInsertAtTail(*pIndex);
+
+ //Initialize values
+ DV_ARRAY[*pIndex].Offset = NOT_AN_OFFSET;
+ DV_ARRAY[*pIndex].ElemSize = ElemSize;
+ DV_ARRAY[*pIndex].Count = 0;
+ DV_ARRAY[*pIndex].BackPtr = BackPtr;
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+
+ return Status;
+}
+
+//
+//cCmdFreeDopeVector() - Open up a spot in the DopeVectorArray for future use
+// The DopeVectorArray doesn't shrink when arrays (and their dope vectors) are deleted.
+// Instead they're pushed on the free list and the array stays the same size.
+// Future allocations check the free list before resorting to cCmdGrowDopeVectorArray()
+//
+NXT_STATUS cCmdFreeDopeVector(DV_INDEX DVIndex)
+{
+ NXT_STATUS Status = NO_ERR;
+ DV_INDEX i;
+
+ //Bounds check
+ NXT_ASSERT(DVIndex < DV_ARRAY[0].Count);
+
+ //Reset dope vector fields
+ DV_ARRAY[DVIndex].Count = 0;
+ DV_ARRAY[DVIndex].ElemSize = 0;
+ DV_ARRAY[DVIndex].Offset = NOT_AN_OFFSET;
+ DV_ARRAY[DVIndex].BackPtr = NOT_AN_OFFSET;
+
+ //Remove from MemMgr list
+ if (DVIndex == VarsCmd.MemMgr.Head)
+ {
+ VarsCmd.MemMgr.Head = DV_ARRAY[DVIndex].Link;
+ }
+ else
+ {
+ //Walk MemMgr list to find previous.
+ //!!! Could speed this up if MemMgr list were doubly linked
+ for (i = VarsCmd.MemMgr.Head; i != NOT_A_DS_ID; i = DV_ARRAY[i].Link)
+ {
+ if (DV_ARRAY[i].Link == DVIndex)
+ {
+ DV_ARRAY[i].Link = DV_ARRAY[DVIndex].Link;
+ if (DVIndex == VarsCmd.MemMgr.Tail)
+ VarsCmd.MemMgr.Tail = i;
+ break;
+ }
+ }
+ //Make sure we found the previous DV, otherwise this DV was not in the the list (already freed?)
+ NXT_ASSERT(i != NOT_A_DS_ID);
+ }
+
+ //Push on to free list
+ DV_ARRAY[DVIndex].Link = VarsCmd.MemMgr.FreeHead;
+ VarsCmd.MemMgr.FreeHead = DVIndex;
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+
+ return Status;
+}
+
+//
+//cCmdGrowDopeVectorArray() - expand DopeVectorArray to be able to track more dataspace arrays
+//
+NXT_STATUS cCmdGrowDopeVectorArray(UWORD NewNodesCount)
+{
+ NXT_STATUS Status = NO_ERR;
+ UWORD ArraySize;
+ UWORD OldCount, NewCount, i;
+ UBYTE * pData;
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+
+ OldCount = DV_ARRAY[0].Count;
+ NewCount = OldCount + NewNodesCount;
+ NXT_ASSERT(NewCount > OldCount);
+
+ ArraySize = DV_ARRAY[0].ElemSize * NewCount;
+
+ //!!! Aligning beginning of ALL arrays to 4 byte address
+ ALIGN_TO_MOD(VarsCmd.PoolSize, SIZE_ULONG);
+ ALIGN_TO_MOD(VarsCmd.DataspaceSize, SIZE_ULONG);
+
+ if (VarsCmd.PoolSize + ArraySize >= POOL_MAX_SIZE)
+ {
+ //Not enough memory available
+ return ERR_MEM;
+ }
+
+ //Get data from end of pool
+ pData = VarsCmd.Pool + VarsCmd.PoolSize;
+ //Grow pool and dataspace
+ VarsCmd.PoolSize += ArraySize;
+ VarsCmd.DataspaceSize += ArraySize;
+
+ //Move DopeVector Array
+ memmove(pData, (UBYTE *)VarsCmd.MemMgr.pDopeVectorArray, (UWORD)(DV_ARRAY[0].ElemSize * DV_ARRAY[0].Count));
+
+ //Update MemMgr pointer
+ VarsCmd.MemMgr.pDopeVectorArray = (DOPE_VECTOR *)pData;
+ IOMapCmd.OffsetDVA = (UWORD)((ULONG)(VarsCmd.MemMgr.pDopeVectorArray) - (ULONG)&(IOMapCmd));
+
+ //Update dope vector
+ DV_ARRAY[0].Offset = pData - VarsCmd.pDataspace;
+ DV_ARRAY[0].Count = NewCount;
+
+ //Add new DopeVectors to free list
+ //Push in reverse order so they get popped in order (mostly for ease of debugging)
+ for (i = NewCount - 1; i >= OldCount; i--)
+ {
+ DV_ARRAY[i].Offset = 0xFFFF;
+ DV_ARRAY[i].ElemSize = 0;
+ DV_ARRAY[i].Count = 0;
+ DV_ARRAY[i].BackPtr = 0xFFFF;
+ DV_ARRAY[i].Link = VarsCmd.MemMgr.FreeHead;
+ VarsCmd.MemMgr.FreeHead = i;
+ }
+
+ //Move dope vector to end of MemMgr list
+ Status = cCmdMemMgrMoveToTail(0);
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+
+ return Status;
+}
+
+NXT_STATUS cCmdCompactDopeVectorArray(void)
+{
+ //!!! Not implemented. Needs BackPtr support.
+ NXT_BREAK;
+ return ERR_ARG;
+}
+
+
+UWORD cCmdCalcArrayElemSize(DS_ELEMENT_ID DSElementID)
+{
+ TYPE_CODE TypeCode;
+ UWORD SizeOfType;
+ UWORD i;
+ UWORD LoopCount = 1;
+ UWORD Size = 0;
+ UWORD Alignment = 0;
+
+ NXT_ASSERT(cCmdDSType(DSElementID) == TC_ARRAY);
+
+ DSElementID = INC_ID(DSElementID);
+ for (i = 0; i < LoopCount; i++)
+ {
+ TypeCode = cCmdDSType((DS_ELEMENT_ID)(DSElementID + i));
+ if (TypeCode == TC_CLUSTER)
+ {
+ LoopCount += cCmdClusterCount((DS_ELEMENT_ID)(DSElementID + i));
+ }
+ else
+ {
+ SizeOfType = cCmdSizeOf(TypeCode);
+ ALIGN_TO_MOD(Size, SizeOfType);
+ Size += SizeOfType;
+ if (SizeOfType > Alignment)
+ Alignment = SizeOfType;
+ }
+ }
+ ALIGN_TO_MOD(Size, Alignment);
+
+ return Size;
+}
+
+
+NXT_STATUS cCmdMemMgrMoveToTail(DV_INDEX DVIndex)
+{
+ DV_INDEX i;
+
+ //Bounds check
+ NXT_ASSERT(DVIndex < DV_ARRAY[0].Count);
+
+ //Short circut if its already at the tail
+ if (DVIndex == VarsCmd.MemMgr.Tail)
+ return NO_ERR;
+
+ if (DVIndex == VarsCmd.MemMgr.Head)
+ VarsCmd.MemMgr.Head = DV_ARRAY[DVIndex].Link;
+ else
+ {
+ //Walk MemMgr list to find previous.
+ //!!! Could speed this up if MemMgr list were doubly linked
+ for (i = VarsCmd.MemMgr.Head; i != NOT_A_DS_ID; i = DV_ARRAY[i].Link)
+ {
+ if (DV_ARRAY[i].Link == DVIndex)
+ {
+ DV_ARRAY[i].Link = DV_ARRAY[DVIndex].Link;
+ break;
+ }
+ }
+ //Make sure we found the previous DV, otherwise this DV was not in the the list
+ NXT_ASSERT(i != NOT_A_DS_ID);
+ }
+
+ DV_ARRAY[DVIndex].Link = NOT_A_DS_ID;
+ DV_ARRAY[VarsCmd.MemMgr.Tail].Link = DVIndex;
+ VarsCmd.MemMgr.Tail = DVIndex;
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+
+ return NO_ERR;
+}
+
+
+NXT_STATUS cCmdMemMgrInsertAtTail(DV_INDEX DVIndex)
+{
+ //Bounds check
+ NXT_ASSERT(DVIndex < DV_ARRAY[0].Count);
+
+ DV_ARRAY[VarsCmd.MemMgr.Tail].Link = DVIndex;
+ VarsCmd.MemMgr.Tail = DVIndex;
+ DV_ARRAY[DVIndex].Link = NOT_A_DS_ID;
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+
+ return NO_ERR;
+}
+
+
+UBYTE cCmdVerifyMemMgr()
+{
+ DV_INDEX i;
+ UWORD CurrOffset = 0;
+ UWORD PrevOffset = 0;
+ UWORD DVCount = 0;
+
+ //Make sure the MemMgr list is properly sorted in ascending offset order
+ for (i = VarsCmd.MemMgr.Head; i != NOT_A_DS_ID; i = DV_ARRAY[i].Link)
+ {
+ CurrOffset = DV_ARRAY[i].Offset;
+
+ if (CurrOffset != 0xFFFF)
+ {
+ if (PrevOffset > CurrOffset)
+ return FALSE;
+
+ PrevOffset = CurrOffset;
+ }
+
+ if (DV_ARRAY[i].Link == NOT_A_DS_ID && i != VarsCmd.MemMgr.Tail)
+ return FALSE;
+
+ DVCount++;
+ }
+
+ for (i = VarsCmd.MemMgr.FreeHead; i != NOT_A_DS_ID; i = DV_ARRAY[i].Link)
+ {
+ DVCount++;
+ }
+
+ //Make sure the # of dope vectors = # used + # free
+ if (DVCount != DV_ARRAY[0].Count)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+NXT_STATUS cCmdDSCompact(void)
+{
+ NXT_STATUS Status = NO_ERR;
+
+ DV_INDEX CurrIndex;
+ UWORD NewOffset;
+ UWORD CurrOffset;
+ UWORD Size;
+ UWORD DeltaDSSize;
+ UWORD TempOffset, TempSize;
+
+#if VM_BENCHMARK
+ ULONG StartTime, TotalTime;
+
+ VarsCmd.CompactionCount++;
+ VarsCmd.LastCompactionTick = IOMapCmd.Tick - VarsCmd.StartTick;
+
+ StartTime = dTimerRead();
+#endif
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+
+ NewOffset = VarsCmd.DSStaticSize;
+ for (CurrIndex = VarsCmd.MemMgr.Head; CurrIndex != NOT_A_DS_ID; CurrIndex = DV_ARRAY[CurrIndex].Link)
+ {
+ //Align NewOffset for array to 4 byte address.
+ ALIGN_TO_MOD(NewOffset, SIZE_ULONG);
+
+ CurrOffset = DV_ARRAY[CurrIndex].Offset;
+ if (CurrOffset != NOT_AN_OFFSET)
+ {
+ Size = DV_ARRAY[CurrIndex].ElemSize * DV_ARRAY[CurrIndex].Count;
+ if (CurrOffset != NewOffset)
+ {
+ NXT_ASSERT(NewOffset < CurrOffset);
+ memmove(VarsCmd.pDataspace + NewOffset, VarsCmd.pDataspace + CurrOffset, Size);
+
+ // Clear mem to make stale data references more obvious while debugging.
+ // Correct for overlapping memory regions (make sure we don't clear what we just moved).
+ //!!! Clearing step not strictly necessary, so it could be optimized out
+ if (NewOffset + Size > CurrOffset)
+ {
+ TempOffset = NewOffset + Size;
+ TempSize = Size - (TempOffset - CurrOffset);
+ }
+ else
+ {
+ TempOffset = CurrOffset;
+ TempSize = Size;
+ }
+ memset(VarsCmd.pDataspace + TempOffset, 0xFF, TempSize);
+
+ //Update pDopeVectorArray if we move the dope vector array
+ if (CurrIndex == 0)
+ {
+ VarsCmd.MemMgr.pDopeVectorArray = (DOPE_VECTOR *)(VarsCmd.pDataspace + NewOffset);
+ IOMapCmd.OffsetDVA = (UWORD)((ULONG)(VarsCmd.MemMgr.pDopeVectorArray) - (ULONG)&(IOMapCmd));
+ }
+
+ //Update offset in DV Array
+ DV_ARRAY[CurrIndex].Offset = NewOffset;
+ }
+
+ NewOffset += Size;
+ }
+ }
+
+ DeltaDSSize = VarsCmd.DataspaceSize - NewOffset;
+
+ VarsCmd.PoolSize -= DeltaDSSize;
+ VarsCmd.DataspaceSize -= DeltaDSSize;
+
+ NXT_ASSERT(cCmdVerifyMemMgr());
+
+#if VM_BENCHMARK
+ TotalTime = dTimerRead() - StartTime;
+
+ if (TotalTime > VarsCmd.MaxCompactionTime)
+ VarsCmd.MaxCompactionTime = TotalTime;
+#endif
+
+ return Status;
+}
+
+
+//
+// Message Queue functions
+//
+
+NXT_STATUS cCmdMessageWrite(UWORD QueueID, UBYTE * pData, UWORD Length)
+{
+ NXT_STATUS Status = NO_ERR;
+
+ if (pData == NULL)
+ return ERR_ARG;
+
+ if (QueueID >= MESSAGE_QUEUE_COUNT)
+ return ERR_INVALID_QUEUE;
+
+ if (VarsCmd.ActiveProgHandle == NOT_A_HANDLE)
+ return ERR_NO_PROG;
+
+ //Can't accept oversize messages because we treat them as strings (truncation would remove null termination)
+ if (Length > MAX_MESSAGE_SIZE)
+ return ERR_INVALID_SIZE;
+
+ if (IS_DV_INDEX_SANE(GET_WRITE_MSG(QueueID)))
+ {
+ //A message is already there, the queue is full
+ NXT_ASSERT(VarsCmd.MessageQueues[QueueID].WriteIndex == VarsCmd.MessageQueues[QueueID].ReadIndex);
+
+ //Bump read index, drop existing message to make room for our new incoming message
+ VarsCmd.MessageQueues[QueueID].ReadIndex = (VarsCmd.MessageQueues[QueueID].ReadIndex + 1) % MESSAGES_PER_QUEUE;
+ }
+ else
+ {
+ //Allocate dope vector for message
+ Status = cCmdAllocDopeVector(&GET_WRITE_MSG(QueueID), 1, NOT_AN_OFFSET);
+ if (IS_ERR(Status))
+ return Status;
+ }
+
+ //Allocate storage for message
+ Status = cCmdDVArrayAlloc(GET_WRITE_MSG(QueueID), Length);
+ if (IS_ERR(Status))
+ {
+ //Clear the dope vector for the message, since we're unable to put a message there.
+ cCmdFreeDopeVector(GET_WRITE_MSG(QueueID));
+ SET_WRITE_MSG(QueueID, NOT_A_DS_ID);
+ return Status;
+ }
+
+ //Copy message
+ memmove(cCmdDVPtr(GET_WRITE_MSG(QueueID)), pData, Length);
+
+ //Advance write index
+ VarsCmd.MessageQueues[QueueID].WriteIndex = (VarsCmd.MessageQueues[QueueID].WriteIndex + 1) % MESSAGES_PER_QUEUE;
+
+ return Status;
+}
+
+
+NXT_STATUS cCmdMessageGetSize(UWORD QueueID, UWORD * Size)
+{
+ DV_INDEX ReadDVIndex;
+
+ if (Size == NULL)
+ return (ERR_ARG);
+
+ if (VarsCmd.ActiveProgHandle == NOT_A_HANDLE)
+ {
+ *Size = 0;
+ return (ERR_NO_PROG);
+ }
+
+ if (QueueID >= MESSAGE_QUEUE_COUNT)
+ {
+ *Size = 0;
+ return (ERR_INVALID_QUEUE);
+ }
+
+ ReadDVIndex = GET_READ_MSG(QueueID);
+
+ if (IS_DV_INDEX_SANE(ReadDVIndex))
+ {
+ *Size = (DV_ARRAY[ReadDVIndex].Count);
+ return (NO_ERR);
+ }
+ else
+ {
+ *Size = 0;
+ return (STAT_MSG_EMPTY_MAILBOX);
+ }
+}
+
+
+NXT_STATUS cCmdMessageRead(UWORD QueueID, UBYTE * pBuffer, UWORD Length, UBYTE Remove)
+{
+ NXT_STATUS Status = NO_ERR;
+ DV_INDEX ReadDVIndex;
+
+ if (pBuffer == NULL)
+ return (ERR_ARG);
+
+ if (VarsCmd.ActiveProgHandle == NOT_A_HANDLE)
+ return (ERR_NO_PROG);
+
+ if (QueueID >= MESSAGE_QUEUE_COUNT)
+ return (ERR_INVALID_QUEUE);
+
+ ReadDVIndex = GET_READ_MSG(QueueID);
+
+ if (IS_DV_INDEX_SANE(ReadDVIndex))
+ {
+ //If Buffer doesn't have room for the entire message,
+ //don't risk incomplete string floating around
+ if (Length < DV_ARRAY[ReadDVIndex].Count)
+ return (ERR_INVALID_SIZE);
+
+ //Copy message
+ memmove(pBuffer, cCmdDVPtr(ReadDVIndex), DV_ARRAY[ReadDVIndex].Count);
+
+ if (Remove)
+ {
+ //Free memory used by message
+ Status = cCmdFreeDopeVector(ReadDVIndex);
+ if (IS_ERR(Status))
+ return Status;
+
+ SET_READ_MSG(QueueID, NOT_A_DS_ID);
+
+ //Advance read index
+ VarsCmd.MessageQueues[QueueID].ReadIndex = (VarsCmd.MessageQueues[QueueID].ReadIndex + 1) % MESSAGES_PER_QUEUE;
+ }
+ }
+ else
+ {
+ //No message to read, message Queue is empty
+ NXT_ASSERT(VarsCmd.MessageQueues[QueueID].ReadIndex == VarsCmd.MessageQueues[QueueID].WriteIndex);
+
+ return (STAT_MSG_EMPTY_MAILBOX);
+ }
+
+ return Status;
+}
+
+
+//
+// Dataspace Support functions
+//
+
+UBYTE cCmdIsDSElementIDSane(DS_ELEMENT_ID Index)
+{
+ if (Index < VarsCmd.DataspaceCount)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+TYPE_CODE cCmdDSType(DS_ELEMENT_ID DSElementID)
+{
+ NXT_ASSERT(cCmdIsDSElementIDSane(DSElementID));
+
+ return (VarsCmd.pDataspaceTOC[DSElementID].TypeCode);
+}
+
+
+void * cCmdResolveDataArg(DATA_ARG DataArg, UWORD Offset, TYPE_CODE * TypeCode)
+{
+ UBYTE ModuleID;
+ UWORD FieldID;
+ void * ret_val = NULL;
+
+ //
+ //!!! DATA_ARG masking system only for internal c_cmd use!
+ // All normal bytecode arguments should go through top if() block.
+ //
+
+ if (DataArg <= (DATA_ARG)(DATA_ARG_ADDR_MASK) )
+ {
+ NXT_ASSERT(cCmdIsDSElementIDSane(DataArg));
+ ret_val = cCmdDSPtr(DataArg, Offset);
+ if (TypeCode)
+ *TypeCode = VarsCmd.pDataspaceTOC[DataArg].TypeCode;
+ }
+ else if (DataArg & ~((DATA_ARG)(DATA_ARG_ADDR_MASK)))
+ {
+ //DataArg refers to a field in the IO map
+ ModuleID = (UBYTE)((DataArg >> 9) & 0x001F);
+ FieldID = (UWORD)(DataArg & 0x01FF);
+
+ //!!! Preliminary bounds check -- still could allow invalid combos through
+ if (ModuleID > MOD_OUTPUT || FieldID >= IO_OUT_FIELD_COUNT)
+ {
+ NXT_BREAK;
+ return NULL;
+ }
+
+ ret_val = IO_PTRS[ModuleID][FieldID];
+ if (TypeCode)
+ *TypeCode = IO_TYPES[ModuleID][FieldID];
+ }
+
+ //!!! Caller beware! If DataArg isn't sane, ret_val may be out of range or NULL!
+ return ret_val;
+}
+
+void cCmdSetVal(void * pVal, TYPE_CODE TypeCode, ULONG NewVal)
+{
+
+ if (pVal)
+ {
+ switch (TypeCode)
+ {
+ case TC_ULONG:
+ case TC_SLONG:
+ {
+ *(ULONG*)pVal = NewVal;
+ }
+ break;
+
+ case TC_UWORD:
+ case TC_SWORD:
+ {
+ *(UWORD*)pVal = (UWORD)NewVal;
+ }
+ break;
+
+ case TC_UBYTE:
+ case TC_SBYTE:
+ {
+ *(UBYTE*)pVal = (UBYTE)NewVal;
+ }
+ break;
+ }
+ }
+
+ return;
+}
+
+
+ULONG cCmdGetVal(void * pVal, TYPE_CODE TypeCode)
+{
+ if (pVal)
+ {
+ switch (TypeCode)
+ {
+ case TC_ULONG:
+ {
+ return (ULONG)(*(ULONG*)pVal);
+ }
+
+ case TC_SLONG:
+ {
+ return (SLONG)(*(SLONG*)pVal);
+ }
+
+ case TC_UWORD:
+ {
+ return (UWORD)(*(UWORD*)pVal);
+ }
+
+ case TC_SWORD:
+ {
+ return (SWORD)(*(SWORD*)pVal);
+ }
+
+ case TC_UBYTE:
+ {
+ return (UBYTE)(*(UBYTE*)pVal);
+ }
+
+ case TC_SBYTE:
+ {
+ return (SBYTE)(*(SBYTE*)pVal);
+ }
+
+ default:
+ break;
+ }
+ }
+
+ //!!! Default return value places responsibility on caller to use this function wisely
+ return 0;
+}
+
+
+UWORD cCmdSizeOf(TYPE_CODE TypeCode)
+{
+ //!!! Why not use a lookup table? No particular reason...
+ switch(TypeCode)
+ {
+ case TC_ULONG:
+ return SIZE_ULONG;
+ case TC_SLONG:
+ return SIZE_SLONG;
+ case TC_UWORD:
+ return SIZE_UWORD;
+ case TC_SWORD:
+ return SIZE_SWORD;
+ case TC_UBYTE:
+ return SIZE_UBYTE;
+ case TC_SBYTE:
+ return SIZE_SBYTE;
+ case TC_MUTEX:
+ return SIZE_MUTEX;
+ case TC_ARRAY:
+ //Arrays have a 2-byte structure in the dataspace for the DVIndex
+ return SIZE_UWORD;
+ case TC_CLUSTER:
+ default:
+ return 0;
+ }
+}
+
+
+void* cCmdDSPtr(DS_ELEMENT_ID DSElementID, UWORD Offset)
+{
+ void * pDSItem;
+ DV_INDEX DVIndex;
+ TYPE_CODE TypeCode;
+
+ NXT_ASSERT(cCmdIsDSElementIDSane(DSElementID));
+
+ TypeCode = cCmdDSType(DSElementID);
+ if (TypeCode == TC_ARRAY)
+ {
+ //!!! Empty arrays return NULL.
+ if (cCmdArrayCount(DSElementID, Offset) == 0)
+ pDSItem = NULL;
+ else
+ {
+ DVIndex = cCmdGetDVIndex(DSElementID, Offset);
+ pDSItem = (VarsCmd.pDataspace + DV_ARRAY[DVIndex].Offset);
+ }
+ }
+ else if (TypeCode == TC_CLUSTER)
+ {
+ NXT_ASSERT(cCmdClusterCount(DSElementID) != 0)
+
+ //Returning pointer to the first element in the cluster
+ pDSItem = cCmdDSPtr(INC_ID(DSElementID), Offset);
+ }
+ else
+ pDSItem = (VarsCmd.pDataspace + VarsCmd.pDataspaceTOC[DSElementID].DSOffset + Offset);
+
+ NXT_ASSERT((UBYTE*)pDSItem < POOL_SENTINEL);
+
+ return pDSItem;
+}
+
+void* cCmdDVPtr(DV_INDEX DVIndex)
+{
+ NXT_ASSERT(IS_DV_INDEX_SANE(DVIndex));
+ return (VarsCmd.pDataspace + DV_ARRAY[DVIndex].Offset);
+}
+
+
+//!!! Recursive function
+DS_ELEMENT_ID cCmdNextDSElement(DS_ELEMENT_ID CurrID)
+{
+ DS_ELEMENT_ID NextID;
+ TYPE_CODE CurrType;
+ UWORD ClusterCount, i;
+
+ NXT_ASSERT(cCmdIsDSElementIDSane(CurrID));
+
+ NextID = CurrID + 1;
+
+ if (!cCmdIsDSElementIDSane(NextID))
+ return NOT_A_DS_ID;
+
+ CurrType = cCmdDSType(CurrID);
+
+ if (CurrType == TC_ARRAY)
+ {
+ //Arrays contain two elements. Advance past the second one.
+ NextID = cCmdNextDSElement(NextID);
+ }
+ else if (CurrType == TC_CLUSTER)
+ {
+ ClusterCount = cCmdClusterCount(CurrID);
+ for (i = 0; i < ClusterCount; i++)
+ {
+ NextID = cCmdNextDSElement(NextID);
+ }
+ }
+
+ return NextID;
+}
+
+
+//!!! Recursive function
+UBYTE cCmdCompareDSType(DS_ELEMENT_ID DSElementID1, DS_ELEMENT_ID DSElementID2)
+{
+ TYPE_CODE Type1, Type2;
+ UWORD i, Count1, Count2;
+
+ Type1 = cCmdDSType(DSElementID1);
+ Type2 = cCmdDSType(DSElementID2);
+
+ if (Type1 != Type2)
+ return FALSE;
+
+ if (Type1 == TC_CLUSTER)
+ {
+ Count1 = cCmdClusterCount(DSElementID1);
+ Count2 = cCmdClusterCount(DSElementID2);
+
+ if(Count1 != Count2)
+ return FALSE;
+
+ DSElementID1 = INC_ID(DSElementID1);
+ DSElementID2 = INC_ID(DSElementID2);
+
+ for (i = 0; i < Count1; i++)
+ {
+ if (!cCmdCompareDSType(DSElementID1, DSElementID2))
+ return FALSE;
+
+ DSElementID1 = cCmdNextDSElement(DSElementID1);
+ DSElementID2 = cCmdNextDSElement(DSElementID2);
+ }
+ }
+ else if (Type1 == TC_ARRAY)
+ {
+ if (!cCmdCompareDSType(INC_ID(DSElementID1), INC_ID(DSElementID2)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+//!!! Recursive function
+UWORD cCmdCalcFlattenedSize(DS_ELEMENT_ID DSElementID, UWORD Offset)
+{
+ UWORD Size = 0;
+ TYPE_CODE TypeCode;
+ DV_INDEX DVIndex;
+ UWORD i;
+ UWORD Count;
+
+ TypeCode = cCmdDSType(DSElementID);
+
+ if (TypeCode == TC_ARRAY)
+ {
+ DVIndex = cCmdGetDVIndex(DSElementID, Offset);
+
+ DSElementID = INC_ID(DSElementID);
+ TypeCode = cCmdDSType(DSElementID);
+
+ if (!IS_AGGREGATE_TYPE(TypeCode))
+ {
+ //Short circuit recursive calculation if our array sub-type is a scalar
+ Size += DV_ARRAY[DVIndex].ElemSize * DV_ARRAY[DVIndex].Count;
+ }
+ else
+ {
+ //If the sub type is an aggregate type, then it can contain arrays, so we have to recur
+ for (i = 0; i < DV_ARRAY[DVIndex].Count; i++)
+ {
+ Size += cCmdCalcFlattenedSize(DSElementID, ARRAY_ELEM_OFFSET(DVIndex, i));
+ }
+ }
+ }
+ else if (TypeCode == TC_CLUSTER)
+ {
+ Count = cCmdClusterCount(DSElementID);
+
+ DSElementID = INC_ID(DSElementID);
+ for (i = 0; i < Count; i++)
+ {
+ Size += cCmdCalcFlattenedSize(DSElementID, Offset);
+ DSElementID = cCmdNextDSElement(DSElementID);
+ }
+ }
+ else //Scalar
+ {
+ Size += cCmdSizeOf(TypeCode);
+ }
+ return Size;
+}
+
+
+//!!! Recursive function
+NXT_STATUS cCmdFlattenToByteArray(UBYTE * pByteArray, UWORD * pByteOffset, DS_ELEMENT_ID DSElementID, UWORD Offset)
+{
+ NXT_STATUS Status = NO_ERR;
+ TYPE_CODE TypeCode;
+ DV_INDEX DVIndex;
+ UWORD i;
+ UWORD Count;
+ UBYTE *pVal;
+
+ TypeCode = cCmdDSType(DSElementID);
+
+ if (TypeCode == TC_ARRAY)
+ {
+ DVIndex = cCmdGetDVIndex(DSElementID, Offset);
+ Count = DV_ARRAY[DVIndex].Count;
+
+ DSElementID = INC_ID(DSElementID);
+ TypeCode = cCmdDSType(DSElementID);
+ if (!IS_AGGREGATE_TYPE(TypeCode))
+ {
+ //Short circuit recursive calculation if our array sub-type is a scalar
+ Count = DV_ARRAY[DVIndex].ElemSize * DV_ARRAY[DVIndex].Count;
+ memmove((pByteArray + *pByteOffset), (VarsCmd.pDataspace + DV_ARRAY[DVIndex].Offset), Count);
+ *pByteOffset += Count;
+ }
+ else
+ {
+ //If the sub type is an aggregate type, then it can contain arrays, so we have to recur
+ for (i = 0; i < Count; i++)
+ {
+ cCmdFlattenToByteArray(pByteArray, pByteOffset, DSElementID, ARRAY_ELEM_OFFSET(DVIndex, i));
+ }
+ }
+ }
+ else if (TypeCode == TC_CLUSTER)
+ {
+ Count = cCmdClusterCount(DSElementID);
+
+ DSElementID = INC_ID(DSElementID);
+ for (i = 0; i < Count; i++)
+ {
+ cCmdFlattenToByteArray(pByteArray, pByteOffset, DSElementID, Offset);
+ DSElementID = cCmdNextDSElement(DSElementID);
+ }
+ }
+ else //Scalar
+ {
+ pVal = cCmdResolveDataArg(DSElementID, Offset, NULL);
+ Count = cCmdSizeOf(TypeCode);
+
+ memmove((pByteArray + *pByteOffset), pVal, Count);
+ *pByteOffset += Count;
+ }
+
+ return Status;
+}
+
+NXT_STATUS cCmdUnflattenFromByteArray(UBYTE * pByteArray, UWORD * pByteOffset, DS_ELEMENT_ID DSElementID, UWORD Offset)
+{
+ NXT_STATUS Status = NO_ERR;
+ TYPE_CODE TypeCode;
+ DV_INDEX DVIndex;
+ UWORD i;
+ UWORD Count;
+ UBYTE *pVal;
+
+ TypeCode = cCmdDSType(DSElementID);
+
+ if (TypeCode == TC_ARRAY)
+ {
+ DVIndex = cCmdGetDVIndex(DSElementID, Offset);
+ Count = DV_ARRAY[DVIndex].Count;
+
+ DSElementID = INC_ID(DSElementID);
+ TypeCode = cCmdDSType(DSElementID);
+ if (!IS_AGGREGATE_TYPE(TypeCode))
+ {
+ //Short circuit recursive calculation if our array sub-type is a scalar
+ Count = DV_ARRAY[DVIndex].ElemSize * DV_ARRAY[DVIndex].Count;
+ memmove((VarsCmd.pDataspace + DV_ARRAY[DVIndex].Offset), (pByteArray + *pByteOffset), Count);
+ *pByteOffset += Count;
+ }
+ else
+ {
+ //If the sub type is an aggregate type, then it can contain arrays, so we have to recur
+ for (i = 0; i < Count; i++)
+ {
+ cCmdUnflattenFromByteArray(pByteArray, pByteOffset, DSElementID, ARRAY_ELEM_OFFSET(DVIndex, i));
+ }
+ }
+ }
+ else if (TypeCode == TC_CLUSTER)
+ {
+ Count = cCmdClusterCount(DSElementID);
+
+ DSElementID = INC_ID(DSElementID);
+ for (i = 0; i < Count; i++)
+ {
+ cCmdUnflattenFromByteArray(pByteArray, pByteOffset, DSElementID, Offset);
+ DSElementID = cCmdNextDSElement(DSElementID);
+ }
+ }
+ else //Scalar
+ {
+ pVal = cCmdResolveDataArg(DSElementID, Offset, NULL);
+ Count = cCmdSizeOf(TypeCode);
+
+ memmove(pVal, (pByteArray + *pByteOffset), Count);
+ *pByteOffset += Count;
+ }
+
+ return Status;
+}
+
+
+UWORD cCmdClusterCount(DS_ELEMENT_ID DSElementID)
+{
+ UWORD ClusterCount;
+
+ NXT_ASSERT(cCmdIsDSElementIDSane(DSElementID));
+ NXT_ASSERT(cCmdDSType(DSElementID) == TC_CLUSTER);
+
+ ClusterCount = VarsCmd.pDataspaceTOC[DSElementID].DSOffset;
+
+ return ClusterCount;
+}
+
+
+UWORD cCmdGetDVIndex(DS_ELEMENT_ID DSElementID, UWORD Offset)
+{
+ UWORD DVIndex;
+
+ NXT_ASSERT(cCmdDSType(DSElementID) == TC_ARRAY);
+
+ DVIndex = *(UWORD *)(VarsCmd.pDataspace + VarsCmd.pDataspaceTOC[DSElementID].DSOffset + Offset);
+
+ //Make sure we're returning a valid DVIndex
+ NXT_ASSERT(DVIndex != 0 && DVIndex < DV_ARRAY[0].Count);
+
+ return DVIndex;
+}
+
+
+UWORD cCmdArrayCount(DS_ELEMENT_ID DSElementID, UWORD Offset)
+{
+ DV_INDEX DVIndex;
+
+ NXT_ASSERT(cCmdIsDSElementIDSane(DSElementID));
+ NXT_ASSERT(cCmdDSType(DSElementID) == TC_ARRAY);
+
+ DVIndex = cCmdGetDVIndex(DSElementID, Offset);
+ return DV_ARRAY[DVIndex].Count;
+}
+
+TYPE_CODE cCmdArrayType(DS_ELEMENT_ID DSElementID)
+{
+ TYPE_CODE TypeCode;
+
+ NXT_ASSERT(cCmdIsDSElementIDSane(DSElementID));
+ NXT_ASSERT(cCmdIsDSElementIDSane(INC_ID(DSElementID)));
+ NXT_ASSERT(cCmdDSType(DSElementID) == TC_ARRAY);
+
+ TypeCode = VarsCmd.pDataspaceTOC[DSElementID + 1].TypeCode;
+
+ return TypeCode;
+}
+
+
+DS_ELEMENT_ID cCmdGetDataspaceCount(void)
+{
+ return (VarsCmd.DataspaceCount);
+}
+
+
+CODE_INDEX cCmdGetCodespaceCount(CLUMP_ID Clump)
+{
+ if (Clump == NOT_A_CLUMP)
+ return (VarsCmd.CodespaceCount);
+ else
+ {
+ NXT_ASSERT(cCmdIsClumpIDSane(Clump));
+ return (VarsCmd.pAllClumps[Clump].CodeEnd - VarsCmd.pAllClumps[Clump].CodeStart + 1);
+ }
+}
+
+
+UBYTE cCmdCompare(UBYTE CompCode, ULONG Val1, ULONG Val2, TYPE_CODE TypeCode1, TYPE_CODE TypeCode2)
+{
+ SLONG SVal1, SVal2;
+
+ if (IS_SIGNED_TYPE(TypeCode1) && IS_SIGNED_TYPE(TypeCode2))
+ {
+ SVal1 = (SLONG)Val1;
+ SVal2 = (SLONG)Val2;
+ return ((CompCode == OPCC1_LT && SVal1 < SVal2)
+ || (CompCode == OPCC1_GT && SVal1 > SVal2)
+ || (CompCode == OPCC1_LTEQ && SVal1 <= SVal2)
+ || (CompCode == OPCC1_GTEQ && SVal1 >= SVal2)
+ || (CompCode == OPCC1_EQ && SVal1 == SVal2)
+ || (CompCode == OPCC1_NEQ && SVal1 != SVal2));
+ }
+ else
+ {
+ return ((CompCode == OPCC1_LT && Val1 < Val2)
+ || (CompCode == OPCC1_GT && Val1 > Val2)
+ || (CompCode == OPCC1_LTEQ && Val1 <= Val2)
+ || (CompCode == OPCC1_GTEQ && Val1 >= Val2)
+ || (CompCode == OPCC1_EQ && Val1 == Val2)
+ || (CompCode == OPCC1_NEQ && Val1 != Val2));
+ }
+
+}
+
+
+NXT_STATUS cCmdCompareAggregates(UBYTE CompCode, UBYTE *ReturnBool, DATA_ARG Arg2, UWORD Offset2, DATA_ARG Arg3, UWORD Offset3)
+{
+ NXT_STATUS Status = NO_ERR;
+ UBYTE Finished;
+
+ Finished = FALSE;
+ Status = cCmdRecursiveCompareAggregates(CompCode, ReturnBool, &Finished, Arg2, Offset2, Arg3, Offset3);
+ if (Finished == FALSE)
+ {
+ //If Finished has not been set to TRUE, it means that it was unable to find an inequality, thereby ending the comparison.
+ //Both elements are equal. Assign the proper value to ReturnBool
+ *ReturnBool = (CompCode == OPCC1_EQ || CompCode == OPCC1_GTEQ || CompCode == OPCC1_LTEQ);
+ }
+
+ return Status;
+}
+
+
+//!!! Recursive function
+NXT_STATUS cCmdRecursiveCompareAggregates(UBYTE CompCode, UBYTE *ReturnBool, UBYTE *Finished, DATA_ARG Arg2, UWORD Offset2, DATA_ARG Arg3, UWORD Offset3)
+{
+ //The value of Finished must be set to FALSE before calling this function.
+ //We are able to determine the result of the comparison once we find an inequality.
+ //Once an inequality is found, Finished is set to TRUE and ReturnBool is set based on the CompCode.
+ //A call to this function will return with Finished still equal to FALSE if both elements are equal in value and count.
+ //It is the caller of this function's job to set ReturnBool if this function returns with Finished == FALSE.
+
+ NXT_STATUS Status = NO_ERR;
+ TYPE_CODE TypeCode2, TypeCode3;
+ DV_INDEX DVIndex2, DVIndex3;
+ ULONG ArgVal2, ArgVal3;
+ UWORD Count2, Count3, MinCount;
+ UWORD i;
+
+ void *pArg2 = NULL,
+ *pArg3 = NULL;
+
+ TypeCode2 = cCmdDSType(Arg2);
+ TypeCode3 = cCmdDSType(Arg3);
+
+ //Make sure the two things we're comparing are the same type
+ if (IS_AGGREGATE_TYPE(TypeCode2) && (TypeCode2 != TypeCode3))
+ {
+ NXT_BREAK;
+ return ERR_ARG;
+ }
+
+ //Simple case, both args are scalars. Solve and return.
+ if (!IS_AGGREGATE_TYPE(TypeCode2))
+ {
+ pArg2 = cCmdResolveDataArg(Arg2, Offset2, &TypeCode2);
+ pArg3 = cCmdResolveDataArg(Arg3, Offset3, &TypeCode3);
+
+ ArgVal2 = cCmdGetVal(pArg2, TypeCode2);
+ ArgVal3 = cCmdGetVal(pArg3, TypeCode3);
+
+ //Once we find an inequality, we can determine the result of the comparison
+ *Finished = cCmdCompare(OPCC1_NEQ, ArgVal2, ArgVal3, TypeCode2, TypeCode3);
+
+ if (*Finished)
+ *ReturnBool = cCmdCompare(CompCode, ArgVal2, ArgVal3, TypeCode2, TypeCode3);
+
+ return Status;
+ }
+
+ // Initialize local variables for each argument
+
+ if (TypeCode2 == TC_ARRAY)
+ {
+ Count2 = cCmdArrayCount(Arg2, Offset2);
+ DVIndex2 = cCmdGetDVIndex(Arg2, Offset2);
+ Offset2 = DV_ARRAY[DVIndex2].Offset;
+
+ Count3 = cCmdArrayCount(Arg3, Offset3);
+ DVIndex3 = cCmdGetDVIndex(Arg3, Offset3);
+ Offset3 = DV_ARRAY[DVIndex3].Offset;
+ }
+ else if (TypeCode2 == TC_CLUSTER)
+ {
+ Count2 = cCmdClusterCount(Arg2);
+ Count3 = cCmdClusterCount(Arg3);
+ }
+
+ //Short circuit evaluation of EQ and NEQ if counts are different
+ if (Count2 != Count3)
+ {
+ if ((CompCode == OPCC1_EQ) || (CompCode == OPCC1_NEQ))
+ {
+ *Finished = TRUE;
+ *ReturnBool = (CompCode == OPCC1_NEQ);
+ return Status;
+ }
+ }
+
+ MinCount = (Count2 < Count3) ? Count2 : Count3;
+
+ //Advance aggregate args to first sub-element for next call
+ Arg2 = INC_ID(Arg2);
+ Arg3 = INC_ID(Arg3);
+
+ //
+ // Loop through the sub-elements of aggregate arguments.
+ // Call cCmdRecursiveCompareAggregates recursively with simpler type.
+ //
+
+ for (i = 0; i < MinCount; i++)
+ {
+ Status = cCmdRecursiveCompareAggregates(CompCode, ReturnBool, Finished, Arg2, Offset2, Arg3, Offset3);
+ if (*Finished || IS_ERR(Status))
+ return Status;
+
+ //Advance aggregate args to next sub-element
+ if (TypeCode2 == TC_ARRAY)
+ {
+ Offset2 += DV_ARRAY[DVIndex2].ElemSize;
+ Offset3 += DV_ARRAY[DVIndex3].ElemSize;
+ }
+ else if (TypeCode2 == TC_CLUSTER)
+ {
+ Arg2 = cCmdNextDSElement(Arg2);
+ Arg3 = cCmdNextDSElement(Arg3);
+ }
+ }
+
+ //All elements in aggregates type up to MinCount are equal. Count discrepancy determines comparison outcome.
+ if (Count2 != Count3)
+ {
+ *Finished = TRUE;
+ *ReturnBool = cCmdCompare(CompCode, Count2, Count3, TC_UWORD, TC_UWORD);
+ }
+ //Else, no size discrepancy. Elements are equal. Comparison still not resolved,
+ //so return !Finished and status back up the call chain for further comparison
+
+ return Status;
+}
+
+
+//
+// Interpreter Functions
+//
+#define VAR_INSTR_SIZE 0xE
+
+NXT_STATUS cCmdInterpFromClump(CLUMP_ID Clump)
+{
+ NXT_STATUS Status = NO_ERR;
+ CLUMP_REC * pClumpRec;
+ CODE_WORD * pInstr;
+ UBYTE InterpFuncIndex, InstrSize;
+#if VM_BENCHMARK
+ ULONG InstrTime = dTimerRead();
+#endif
+
+ if (!cCmdIsClumpIDSane(Clump))
+ {
+ //Caller gave us a bad clump ID -- something is very wrong! Force interpretter to halt.
+ NXT_BREAK;
+ return (ERR_ARG);
+ }
+
+ //Resolve clump record structure and current instruction pointer
+ pClumpRec = &(VarsCmd.pAllClumps[Clump]);
+ pInstr = (VarsCmd.pCodespace + pClumpRec->CodeStart + pClumpRec->PC);
+
+ //Get instruction size in bytes.
+ InstrSize = INSTR_SIZE(pInstr);
+
+ //If instruction is odd-sized or if "real" op code is out of range, give up and return ERR_INSTR
+ if ((InstrSize & 0x01) || OP_CODE(pInstr) >= OPCODE_COUNT)
+ return (ERR_INSTR);
+
+ InterpFuncIndex = (InstrSize / 2) - 1;
+
+#ifdef USE_SHORT_OPS
+ //If instruction has shortened encoding, add 1 for true interpretter
+ if (IS_SHORT_OP(pInstr))
+ {
+ InterpFuncIndex++;
+ }
+#endif
+
+ //Peg InterpFuncIndex to 'Other'. Illegal instructions will be caught in cCmdInterpOther().
+ if (InterpFuncIndex > 4)
+ InterpFuncIndex = 4;
+
+ //If instruction is variably-sized; true size is held in the first argument
+ //!!! This InstrSize wrangling MUST occur after computing InterpFuncIndex
+ //because variable sized instructions may confuse the code otherwise
+ if (InstrSize == VAR_INSTR_SIZE)
+ InstrSize = (UBYTE)(pInstr[1]);
+
+ //Set ScratchPC to clump's current PC so sub-interpreters can apply relative offsets
+ VarsCmd.ScratchPC = pClumpRec->PC;
+
+ //Set CallerClump to Clump, for use by instructions such as OP_ACQUIRE
+ VarsCmd.CallerClump = Clump;
+
+ Status = (*InterpFuncs[InterpFuncIndex])(pInstr);
+
+ if (Status == ERR_MEM)
+ {
+ //Memory is full. Compact dataspace and try the instruction again.
+ //!!! Could compact DopeVectorArray here
+ cCmdDSCompact();
+ Status = (*InterpFuncs[InterpFuncIndex])(pInstr);
+ }
+
+ if (!IS_ERR(Status))
+ {
+ //If clump is finished, reset PC and firecount
+ if (Status == CLUMP_DONE)
+ {
+ pClumpRec->PC = 0;
+ pClumpRec->CurrFireCount = pClumpRec->InitFireCount;
+ }
+ //Else, if instruction has provided override program counter, use it
+ else if (Status == PC_OVERRIDE)
+ {
+ pClumpRec->PC = VarsCmd.ScratchPC;
+ }
+ //Else, auto-advance from encoded instruction size (PC is word-based)
+ else
+ {
+ pClumpRec->PC += InstrSize / 2;
+ }
+
+ //Throw error if we ever advance beyond the clump's codespace
+ if (pClumpRec->PC > cCmdGetCodespaceCount(Clump))
+ {
+ NXT_BREAK;
+ Status = ERR_INSTR;
+ }
+ }
+
+#if VM_BENCHMARK
+ //Increment opcode count
+ VarsCmd.OpcodeBenchmarks[OP_CODE(pInstr)][0]++;
+
+ InstrTime = dTimerRead() - InstrTime;
+ if (InstrTime > 1)
+ {
+ VarsCmd.OpcodeBenchmarks[OP_CODE(pInstr)][1]++;
+ if (InstrTime > VarsCmd.OpcodeBenchmarks[OP_CODE(pInstr)][2])
+ VarsCmd.OpcodeBenchmarks[OP_CODE(pInstr)][2] = InstrTime;
+ }
+#endif
+
+ return (Status);
+}
+
+
+NXT_STATUS cCmdInterpUnop1(CODE_WORD * const pCode)
+{
+ NXT_STATUS Status = NO_ERR;
+ UBYTE opCode;
+ DATA_ARG Arg1;
+ void *pArg1 = NULL;
+ TYPE_CODE TypeCode1;
+
+ NXT_ASSERT(pCode != NULL);
+
+#ifdef USE_SHORT_OPS
+ if (IS_SHORT_OP(pCode))
+ {
+ //add mapping from quick op to real op
+ opCode = ShortOpMap[SHORT_OP_CODE(pCode)];
+ Arg1 = SHORT_ARG(pCode);
+ }
+ else
+ {
+ opCode = OP_CODE(pCode);
+ Arg1 = pCode[1];
+ }
+#else
+ opCode = OP_CODE(pCode);
+ Arg1 = pCode[1];
+#endif //USE_SHORT_OPS
+
+
+ switch (opCode)
+ {
+ case OP_JMP:
+ {
+ VarsCmd.ScratchPC = VarsCmd.ScratchPC + (SWORD)Arg1;
+ Status = PC_OVERRIDE;
+ }
+ break;
+
+ case OP_ACQUIRE:
+ {
+ NXT_ASSERT(cCmdIsDSElementIDSane(Arg1));
+ NXT_ASSERT(VarsCmd.pDataspaceTOC[Arg1].TypeCode == TC_MUTEX);
+
+ Status = cCmdAcquireMutex((MUTEX_Q *)cCmdDSPtr(Arg1, 0), VarsCmd.CallerClump);
+ }
+ break;
+
+ case OP_RELEASE:
+ {
+ NXT_ASSERT(cCmdIsDSElementIDSane(Arg1));
+ NXT_ASSERT(VarsCmd.pDataspaceTOC[Arg1].TypeCode == TC_MUTEX);
+
+ Status = cCmdReleaseMutex((MUTEX_Q *)cCmdDSPtr(Arg1, 0), VarsCmd.CallerClump);
+ }
+ break;
+
+ case OP_SUBRET:
+ {
+ NXT_ASSERT(cCmdIsDSElementIDSane(Arg1));
+
+ //Take Subroutine off RunQ
+ //Add Subroutine's caller to RunQ
+ cCmdDeQClump(&(VarsCmd.RunQ), VarsCmd.CallerClump);
+ cCmdEnQClump(&(VarsCmd.RunQ), *((CLUMP_ID *)cCmdDSPtr(Arg1, 0)));
+
+ Status = CLUMP_DONE;
+ }
+ break;
+
+ case OP_FINCLUMPIMMED:
+ {
+ cCmdDeQClump(&(VarsCmd.RunQ), VarsCmd.CallerClump); //Dequeue finalized clump
+ cCmdSchedDependent(VarsCmd.CallerClump, (CLUMP_ID)Arg1); // Use immediate form
+
+ Status = CLUMP_DONE;
+ }
+ break;
+
+ case OP_GETTICK:
+ {
+ pArg1 = cCmdResolveDataArg(Arg1, 0, &TypeCode1);
+
+
+ cCmdSetVal(pArg1, TypeCode1, dTimerRead());
+ }
+ break;
+
+ case OP_STOP:
+ {
+ //Unwired Arg1 means always stop
+ if (Arg1 == NOT_A_DS_ID)
+ {
+ Status = STOP_REQ;
+ }
+ else
+ {
+ pArg1 = cCmdResolveDataArg(Arg1, 0, &TypeCode1);
+
+ if (cCmdGetVal(pArg1, TypeCode1) > 0)
+ Status = STOP_REQ;
+ }
+ }
+ break;
+
+ default:
+ {
+ //Fatal error: Unrecognized instruction
+ NXT_BREAK;
+ Status = ERR_INSTR;
+ }
+ break;
+ }
+
+ return (Status);
+}
+
+
+NXT_STATUS cCmdInterpUnop2(CODE_WORD * const pCode)
+{
+ NXT_STATUS Status = NO_ERR;
+ UBYTE opCode;
+ DATA_ARG Arg1;
+ DATA_ARG Arg2;
+ void *pArg1 = NULL, *pArg2 = NULL;
+ TYPE_CODE TypeCode1, TypeCode2;
+
+ ULONG i;
+ UWORD ArgC;
+ static UBYTE * ArgV[MAX_CALL_ARGS + 1];
+
+ UWORD Count;
+ UWORD Offset;
+ SLONG TmpSLong;
+ ULONG TmpULong;
+ ULONG ArgVal2;
+
+ NXT_ASSERT(pCode != NULL);
+
+#ifdef USE_SHORT_OPS
+ if (IS_SHORT_OP(pCode))
+ {
+ //add mapping from quick op to real op
+ opCode = ShortOpMap[SHORT_OP_CODE(pCode)];
+ Arg1 = SHORT_ARG(pCode) + pCode[1];
+ Arg2 = pCode[1];
+ }
+ else
+ {
+ opCode = OP_CODE(pCode);
+ Arg1 = pCode[1];
+ Arg2 = pCode[2];
+ }
+#else
+ opCode = OP_CODE(pCode);
+ Arg1 = pCode[1];
+ Arg2 = pCode[2];
+#endif //USE_SHORT_OPS
+
+ if (opCode == OP_NEG || opCode == OP_NOT || opCode == OP_TST)
+ {
+ return cCmdInterpPolyUnop2(*pCode, Arg1, 0, Arg2, 0);
+ }
+
+ switch (opCode)
+ {
+ case OP_MOV:
+ {
+ //!!! Optimized move for byte arrays (makes File I/O involving CStrs tolerable). Optimize for other cases?
+ if ((cCmdDSType(Arg1) == TC_ARRAY) && (cCmdDSType(INC_ID(Arg1)) == TC_UBYTE) &&
+ (cCmdDSType(Arg2) == TC_ARRAY) && (cCmdDSType(INC_ID(Arg2)) == TC_UBYTE))
+ {
+ Count = cCmdArrayCount(Arg2, 0);
+ Status = cCmdDSArrayAlloc(Arg1, 0, Count);
+ if (IS_ERR(Status))
+ return Status;
+
+ pArg1 = cCmdResolveDataArg(Arg1, 0, NULL);
+ pArg2 = cCmdResolveDataArg(Arg2, 0, NULL);
+
+ memmove(pArg1, pArg2, Count);
+ }
+ else
+ {
+ Status = cCmdInterpPolyUnop2(OP_MOV, Arg1, 0, Arg2, 0);
+ }
+ }
+ break;
+
+ case OP_SET:
+ {
+ //!!! Should throw error if TypeCode1 is non-scalar
+ // Accepting non-scalar destinations could have unpredictable results!
+ pArg1 = cCmdResolveDataArg(Arg1, 0, &TypeCode1);
+ cCmdSetVal(pArg1, TypeCode1, Arg2);
+ }
+ break;
+
+ case OP_BRTST:
+ {
+ pArg2 = cCmdResolveDataArg(Arg2, 0, &TypeCode2);
+ if (cCmdCompare(COMP_CODE(pCode), (SLONG)cCmdGetVal(pArg2, TypeCode2), 0, TC_SLONG, TC_SLONG))
+ {
+ VarsCmd.ScratchPC = VarsCmd.ScratchPC + (SWORD)Arg1;
+ Status = PC_OVERRIDE;
+ }
+ }
+ break;
+
+ case OP_FINCLUMP:
+ {
+ cCmdDeQClump(&(VarsCmd.RunQ), VarsCmd.CallerClump); //Dequeue finalized clump
+ cCmdSchedDependents(VarsCmd.CallerClump, (SWORD)Arg1, (SWORD)Arg2);
+
+ Status = CLUMP_DONE;
+ }
+ break;
+
+ case OP_SUBCALL:
+ {
+ NXT_ASSERT(cCmdIsClumpIDSane((CLUMP_ID)Arg1));
+ NXT_ASSERT(!cCmdIsClumpOnQ(&(VarsCmd.RunQ), (CLUMP_ID)Arg1));
+
+ NXT_ASSERT(cCmdIsDSElementIDSane(Arg2));
+
+ *((CLUMP_ID *)(cCmdDSPtr(Arg2, 0))) = VarsCmd.CallerClump;
+
+ cCmdDeQClump(&(VarsCmd.RunQ), VarsCmd.CallerClump); //Take caller off RunQ
+ cCmdEnQClump(&(VarsCmd.RunQ), (CLUMP_ID)Arg1); //Add callee to RunQ
+
+ Status = CLUMP_SUSPEND;
+ }
+ break;
+
+ case OP_ARRSIZE:
+ {
+ pArg1 = cCmdResolveDataArg(Arg1, 0, &TypeCode1);
+ cCmdSetVal(pArg1, TypeCode1, cCmdArrayCount(Arg2, 0));
+ }
+ break;
+
+ case OP_SYSCALL:
+ {
+ if (Arg1 >= SYSCALL_COUNT)
+ {
+ NXT_BREAK;
+ Status = ERR_INSTR;
+ break;
+ }
+
+ ArgC = cCmdClusterCount(Arg2);
+
+ if (ArgC > MAX_CALL_ARGS)
+ {
+ NXT_BREAK;
+ Status = ERR_INSTR;
+ break;
+ }
+
+ if (ArgC > 0)
+ {
+ Arg2 = INC_ID(Arg2);
+
+ for (i = 0; i < ArgC; i++)
+ {
+ if (cCmdDSType(Arg2) == TC_ARRAY)
+ {
+ //Storing pointer to array's DV_INDEX
+ //!!! This resolve is different than cCmdDSPtr
+ // since SysCalls may need the DVIndex to re-alloc arrays
+ ArgV[i] = VarsCmd.pDataspace + VarsCmd.pDataspaceTOC[Arg2].DSOffset;
+ }
+ else
+ {
+ ArgV[i] = cCmdDSPtr(Arg2, 0);
+ }
+
+ //If any argument fails to resolve, return a fatal error.
+ if (ArgV[i] == NULL)
+ {
+ Status = ERR_BAD_PTR;
+ break;
+ }
+
+ Arg2 = cCmdNextDSElement(Arg2);
+ }
+ }
+ else
+ {
+ i = 0;
+ }
+
+ //ArgV list is null terminated
+ ArgV[i] = NULL;
+
+ Status = (*SysCallFuncs[Arg1])(ArgV);
+ }
+ break;
+
+ case OP_FLATTEN:
+ {
+ //Flatten Arg2 to a NULL terminated string
+
+ //Assert that the destination is a string (array of bytes)
+ NXT_ASSERT(cCmdDSType(Arg1) == TC_ARRAY);
+ NXT_ASSERT(cCmdDSType(INC_ID(Arg1)) == TC_UBYTE);
+
+ Count = cCmdCalcFlattenedSize(Arg2, 0);
+ //Add room for NULL terminator
+ Count++;
+ Status = cCmdDSArrayAlloc(Arg1, 0, Count);
+ if (IS_ERR(Status))
+ return Status;
+
+ pArg1 = cCmdResolveDataArg(Arg1, 0, NULL);
+ Offset = 0;
+
+ Status = cCmdFlattenToByteArray(pArg1, &Offset, Arg2, 0);
+ //Append NULL terminator
+ *((UBYTE *)pArg1 + Offset) = 0;
+ Offset++;
+ NXT_ASSERT(Offset == Count);
+ }
+ break;
+
+ case OP_NUMTOSTRING:
+ {
+ //Assert that the destination is a string (array of bytes)
+ NXT_ASSERT(cCmdDSType(Arg1) == TC_ARRAY);
+ NXT_ASSERT(cCmdDSType(INC_ID(Arg1)) == TC_UBYTE);
+
+ pArg2 = cCmdResolveDataArg(Arg2, 0, &TypeCode2);
+ //Make sure we're trying to convert a scalar to a string
+ NXT_ASSERT(!IS_AGGREGATE_TYPE(TypeCode2));
+
+ ArgVal2 = cCmdGetVal(pArg2, TypeCode2);
+
+ //Calculate size of array
+ if (ArgVal2 == 0)
+ Count = 1;
+ else
+ Count = 0;
+
+ if (TypeCode2 == TC_SLONG || TypeCode2 == TC_SWORD || TypeCode2 == TC_SBYTE)
+ {
+ TmpSLong = (SLONG)ArgVal2;
+ //Add room for negative sign
+ if (TmpSLong < 0)
+ Count++;
+
+ while (TmpSLong)
+ {
+ TmpSLong /= 10;
+ Count++;
+ }
+ }
+ else
+ {
+ TmpULong = ArgVal2;
+ while (TmpULong)
+ {
+ TmpULong /= 10;
+ Count++;
+ }
+ }
+
+ //add room for NULL terminator
+ Count++;
+
+ //Allocate array
+ Status = cCmdDSArrayAlloc(Arg1, 0, Count);
+ if (IS_ERR(Status))
+ return Status;
+
+ pArg1 = cCmdResolveDataArg(Arg1, 0, &TypeCode1);
+
+ //Populate array
+ if (TypeCode2 == TC_SLONG || TypeCode2 == TC_SWORD || TypeCode2 == TC_SBYTE)
+ {
+ sprintf(pArg1, "%d", (SLONG)ArgVal2);
+ }
+ else
+ {
+ sprintf(pArg1, "%u", ArgVal2);
+ }
+ }
+ break;
+
+ case OP_STRTOBYTEARR:
+ {
+ NXT_ASSERT((cCmdDSType(Arg1) == TC_ARRAY) && (cCmdDSType(INC_ID(Arg1)) == TC_UBYTE));
+ NXT_ASSERT((cCmdDSType(Arg2) == TC_ARRAY) && (cCmdDSType(INC_ID(Arg2)) == TC_UBYTE));
+
+ Count = cCmdArrayCount(Arg2, 0);
+
+ if (Count > 0)
+ {
+ Status = cCmdDSArrayAlloc(Arg1, 0, (UWORD)(Count - 1));
+ if (IS_ERR(Status))
+ return Status;
+
+ pArg1 = cCmdResolveDataArg(Arg1, 0, NULL);
+ pArg2 = cCmdResolveDataArg(Arg2, 0, NULL);
+
+ memmove(pArg1, pArg2, Count - 1);
+ }
+ }
+ break;
+
+ case OP_BYTEARRTOSTR:
+ {
+ NXT_ASSERT((cCmdDSType(Arg1) == TC_ARRAY) && (cCmdDSType(INC_ID(Arg1)) == TC_UBYTE));
+ NXT_ASSERT((cCmdDSType(Arg2) == TC_ARRAY) && (cCmdDSType(INC_ID(Arg2)) == TC_UBYTE));
+
+ Count = cCmdArrayCount(Arg2, 0);
+
+ Status = cCmdDSArrayAlloc(Arg1, 0, (UWORD)(Count + 1));
+ if (IS_ERR(Status))
+ return Status;
+
+ pArg1 = cCmdResolveDataArg(Arg1, 0, NULL);
+ pArg2 = cCmdResolveDataArg(Arg2, 0, NULL);
+
+ memmove(pArg1, pArg2, Count);
+ *((UBYTE *)pArg1 + Count) = '\0';
+ }
+ break;
+
+ default:
+ {
+ //Fatal error: Unrecognized instruction
+ NXT_BREAK;
+ Status = ERR_INSTR;
+ }
+ break;
+ }
+
+ return (Status);
+}
+
+
+NXT_STATUS cCmdInterpPolyUnop2(CODE_WORD const Code, DATA_ARG Arg1, UWORD Offset1, DATA_ARG Arg2, UWORD Offset2)
+{
+ NXT_STATUS Status = NO_ERR;
+ TYPE_CODE TypeCode1, TypeCode2;
+ DV_INDEX DVIndex1, DVIndex2;
+ ULONG ArgVal1, ArgVal2;
+ UWORD Count1, Count2;
+ UWORD MinArrayCount;
+ UWORD i;
+ //!!! AdvCluster is intended to catch the case where sources are Cluster and an Array of Clusters.
+ // In practice, the logic it uses is broken, leading to some source cluster elements being ignored.
+ UBYTE AdvCluster;
+
+ void * pArg1 = NULL,
+ *pArg2 = NULL;
+
+ TypeCode1 = cCmdDSType(Arg1);
+ TypeCode2 = cCmdDSType(Arg2);
+
+ //Simple case, scalar. Solve and return.
+ if (!IS_AGGREGATE_TYPE(TypeCode2))
+ {
+ NXT_ASSERT(!IS_AGGREGATE_TYPE(TypeCode1));
+
+ pArg1 = cCmdResolveDataArg(Arg1, Offset1, &TypeCode1);
+ pArg2 = cCmdResolveDataArg(Arg2, Offset2, &TypeCode2);
+
+ ArgVal2 = cCmdGetVal(pArg2, TypeCode2);
+ ArgVal1 = cCmdUnop2(Code, ArgVal2, TypeCode2);
+ cCmdSetVal(pArg1, TypeCode1, ArgVal1);
+ return Status;
+ }
+
+ //At least one of the args is an aggregate type
+
+ //
+ // Initialize Count and ArrayType local variables for each argument
+ //
+
+ if (TypeCode2 == TC_ARRAY)
+ {
+ Count2 = cCmdArrayCount(Arg2, Offset2);
+ DVIndex2 = cCmdGetDVIndex(Arg2, Offset2);
+ Offset2 = DV_ARRAY[DVIndex2].Offset;
+ }
+ else if (TypeCode2 == TC_CLUSTER)
+ {
+ Count2 = cCmdClusterCount(Arg2);
+ }
+
+ if (TypeCode1 == TC_ARRAY)
+ {
+ if (TypeCode2 != TC_ARRAY)
+ {
+ //If output is an array, but source is not an array, that's a fatal error!
+ NXT_BREAK;
+ return (ERR_ARG);
+ }
+
+ MinArrayCount = Count2;
+
+ //Make sure the destination array is the proper size to hold the result
+ Status = cCmdDSArrayAlloc(Arg1, Offset1, MinArrayCount);
+ if (IS_ERR(Status))
+ return Status;
+
+ Count1 = MinArrayCount;
+ DVIndex1 = cCmdGetDVIndex(Arg1, Offset1);
+ Offset1 = DV_ARRAY[DVIndex1].Offset;
+ AdvCluster = FALSE;
+ }
+ else if (TypeCode1 == TC_CLUSTER)
+ {
+ Count1 = cCmdClusterCount(Arg1);
+ AdvCluster = TRUE;
+ }
+
+ //Advance aggregate args to first sub-element for next call
+ if (IS_AGGREGATE_TYPE(TypeCode1))
+ Arg1 = INC_ID(Arg1);
+ if (IS_AGGREGATE_TYPE(TypeCode2))
+ Arg2 = INC_ID(Arg2);
+
+ //
+ // Loop through the sub-elements of aggregate arguments.
+ // Call cCmdInterpPolyUnop2 recursively with simpler type.
+ //
+
+ for (i = 0; i < Count1; i++)
+ {
+ Status = cCmdInterpPolyUnop2(Code, Arg1, Offset1, Arg2, Offset2);
+ if (IS_ERR(Status))
+ return Status;
+
+ //Advance aggregate args to next sub-element
+ if (TypeCode1 == TC_ARRAY)
+ Offset1 += DV_ARRAY[DVIndex1].ElemSize;
+ else if ((TypeCode1 == TC_CLUSTER) && AdvCluster)
+ Arg1 = cCmdNextDSElement(Arg1);
+
+ if (TypeCode2 == TC_ARRAY)
+ Offset2 += DV_ARRAY[DVIndex2].ElemSize;
+ else if ((TypeCode2 == TC_CLUSTER) && AdvCluster)
+ Arg2 = cCmdNextDSElement(Arg2);
+ }
+
+ return Status;
+}
+
+
+ULONG cCmdUnop2(CODE_WORD const Code, ULONG Operand, TYPE_CODE TypeCode)
+{
+ UBYTE opCode;
+
+ opCode = OP_CODE((&Code));
+
+ switch (opCode)
+ {
+ case OP_MOV:
+ {
+ return Operand;
+ }
+
+ case OP_NEG:
+ {
+ return (-((SLONG)Operand));
+ }
+
+ case OP_NOT:
+ {
+ //!!! OP_NOT is logical, *not* bit-wise.
+ //This differs from the other logical ops because we don't distinguish booleans from UBYTEs.
+ return (!Operand);
+ }
+
+ case OP_TST:
+ {
+ return cCmdCompare(COMP_CODE((&Code)), Operand, 0, TypeCode, TypeCode);
+ }
+
+ default:
+ {
+ //Unrecognized instruction, NXT_BREAK for easy debugging (ERR_INSTR handled in caller)
+ NXT_BREAK;
+ return 0;
+ }
+ }
+}
+
+
+NXT_STATUS cCmdInterpBinop(CODE_WORD * const pCode)
+{
+ NXT_STATUS Status = NO_ERR;
+ UBYTE opCode;
+ DATA_ARG Arg1, Arg2, Arg3;
+ TYPE_CODE TypeCode1, TypeCode2, TypeCode3;
+ ULONG ArgVal2, ArgVal3;
+ UBYTE CmpBool;
+ DV_INDEX DVIndex1, DVIndex2;
+ UWORD i;
+
+ void * pArg1 = NULL,
+ *pArg2 = NULL,
+ *pArg3 = NULL;
+
+ NXT_ASSERT(pCode != NULL);
+#ifdef USE_SHORT_OPS
+ if (IS_SHORT_OP(pCode))
+ {
+ //add mapping from quick op to real op
+ opCode = ShortOpMap[SHORT_OP_CODE(pCode)];
+ Arg1 = SHORT_ARG(pCode) + pCode[1];
+ Arg2 = pCode[1];
+ Arg3 = pCode[2];
+ }
+ else
+ {
+ opCode = OP_CODE(pCode);
+ Arg1 = pCode[1];
+ Arg2 = pCode[2];
+ Arg3 = pCode[3];
+ }
+#else
+ opCode = OP_CODE(pCode);
+ Arg1 = pCode[1];
+ Arg2 = pCode[2];
+ Arg3 = pCode[3];
+#endif //USE_SHORT_OPS
+
+ if (opCode == OP_ADD || opCode == OP_SUB || opCode == OP_MUL || opCode == OP_DIV || opCode == OP_MOD ||
+ opCode == OP_AND || opCode == OP_OR || opCode == OP_XOR)
+ {
+ return cCmdInterpPolyBinop(opCode, Arg1, 0, Arg2, 0, Arg3, 0);
+ }
+
+ //Resolve data arguments, except for opcodes which the arguments are not DataArgs
+ if (opCode != OP_BRCMP)
+ {
+ pArg1 = cCmdResolveDataArg(Arg1, 0, &TypeCode1);
+ }
+
+ if (opCode != OP_INDEX)
+ {
+ pArg2 = cCmdResolveDataArg(Arg2, 0, &TypeCode2);
+ ArgVal2 = cCmdGetVal(pArg2, TypeCode2);
+ }
+
+ if ((opCode != OP_GETOUT) && (opCode != OP_SETIN) && (opCode != OP_GETIN) && (opCode != OP_INDEX) && (opCode != OP_ARRINIT))
+ {
+ pArg3 = cCmdResolveDataArg(Arg3, 0, &TypeCode3);
+ ArgVal3 = cCmdGetVal(pArg3, TypeCode3);
+ }
+
+ switch (opCode)
+ {
+
+ case OP_CMP:
+ {
+ if (!IS_AGGREGATE_TYPE(cCmdDSType(Arg1)) && IS_AGGREGATE_TYPE(cCmdDSType(Arg2)) && IS_AGGREGATE_TYPE(cCmdDSType(Arg3)))
+ {
+ //Compare Aggregates
+ Status = cCmdCompareAggregates(COMP_CODE(pCode), &CmpBool, Arg2, 0, Arg3, 0);
+ cCmdSetVal(pArg1, TypeCode1, CmpBool);
+ }
+ else
+ {
+ //Compare Elements
+ Status = cCmdInterpPolyBinop(*pCode, Arg1, 0, Arg2, 0, Arg3, 0);
+ }
+ }
+ break;
+
+ case OP_BRCMP:
+ {
+ //Compare Aggregates
+ Status = cCmdCompareAggregates(COMP_CODE(pCode), &CmpBool, Arg2, 0, Arg3, 0);
+
+ if (CmpBool)
+ {
+ VarsCmd.ScratchPC = VarsCmd.ScratchPC + (SWORD)Arg1;
+ Status = PC_OVERRIDE;
+ }
+ }
+ break;
+
+ case OP_GETOUT:
+ {
+ Arg2 = (UWORD)(0xC200 | (Arg3 + ArgVal2 * IO_OUT_FPP));
+ pArg2 = cCmdResolveDataArg(Arg2, 0, &TypeCode2);
+
+ cCmdSetVal(pArg1, TypeCode1, cCmdGetVal(pArg2, TypeCode2));
+ }
+ break;
+
+ //!!! All IO map access commands should screen illegal port values!
+ // Right now, cCmdResolveDataArg's implementation allows SETIN/GETIN to access arbitrary RAM!
+ case OP_SETIN:
+ {
+ Arg2 = (UWORD)(0xC000 | (Arg3 + ArgVal2 * IO_IN_FPP));
+ pArg2 = cCmdResolveDataArg(Arg2, 0, &TypeCode2);
+
+ cCmdSetVal(pArg2, TypeCode2, cCmdGetVal(pArg1, TypeCode1));
+ }
+ break;
+
+ case OP_GETIN:
+ {
+ Arg2 = (UWORD)(0xC000 | (Arg3 + ArgVal2 * IO_IN_FPP));
+ pArg2 = cCmdResolveDataArg(Arg2, 0, &TypeCode2);
+
+ cCmdSetVal(pArg1, TypeCode1, cCmdGetVal(pArg2, TypeCode2));
+ }
+ break;
+
+ case OP_INDEX:
+ {
+ if (Arg3 != NOT_A_DS_ID)
+ {
+ pArg3 = cCmdResolveDataArg(Arg3, 0, &TypeCode3);
+ ArgVal3 = cCmdGetVal(pArg3, TypeCode3);
+ }
+ else //Index input unwired
+ {
+ ArgVal3 = 0;
+ }
+
+ DVIndex2 = cCmdGetDVIndex(Arg2, 0);
+ if (ArgVal3 >= DV_ARRAY[DVIndex2].Count)
+ return (ERR_ARG);
+
+ Status = cCmdInterpPolyUnop2(OP_MOV, Arg1, 0, INC_ID(Arg2), ARRAY_ELEM_OFFSET(DVIndex2, ArgVal3));
+ }
+ break;
+
+ case OP_ARRINIT:
+ {
+ //Arg1 - Dst, Arg2 - element type/default val, Arg3 - length
+
+ NXT_ASSERT(TypeCode1 == TC_ARRAY);
+
+ if (Arg3 != NOT_A_DS_ID)
+ {
+ pArg3 = cCmdResolveDataArg(Arg3, 0, &TypeCode3);
+ ArgVal3 = cCmdGetVal(pArg3, TypeCode3);
+ }
+ else //Length input unwired
+ {
+ ArgVal3 = 0;
+ }
+
+ Status = cCmdDSArrayAlloc(Arg1, 0, (UWORD)ArgVal3);
+ if (IS_ERR(Status))
+ return Status;
+
+ DVIndex1 = cCmdGetDVIndex(Arg1, 0);
+ for (i = 0; i < ArgVal3; i++)
+ {
+ //copy Arg2 into each element of Arg1
+ Status = cCmdInterpPolyUnop2(OP_MOV, INC_ID(Arg1), ARRAY_ELEM_OFFSET(DVIndex1, i), Arg2, 0);
+ }
+ }
+ break;
+
+ default:
+ {
+ //Fatal error: Unrecognized instruction
+ NXT_BREAK;
+ Status = ERR_INSTR;
+ }
+ break;
+ }
+
+ return (Status);
+}
+
+
+NXT_STATUS cCmdInterpPolyBinop(CODE_WORD const Code, DATA_ARG Arg1, UWORD Offset1, DATA_ARG Arg2, UWORD Offset2, DATA_ARG Arg3, UWORD Offset3)
+{
+ NXT_STATUS Status = NO_ERR;
+ TYPE_CODE TypeCode1, TypeCode2, TypeCode3;
+ DV_INDEX DVIndex1, DVIndex2, DVIndex3;
+ ULONG ArgVal1, ArgVal2, ArgVal3;
+ UWORD Count1, Count2, Count3;
+ UWORD MinArrayCount;
+ UWORD i;
+ //!!! AdvCluster is intended to catch the case where sources are Cluster and an Array of Clusters.
+ // In practice, the logic it uses is broken, leading to some source cluster elements being ignored.
+ UBYTE AdvCluster;
+
+ void * pArg1 = NULL,
+ *pArg2 = NULL,
+ *pArg3 = NULL;
+
+ TypeCode1 = cCmdDSType(Arg1);
+ TypeCode2 = cCmdDSType(Arg2);
+ TypeCode3 = cCmdDSType(Arg3);
+
+ //Simple case, both args are scalars. Solve and return.
+ if ((!IS_AGGREGATE_TYPE(TypeCode2)) && (!IS_AGGREGATE_TYPE(TypeCode3)))
+ {
+ NXT_ASSERT(!IS_AGGREGATE_TYPE(TypeCode1));
+
+ pArg1 = cCmdResolveDataArg(Arg1, Offset1, &TypeCode1);
+ pArg2 = cCmdResolveDataArg(Arg2, Offset2, &TypeCode2);
+ pArg3 = cCmdResolveDataArg(Arg3, Offset3, &TypeCode3);
+
+ ArgVal2 = cCmdGetVal(pArg2, TypeCode2);
+ ArgVal3 = cCmdGetVal(pArg3, TypeCode3);
+ ArgVal1 = cCmdBinop(Code, ArgVal2, ArgVal3, TypeCode2, TypeCode3);
+ cCmdSetVal(pArg1, TypeCode1, ArgVal1);
+ return Status;
+ }
+
+ //At least one of the args is an aggregate type
+
+ //
+ // Initialize Count and ArrayType local variables for each argument
+ //
+
+ if (TypeCode2 == TC_ARRAY)
+ {
+ Count2 = cCmdArrayCount(Arg2, Offset2);
+ DVIndex2 = cCmdGetDVIndex(Arg2, Offset2);
+ Offset2 = DV_ARRAY[DVIndex2].Offset;
+ }
+ else if (TypeCode2 == TC_CLUSTER)
+ {
+ Count2 = cCmdClusterCount(Arg2);
+ }
+
+ if (TypeCode3 == TC_ARRAY)
+ {
+ Count3 = cCmdArrayCount(Arg3, Offset3);
+ DVIndex3 = cCmdGetDVIndex(Arg3, Offset3);
+ Offset3 = DV_ARRAY[DVIndex3].Offset;
+ }
+ else if (TypeCode3 == TC_CLUSTER)
+ {
+ Count3 = cCmdClusterCount(Arg3);
+ }
+
+
+ if (TypeCode1 == TC_ARRAY)
+ {
+ //If the destination is an array, make sure it has enough memory to hold the result
+ if ((TypeCode2 == TC_ARRAY) && (TypeCode3 == TC_ARRAY))
+ {
+ if (Count2 < Count3)
+ MinArrayCount = Count2;
+ else
+ MinArrayCount = Count3;
+ }
+ else if (TypeCode2 == TC_ARRAY)
+ MinArrayCount = Count2;
+ else if (TypeCode3 == TC_ARRAY)
+ MinArrayCount = Count3;
+ else
+ {
+ //If output is an array, but no sources are arrays, that's a fatal error!
+ NXT_BREAK;
+ return (ERR_ARG);
+ }
+
+ //Make sure the destination array is the proper size to hold the result
+ Status = cCmdDSArrayAlloc(Arg1, Offset1, MinArrayCount);
+ if (IS_ERR(Status))
+ return Status;
+
+ Count1 = MinArrayCount;
+ DVIndex1 = cCmdGetDVIndex(Arg1, Offset1);
+ Offset1 = DV_ARRAY[DVIndex1].Offset;
+ AdvCluster = FALSE;
+ }
+ else if (TypeCode1 == TC_CLUSTER)
+ {
+ Count1 = cCmdClusterCount(Arg1);
+ AdvCluster = TRUE;
+ }
+
+ //Advance aggregate args to first sub-element for next call
+ if (IS_AGGREGATE_TYPE(TypeCode1))
+ Arg1 = INC_ID(Arg1);
+ if (IS_AGGREGATE_TYPE(TypeCode2))
+ Arg2 = INC_ID(Arg2);
+ if (IS_AGGREGATE_TYPE(TypeCode3))
+ Arg3 = INC_ID(Arg3);
+
+ //
+ // Loop through the sub-elements of aggregate arguments.
+ // Call cCmdInterpPolyBinop recursively with simpler type.
+ //
+
+ for (i = 0; i < Count1; i++)
+ {
+ Status = cCmdInterpPolyBinop(Code, Arg1, Offset1, Arg2, Offset2, Arg3, Offset3);
+ if (IS_ERR(Status))
+ return Status;
+
+ //Advance aggregate args to next sub-element
+ if (TypeCode1 == TC_ARRAY)
+ Offset1 += DV_ARRAY[DVIndex1].ElemSize;
+ else if ((TypeCode1 == TC_CLUSTER) && AdvCluster)
+ Arg1 = cCmdNextDSElement(Arg1);
+
+ if (TypeCode2 == TC_ARRAY)
+ Offset2 += DV_ARRAY[DVIndex2].ElemSize;
+ else if ((TypeCode2 == TC_CLUSTER) && AdvCluster)
+ Arg2 = cCmdNextDSElement(Arg2);
+
+ if (TypeCode3 == TC_ARRAY)
+ Offset3 += DV_ARRAY[DVIndex3].ElemSize;
+ else if ((TypeCode3 == TC_CLUSTER) && AdvCluster)
+ Arg3 = cCmdNextDSElement(Arg3);
+ }
+
+ return Status;
+}
+
+
+ULONG cCmdBinop(CODE_WORD const Code, ULONG LeftOp, ULONG RightOp, TYPE_CODE LeftType, TYPE_CODE RightType)
+{
+ UBYTE opCode;
+
+ opCode = OP_CODE((&Code));
+
+ switch (opCode)
+ {
+ case OP_ADD:
+ {
+ return LeftOp + RightOp;
+ }
+
+ case OP_SUB:
+ {
+ return LeftOp - RightOp;
+ }
+
+ case OP_MUL:
+ {
+ return LeftOp * RightOp;
+ }
+
+ case OP_DIV:
+ {
+ //Catch divide-by-zero for a portable, well-defined result.
+ //(x / 0) = 0. Thus Spake LOTHAR!! (It's technical.)
+ if (RightOp == 0)
+ return 0;
+
+ if (IS_SIGNED_TYPE(LeftType) && IS_SIGNED_TYPE(RightType))
+ return ((SLONG)LeftOp) / ((SLONG)RightOp);
+ else if (IS_SIGNED_TYPE(LeftType))
+ return ((SLONG)LeftOp) / RightOp;
+ else if (IS_SIGNED_TYPE(RightType))
+ return LeftOp / ((SLONG)RightOp);
+ else
+ return LeftOp / RightOp;
+ }
+
+ case OP_MOD:
+ {
+ //As with OP_DIV, make sure (x % 0) = x is well-defined
+ if (RightOp == 0)
+ return (LeftOp);
+
+ if (IS_SIGNED_TYPE(LeftType) && IS_SIGNED_TYPE(RightType))
+ return ((SLONG)LeftOp) % ((SLONG)RightOp);
+ else if (IS_SIGNED_TYPE(LeftType))
+ return ((SLONG)LeftOp) % RightOp;
+ else if (IS_SIGNED_TYPE(RightType))
+ return LeftOp % ((SLONG)RightOp);
+ else
+ return LeftOp % RightOp;
+ }
+
+ case OP_AND:
+ {
+ return (LeftOp & RightOp);
+ }
+
+ case OP_OR:
+ {
+ return (LeftOp | RightOp);
+ }
+
+ case OP_XOR:
+ {
+ return ((LeftOp | RightOp) & (~(LeftOp & RightOp)));
+ }
+
+ case OP_CMP:
+ {
+ return cCmdCompare(COMP_CODE((&Code)), LeftOp, RightOp, LeftType, RightType);
+ }
+
+ default:
+ {
+ //Unrecognized instruction, NXT_BREAK for easy debugging (ERR_INSTR handled in caller)
+ NXT_BREAK;
+ return 0;
+ }
+ }
+}
+
+NXT_STATUS cCmdInterpNoArg(CODE_WORD * const pCode)
+{
+ //Fatal error: Unrecognized instruction (no current opcodes have zero instructions)
+ NXT_BREAK;
+ return (ERR_INSTR);
+}
+
+
+//OP_SETOUT gets it's own interpreter function because it is relatively complex
+// (called from cCmdInterpOther())
+//This also serves as a convenient breakpoint stop for investigating output module behavior
+NXT_STATUS cCmdExecuteSetOut(CODE_WORD * const pCode)
+{
+ TYPE_CODE TypeCodeField, TypeCodeSrc, TypeCodePortArg;
+ void *pField = NULL,
+ *pSrc = NULL,
+ *pPort = NULL;
+ DS_ELEMENT_ID PortArg;
+ UWORD PortCount, InstrSize;
+ ULONG Port, FieldTableIndex, i, j;
+ DV_INDEX DVIndex;
+
+ //Arg1 = InstrSize
+ //Arg2 = port number or list of ports
+ //Arg3 and beyond = FieldID, src DSID tuples
+
+ //Calculate number of tuples
+ //!!! Might want to throw ERR_INSTR if instrSize and tuples don't check out
+ InstrSize = (pCode[1] / 2);
+
+ //Second argument may specify a single port or an array list.
+ //Figure out which and resolve accordingly.
+ PortArg = pCode[2];
+ TypeCodePortArg = cCmdDSType(PortArg);
+
+ if (TypeCodePortArg == TC_ARRAY)
+ {
+ DVIndex = cCmdGetDVIndex(PortArg, 0);
+ PortCount = cCmdArrayCount(PortArg, 0);
+ }
+ else
+ PortCount = 1;
+
+ //For each port, process all the tuples
+ for (i = 0; i < PortCount; i++)
+ {
+ if (TypeCodePortArg == TC_ARRAY)
+ {
+ pPort = (UBYTE*)cCmdResolveDataArg(INC_ID(PortArg), ARRAY_ELEM_OFFSET(DVIndex, i), NULL);
+ Port = cCmdGetVal(pPort, cCmdDSType(INC_ID(PortArg)));
+ }
+ else
+ {
+ pPort = (UBYTE*)cCmdResolveDataArg(PortArg, 0, NULL);
+ Port = cCmdGetVal(pPort, TypeCodePortArg);
+ }
+
+ //If user specified a valid port, process the tuples. Else, this port is a no-op
+ if (Port < NO_OF_OUTPUTS)
+ {
+ for (j = 3; j < InstrSize; j += 2)
+ {
+ FieldTableIndex = (Port * IO_OUT_FPP) + pCode[j];
+ pSrc = cCmdResolveDataArg(pCode[j + 1], 0, &TypeCodeSrc);
+
+ //If FieldTableIndex is valid, go ahead and set the value
+ if (FieldTableIndex < IO_OUT_FIELD_COUNT)
+ {
+ pField = IO_PTRS[MOD_OUTPUT][FieldTableIndex];
+ TypeCodeField = IO_TYPES[MOD_OUTPUT][FieldTableIndex];
+ cCmdSetVal(pField, TypeCodeField, cCmdGetVal(pSrc, TypeCodeSrc));
+ }
+ //Else, compiler is nutso! Return fatal error.
+ else
+ return (ERR_INSTR);
+ }
+ }
+ }
+
+ return (NO_ERR);
+}
+
+
+NXT_STATUS cCmdInterpOther(CODE_WORD * const pCode)
+{
+ NXT_STATUS Status = NO_ERR;
+ UBYTE opCode;
+ DATA_ARG Arg1, Arg2, Arg3, Arg4, Arg5;
+ TYPE_CODE TypeCode1, TypeCode2, TypeCode3, TypeCode4, TypeCode5;
+ ULONG ArgVal1, ArgVal2, ArgVal3, ArgVal4, ArgVal5;
+ UWORD ArrayCount1, ArrayCount2, ArrayCount3, ArrayCount4;
+ UWORD MinCount;
+ UWORD i,j;
+ DV_INDEX DVIndex1, DVIndex2, DVIndex4,TmpDVIndex;
+ UWORD SrcCount;
+ DS_ELEMENT_ID TmpDSID;
+ UWORD DstIndex;
+ UWORD Size;
+ UWORD Offset;
+
+ void *pArg1 = NULL;
+ void *pArg2 = NULL;
+ void *pArg3 = NULL;
+ void *pArg4 = NULL;
+ void *pArg5 = NULL;
+
+ NXT_ASSERT(pCode != NULL);
+
+ opCode = OP_CODE(pCode);
+
+ switch (opCode)
+ {
+
+ case OP_REPLACE:
+ {
+ //Arg1 - Dst
+ //Arg2 - Src
+ //Arg3 - Index
+ //Arg4 - New val / array of vals
+
+ Arg1 = pCode[1];
+ Arg2 = pCode[2];
+ Arg3 = pCode[3];
+ Arg4 = pCode[4];
+
+ NXT_ASSERT(cCmdDSType(Arg1) == TC_ARRAY);
+ NXT_ASSERT(cCmdDSType(Arg2) == TC_ARRAY);
+
+ //Copy Src to Dst
+ //!!! Could avoid full data copy if we knew which portion to overwrite
+ if (Arg1 != Arg2)
+ {
+ Status = cCmdInterpPolyUnop2(OP_MOV, Arg1, 0, Arg2, 0);
+ if (IS_ERR(Status))
+ return Status;
+ }
+
+ DVIndex1 = cCmdGetDVIndex(Arg1, 0);
+ //Copy new val to Dst
+ if (Arg3 != NOT_A_DS_ID)
+ {
+ pArg3 = cCmdResolveDataArg(Arg3, 0, &TypeCode3);
+ ArgVal3 = cCmdGetVal(pArg3, TypeCode3);
+ }
+ else
+ {
+ //Index input unwired
+ ArgVal3 = 0;
+ }
+
+ ArrayCount1 = cCmdArrayCount(Arg1, 0);
+ //Bounds check
+ //If array index (ArgVal3) is out of range, just pass out the copy of Src (effectively no-op)
+ if (ArgVal3 >= ArrayCount1)
+ return (NO_ERR);
+
+ if (cCmdDSType(Arg4) != TC_ARRAY)
+ {
+ Status = cCmdInterpPolyUnop2(OP_MOV, INC_ID(Arg1), ARRAY_ELEM_OFFSET(DVIndex1, ArgVal3), Arg4, 0);
+ if (IS_ERR(Status))
+ return Status;
+ }
+ else
+ {
+ DVIndex4 = cCmdGetDVIndex(Arg4, 0);
+
+ ArrayCount4 = cCmdArrayCount(Arg4, 0);
+ if (ArrayCount1 - ArgVal3 < ArrayCount4)
+ MinCount = (UWORD)(ArrayCount1 - ArgVal3);
+ else
+ MinCount = ArrayCount4;
+
+ for (i = 0; i < MinCount; i++)
+ {
+ Status = cCmdInterpPolyUnop2(OP_MOV, INC_ID(Arg1), ARRAY_ELEM_OFFSET(DVIndex1, ArgVal3 + i), INC_ID(Arg4), ARRAY_ELEM_OFFSET(DVIndex4, i));
+ if (IS_ERR(Status))
+ return Status;
+ }
+ }
+ }
+ break;
+
+ case OP_ARRSUBSET:
+ {
+ //Arg1 - Dst
+ //Arg2 - Src
+ //Arg3 - Index
+ //Arg4 - Length
+
+ Arg1 = pCode[1];
+ Arg2 = pCode[2];
+ Arg3 = pCode[3];
+ Arg4 = pCode[4];
+
+ NXT_ASSERT(cCmdDSType(Arg1) == TC_ARRAY);
+ NXT_ASSERT(cCmdDSType(Arg2) == TC_ARRAY);
+
+ ArrayCount2 = cCmdArrayCount(Arg2, 0);
+
+ if (Arg3 != NOT_A_DS_ID)
+ {
+ pArg3 = cCmdResolveDataArg(Arg3, 0, &TypeCode3);
+ ArgVal3 = cCmdGetVal(pArg3, TypeCode3);
+ }
+ else //Index input unwired
+ {
+ ArgVal3 = 0;
+ }
+
+ if (Arg4 != NOT_A_DS_ID)
+ {
+ pArg4 = cCmdResolveDataArg(Arg4, 0, &TypeCode4);
+ ArgVal4 = cCmdGetVal(pArg4, TypeCode4);
+ }
+ else //Length input unwired, set to "rest"
+ {
+ ArgVal4 = (UWORD)(ArrayCount2 - ArgVal3);
+ }
+
+ //Bounds check
+ if (ArgVal3 > ArrayCount2)
+ {
+ //Illegal range - return empty subset
+ Status = cCmdDSArrayAlloc(Arg1, 0, 0);
+ return Status;
+ }
+
+ //Set MinCount to "rest"
+ MinCount = (UWORD)(ArrayCount2 - ArgVal3);
+
+ // Copy "Length" if it is less than "rest"
+ if (ArgVal4 < (ULONG)MinCount)
+ MinCount = (UWORD)ArgVal4;
+
+ //Allocate Dst array
+ Status = cCmdDSArrayAlloc(Arg1, 0, MinCount);
+ if (IS_ERR(Status))
+ return Status;
+
+ DVIndex1 = cCmdGetDVIndex(Arg1, 0);
+ DVIndex2 = cCmdGetDVIndex(Arg2, 0);
+
+ //Move src subset to dst
+ for (i = 0; i < MinCount; i++)
+ {
+ Status = cCmdInterpPolyUnop2(OP_MOV, INC_ID(Arg1), ARRAY_ELEM_OFFSET(DVIndex1, i), INC_ID(Arg2), ARRAY_ELEM_OFFSET(DVIndex2, ArgVal3 + i));
+ if (IS_ERR(Status))
+ return Status;
+ }
+ }
+ break;
+
+ case OP_STRSUBSET:
+ {
+ //Arg1 - Dst
+ //Arg2 - Src
+ //Arg3 - Index
+ //Arg4 - Length
+
+ Arg1 = pCode[1];
+ Arg2 = pCode[2];
+ Arg3 = pCode[3];
+ Arg4 = pCode[4];
+
+ NXT_ASSERT(cCmdDSType(Arg1) == TC_ARRAY);
+ NXT_ASSERT(cCmdDSType(INC_ID(Arg1)) == TC_UBYTE);
+ NXT_ASSERT(cCmdDSType(Arg2) == TC_ARRAY);
+ NXT_ASSERT(cCmdDSType(INC_ID(Arg2)) == TC_UBYTE);
+
+ ArrayCount2 = cCmdArrayCount(Arg2, 0);
+
+ //Remove NULL from Count
+ ArrayCount2--;
+
+ if (Arg3 != NOT_A_DS_ID)
+ {
+ pArg3 = cCmdResolveDataArg(Arg3, 0, &TypeCode3);
+ ArgVal3 = cCmdGetVal(pArg3, TypeCode3);
+ }
+ else //Index input unwired
+ {
+ ArgVal3 = 0;
+ }
+
+ if (Arg4 != NOT_A_DS_ID)
+ {
+ pArg4 = cCmdResolveDataArg(Arg4, 0, &TypeCode4);
+ ArgVal4 = cCmdGetVal(pArg4, TypeCode4);
+ }
+ else //Length input unwired, set to "rest"
+ {
+ ArgVal4 = (UWORD)(ArrayCount2 - ArgVal3);
+ }
+
+ //Bounds check
+ if (ArgVal3 > ArrayCount2)
+ {
+ //Illegal range - return empty string
+ Status = cCmdDSArrayAlloc(Arg1, 0, 1);
+ if (!IS_ERR(Status))
+ {
+ pArg1 = cCmdResolveDataArg(Arg1, 0, NULL);
+ *((UBYTE *)pArg1) = '\0';
+ }
+ return Status;
+ }
+
+ //Set MinCount to "rest"
+ MinCount = (UWORD)(ArrayCount2 - ArgVal3);
+
+ // Copy "Length" if it is less than "rest"
+ if (ArgVal4 < (ArrayCount2 - ArgVal3))
+ MinCount = (UWORD)ArgVal4;
+
+ //Allocate Dst array
+ Status = cCmdDSArrayAlloc(Arg1, 0, (UWORD)(MinCount + 1));
+ if (IS_ERR(Status))
+ return Status;
+
+ pArg1 = cCmdResolveDataArg(Arg1, 0, NULL);
+ pArg2 = cCmdResolveDataArg(Arg2, 0, NULL);
+
+ //Move src subset to dst
+ memmove((UBYTE *)pArg1, (UBYTE *)pArg2 + ArgVal3, MinCount);
+
+ //Append NULL terminator to Dst
+ *((UBYTE *)pArg1 + MinCount) = '\0';
+
+ }
+ break;
+
+ case OP_SETOUT:
+ {
+ Status = cCmdExecuteSetOut(pCode);
+ }
+ break;
+
+ case OP_ARRBUILD:
+ {
+ // Arg1 - Instruction Size in bytes
+ // Arg2 - Dst
+ // Arg3-N - Srcs
+
+ Arg2 = pCode[2];
+
+ NXT_ASSERT(cCmdDSType(Arg2) == TC_ARRAY);
+
+ //Number of Srcs = total code words - 3 (account for opcode word, size, and Dst)
+ //!!! Argument access like this is potentially unsafe.
+ //A function/macro which checks proper encoding would be better
+ SrcCount = (pCode[1] / 2) - 3;
+
+ //Calculate Dst array count
+ ArrayCount2 = 0;
+ for (i = 0; i < SrcCount; i++)
+ {
+ TmpDSID = pCode[3 + i];
+ NXT_ASSERT(cCmdIsDSElementIDSane(TmpDSID));
+
+ //If the type descriptors are the same, then the input is an array, not a single element
+ if (cCmdCompareDSType(Arg2, TmpDSID))
+ {
+ NXT_ASSERT(cCmdDSType(TmpDSID) == TC_ARRAY);
+ ArrayCount2 += cCmdArrayCount(TmpDSID, 0);
+ }
+ else
+ {
+ //Assert that the output is an array of this input type
+ NXT_ASSERT(cCmdCompareDSType(INC_ID(Arg2), TmpDSID));
+ ArrayCount2++;
+ }
+ }
+
+ //Allocate Dst array
+ Status = cCmdDSArrayAlloc(Arg2, 0, ArrayCount2);
+ if (IS_ERR(Status))
+ return Status;
+
+ DVIndex2 = cCmdGetDVIndex(Arg2, 0);
+
+ //Move Src(s) to Dst
+ DstIndex = 0;
+ for (i = 0; i < SrcCount; i++)
+ {
+ TmpDSID = pCode[3 + i];
+
+ //If the type descriptors are the same, then the input is an array, not a single element
+ if (cCmdCompareDSType(Arg2, TmpDSID))
+ {
+ NXT_ASSERT(cCmdDSType(TmpDSID) == TC_ARRAY);
+ TmpDVIndex = cCmdGetDVIndex(TmpDSID, 0);
+ for (j = 0; j < DV_ARRAY[TmpDVIndex].Count; j++)
+ {
+ Status = cCmdInterpPolyUnop2(OP_MOV, INC_ID(Arg2), ARRAY_ELEM_OFFSET(DVIndex2, DstIndex), INC_ID(TmpDSID), ARRAY_ELEM_OFFSET(TmpDVIndex, j));
+ if (IS_ERR(Status))
+ return Status;
+ DstIndex++;
+ }
+ }
+ else
+ {
+ //Assert that the output is an array of this input type
+ NXT_ASSERT(cCmdCompareDSType(INC_ID(Arg2), TmpDSID));
+ Status = cCmdInterpPolyUnop2(OP_MOV, INC_ID(Arg2), ARRAY_ELEM_OFFSET(DVIndex2, DstIndex), TmpDSID, 0);
+ if (IS_ERR(Status))
+ return Status;
+ DstIndex++;
+ }
+ }
+
+ NXT_ASSERT(DstIndex == ArrayCount2);
+ }
+ break;
+
+ case OP_STRCAT:
+ {
+ // Arg1 - Instruction Size in bytes
+ // Arg2 - Dst
+ // Arg3-N - Srcs
+
+ Arg2 = pCode[2];
+
+ //Make sure Dst arg is a string
+ NXT_ASSERT(cCmdDSType(Arg2) == TC_ARRAY);
+ NXT_ASSERT(cCmdDSType(INC_ID(Arg2)) == TC_UBYTE);
+
+ //Number of Srcs = total code words - 3 (account for opcode word, size, and Dst)
+ //!!! Argument access like this is potentially unsafe.
+ //A function/macro which checks proper encoding would be better
+ SrcCount = (pCode[1] / 2) - 3;
+
+ //Calculate Dst array count
+ ArrayCount2 = 0;
+ for (i = 0; i < SrcCount; i++)
+ {
+ TmpDSID = pCode[3 + i];
+ NXT_ASSERT(cCmdIsDSElementIDSane(TmpDSID));
+
+ //Make sure Src arg is a string
+ //!!! Type checks here should be richer to allow array of strings as input (match LabVIEW behavior)
+ NXT_ASSERT(cCmdDSType(TmpDSID) == TC_ARRAY);
+
+ if (cCmdDSType(INC_ID(TmpDSID)) != TC_UBYTE)
+ {
+ NXT_BREAK;
+ return ERR_ARG;
+ }
+
+ ArrayCount3 = cCmdArrayCount(TmpDSID, 0);
+ NXT_ASSERT(ArrayCount3 > 0);
+ //Subtract NULL terminator from Src array count
+ ArrayCount3--;
+
+ //Increase Dst array count by Src array count
+ ArrayCount2 += ArrayCount3;
+ }
+
+ //Add room for NULL terminator
+ ArrayCount2++;
+
+ //Allocate Dst array
+ Status = cCmdDSArrayAlloc(Arg2, 0, ArrayCount2);
+ if (IS_ERR(Status))
+ return Status;
+
+ //Move Src(s) to Dst
+ DstIndex = 0;
+ pArg2 = cCmdResolveDataArg(Arg2, 0, NULL);
+ for (i = 0; i < SrcCount; i++)
+ {
+ TmpDSID = pCode[3 + i];
+
+ pArg3 = cCmdResolveDataArg(TmpDSID, 0, NULL);
+
+ ArrayCount3 = cCmdArrayCount(TmpDSID, 0);
+ NXT_ASSERT(ArrayCount3 > 0);
+ //Subtract NULL terminator from Src array count
+ ArrayCount3--;
+
+ memmove((UBYTE *)pArg2 + DstIndex, pArg3, ArrayCount3);
+ DstIndex += ArrayCount3;
+ }
+
+ //Append NULL terminator to Dst
+ *((UBYTE *)pArg2 + DstIndex) = '\0';
+ DstIndex++;
+
+ NXT_ASSERT(DstIndex == ArrayCount2);
+ }
+ break;
+
+ case OP_UNFLATTEN:
+ {
+ //Arg1 - Dst
+ //Arg2 - Err (output)
+ //Arg3 - Src (byte stream)
+ //Arg4 - Type
+
+ //The Type arg is a preallocated structure of the exact size you
+ //want to unflatten into. This allows us to support unflattening arbitrary types.
+
+ //!!! Currently, both outputs must have valid destinations.
+ // It would be trivial to handle NOT_A_DS_ID to avoid dummy
+ // allocations when outputs are unused.
+
+ Arg1 = pCode[1];
+ Arg2 = pCode[2];
+ Arg3 = pCode[3];
+ Arg4 = pCode[4];
+
+ //Move Type template to Dst
+ //This provides a default value for Dst and makes sure Dst is properly sized
+ Status = cCmdInterpPolyUnop2(OP_MOV, Arg1, 0, Arg4, 0);
+ if (IS_ERR(Status))
+ return Status;
+
+ //Resolve error data pointer
+ pArg2 = cCmdResolveDataArg(Arg2, 0, &TypeCode2);
+
+ //Make sure Arg3 is a String
+ NXT_ASSERT(cCmdDSType(Arg3) == TC_ARRAY);
+ NXT_ASSERT(cCmdDSType(INC_ID(Arg3)) == TC_UBYTE);
+
+ ArrayCount3 = cCmdArrayCount(Arg3, 0);
+ //Take NULL terminator out of count
+ ArrayCount3--;
+
+ Size = cCmdCalcFlattenedSize(Arg4, 0);
+
+ //Check that we have a proper type template to unflatten into
+ if (ArrayCount3 == Size)
+ {
+ pArg3 = cCmdResolveDataArg(Arg3, 0, NULL);
+ Offset = 0;
+ Status = cCmdUnflattenFromByteArray(pArg3, &Offset, Arg1, 0);
+
+ //!!! Status ignored from cCmdUnflattenFromByteArray
+ // If future revisions of this function provide better error checking,
+ // Err arg should be conditionally set based on the result.
+ //Unflatten succeeded; set Err arg to FALSE
+ cCmdSetVal(pArg2, TypeCode2, FALSE);
+
+ NXT_ASSERT(Offset == Size);
+ }
+ else
+ {
+ //Unflatten failed; set Err arg to TRUE
+ cCmdSetVal(pArg2, TypeCode2, TRUE);
+ }
+ }
+ break;
+
+ case OP_STRINGTONUM:
+ {
+
+ // Arg1 - Dst number (output)
+ // Arg2 - Offset past match (output)
+ // Arg3 - Src string
+ // Arg4 - Offset
+ // Arg5 - Default (type/value)
+
+ //!!! Currently, both outputs must have valid destinations.
+ // It would be trivial to handle NOT_A_DS_ID to avoid dummy
+ // allocations when outputs are unused.
+
+ Arg1 = pCode[1];
+ Arg2 = pCode[2];
+ Arg3 = pCode[3];
+ Arg4 = pCode[4];
+ Arg5 = pCode[5];
+
+ pArg1 = cCmdResolveDataArg(Arg1, 0, &TypeCode1);
+ pArg2 = cCmdResolveDataArg(Arg2, 0, &TypeCode2);
+ pArg3 = cCmdResolveDataArg(Arg3, 0, &TypeCode3);
+
+ if (Arg4 != NOT_A_DS_ID)
+ {
+ pArg4 = cCmdResolveDataArg(Arg4, 0, &TypeCode4);
+ ArgVal4 = cCmdGetVal(pArg4, TypeCode4);
+ }
+ else //Offset input unwired
+ {
+ ArgVal4 = 0;
+ }
+
+ if (Arg5 != NOT_A_DS_ID)
+ {
+ pArg5 = cCmdResolveDataArg(Arg5, 0, &TypeCode5);
+ ArgVal5 = cCmdGetVal(pArg5, TypeCode5);
+ }
+ else //Default input unwired
+ {
+ ArgVal5 = 0;
+ }
+
+ //Read number from string
+ if (sscanf(((PSZ)pArg3 + ArgVal4), "%d", &ArgVal1) == 1)
+ {
+ i = (UWORD)ArgVal4;
+ //Scan until we see the number
+ while ((((UBYTE *)pArg3)[i] < '0') || (((UBYTE *)pArg3)[i] > '9'))
+ i++;
+
+ //Scan until we get past the number
+ while ((((UBYTE *)pArg3)[i] >= '0') && (((UBYTE *)pArg3)[i] <= '9'))
+ i++;
+
+ ArgVal2 = i;
+ }
+ else
+ {
+ //Number wasn't found in string, use defaults
+ ArgVal1 = ArgVal5;
+ ArgVal2 = 0;
+ }
+
+ //Set outputs
+ cCmdSetVal(pArg1, TypeCode1, ArgVal1);
+ cCmdSetVal(pArg2, TypeCode2, ArgVal2);
+ }
+ break;
+
+ default:
+ {
+ //Fatal error: Unrecognized instruction
+ NXT_BREAK;
+ Status = ERR_INSTR;
+ }
+ break;
+ }
+
+ return (Status);
+}
+
+
+//
+//Support functions for lowspeed (I2C devices, i.e. ultrasonic sensor) communications
+//
+
+//Simple lookup table for pMapLowSpeed->ChannelState[Port] values
+//This is used to keep VM status code handling consistent
+//...and ChannelState gives us too much information, anyway...
+static const NXT_STATUS MapLStoVMStat[6] =
+{
+ NO_ERR, //LOWSPEED_IDLE,
+ STAT_COMM_PENDING, //LOWSPEED_INIT,
+ STAT_COMM_PENDING, //LOWSPEED_LOAD_BUFFER,
+ STAT_COMM_PENDING, //LOWSPEED_COMMUNICATING,
+ ERR_COMM_BUS_ERR, //LOWSPEED_ERROR,
+ STAT_COMM_PENDING, //LOWSPEED_DONE (really means c_lowspeed state machine is resetting)
+};
+
+
+//cCmdLSCheckStatus
+//Check lowspeed port status, optionally returning bytes available in the buffer for reading
+NXT_STATUS cCmdLSCheckStatus(UBYTE Port)
+{
+ if (Port >= NO_OF_LOWSPEED_COM_CHANNEL)
+ {
+ return (ERR_COMM_CHAN_INVALID);
+ }
+
+ //If port is not configured properly ahead of time, report that error
+ //!!! This seems like the right policy, but may restrict otherwise valid read operations...
+ if (!(pMapInput->Inputs[Port].SensorType == LOWSPEED_9V || pMapInput->Inputs[Port].SensorType == LOWSPEED)
+ || !(pMapInput->Inputs[Port].InvalidData == FALSE))
+ {
+ return (ERR_COMM_CHAN_NOT_READY);
+ }
+
+ return (MapLStoVMStat[pMapLowSpeed->ChannelState[Port]]);
+}
+
+//cCmdLSCalcBytesReady
+//Calculate true number of bytes available in the inbound LS buffer
+UBYTE cCmdLSCalcBytesReady(UBYTE Port)
+{
+ SLONG Tmp;
+
+ //Expect callers to validate Port, but short circuit here to be safe.
+ if (Port >= NO_OF_LOWSPEED_COM_CHANNEL)
+ return 0;
+
+ //Normally, bytes available is a simple difference.
+ Tmp = pMapLowSpeed->InBuf[Port].InPtr - pMapLowSpeed->InBuf[Port].OutPtr;
+
+ //If InPtr is actually behind OutPtr, circular buffer has wrapped. Account for wrappage...
+ if (Tmp < 0)
+ Tmp = (pMapLowSpeed->InBuf[Port].InPtr + (SIZE_OF_LSBUF - pMapLowSpeed->InBuf[Port].OutPtr));
+
+ return (UBYTE)(Tmp);
+}
+
+//cCmdLSWrite
+//Write BufLength bytes into specified port's lowspeed buffer and kick off comm process to device
+NXT_STATUS cCmdLSWrite(UBYTE Port, UBYTE BufLength, UBYTE *pBuf, UBYTE ResponseLength)
+{
+ if (Port >= NO_OF_LOWSPEED_COM_CHANNEL)
+ {
+ return (ERR_COMM_CHAN_INVALID);
+ }
+
+ if (BufLength > SIZE_OF_LSBUF || ResponseLength > SIZE_OF_LSBUF)
+ {
+ return (ERR_INVALID_SIZE);
+ }
+
+ //Only start writing process if port is properly configured and c_lowspeed module is ready
+ if ((pMapInput->Inputs[Port].SensorType == LOWSPEED_9V || pMapInput->Inputs[Port].SensorType == LOWSPEED)
+ && (pMapInput->Inputs[Port].InvalidData == FALSE)
+ && (pMapLowSpeed->ChannelState[Port] == LOWSPEED_IDLE) || (pMapLowSpeed->ChannelState[Port] == LOWSPEED_ERROR))
+ {
+ pMapLowSpeed->OutBuf[Port].InPtr = 0;
+ pMapLowSpeed->OutBuf[Port].OutPtr = 0;
+
+ memcpy(pMapLowSpeed->OutBuf[Port].Buf, pBuf, BufLength);
+ pMapLowSpeed->OutBuf[Port].InPtr = (UBYTE)BufLength;
+
+ pMapLowSpeed->InBuf[Port].BytesToRx = ResponseLength;
+
+ pMapLowSpeed->ChannelState[Port] = LOWSPEED_INIT;
+ pMapLowSpeed->State |= (COM_CHANNEL_ONE_ACTIVE << Port);
+
+ return (NO_ERR);
+ }
+ else
+ {
+ //!!! Would be more consistent to return STAT_COMM_PENDING if c_lowspeed is busy
+ return (ERR_COMM_CHAN_NOT_READY);
+ }
+}
+
+
+//cCmdLSRead
+//Read BufLength bytes from specified port's lowspeed buffer
+NXT_STATUS cCmdLSRead(UBYTE Port, UBYTE BufLength, UBYTE * pBuf)
+{
+ UBYTE BytesReady, BytesToRead;
+
+ if (Port >= NO_OF_LOWSPEED_COM_CHANNEL)
+ {
+ return (ERR_COMM_CHAN_INVALID);
+ }
+
+ if (BufLength > SIZE_OF_LSBUF)
+ {
+ return (ERR_INVALID_SIZE);
+ }
+
+ BytesReady = cCmdLSCalcBytesReady(Port);
+
+ if (BufLength > BytesReady)
+ {
+ return (ERR_COMM_CHAN_NOT_READY);
+ }
+
+ BytesToRead = BufLength;
+
+ //If the bytes we want to read wrap around the end, we must first read the end, then reset back to the beginning
+ if (pMapLowSpeed->InBuf[Port].OutPtr + BytesToRead >= SIZE_OF_LSBUF)
+ {
+ BytesToRead = SIZE_OF_LSBUF - pMapLowSpeed->InBuf[Port].OutPtr;
+ memcpy(pBuf, pMapLowSpeed->InBuf[Port].Buf + pMapLowSpeed->InBuf[Port].OutPtr, BytesToRead);
+ pMapLowSpeed->InBuf[Port].OutPtr = 0;
+ pBuf += BytesToRead;
+ BytesToRead = BufLength - BytesToRead;
+ }
+
+ memcpy(pBuf, pMapLowSpeed->InBuf[Port].Buf + pMapLowSpeed->InBuf[Port].OutPtr, BytesToRead);
+ pMapLowSpeed->InBuf[Port].OutPtr += BytesToRead;
+
+ return (NO_ERR);
+}
+
+
+//
+//Wrappers for OP_SYSCALL
+//
+
+//
+//cCmdWrapFileOpenRead
+//ArgV[0]: (Function return) Loader status, U16 return
+//ArgV[1]: File Handle, U8 return
+//ArgV[2]: Filename, CStr
+//ArgV[3]: Length, U32 return
+NXT_STATUS cCmdWrapFileOpenRead(UBYTE * ArgV[])
+{
+ LOADER_STATUS LStatus;
+ DV_INDEX DVIndex;
+
+ //Resolve array argument
+ DVIndex = *(DV_INDEX *)(ArgV[2]);
+ ArgV[2] = cCmdDVPtr(DVIndex);
+
+ LStatus = pMapLoader->pFunc(OPENREAD, ArgV[2], NULL, (ULONG *)ArgV[3]);
+
+ //Add entry into FileHandleTable
+ if (LOADER_ERR(LStatus) == SUCCESS)
+ {
+ VarsCmd.FileHandleTable[LOADER_HANDLE(LStatus)][0] = 'r';
+ strcpy((PSZ)(VarsCmd.FileHandleTable[LOADER_HANDLE(LStatus)] + 1), (PSZ)(ArgV[2]));
+ }
+
+ //Status code in high byte of LStatus
+ *((UWORD *)ArgV[0]) = LOADER_ERR(LStatus);
+ //File handle in low byte of LStatus
+ *(ArgV[1]) = LOADER_HANDLE(LStatus);
+
+ return NO_ERR;
+}
+
+//cCmdWrapFileOpenWrite
+//ArgV[0]: (Function return) Loader status, U16 return
+//ArgV[1]: File Handle, U8 return
+//ArgV[2]: Filename, CStr
+//ArgV[3]: Length, U32 return
+NXT_STATUS cCmdWrapFileOpenWrite(UBYTE * ArgV[])
+{
+ LOADER_STATUS LStatus;
+ DV_INDEX DVIndex;
+
+ //Resolve array argument
+ DVIndex = *(DV_INDEX *)(ArgV[2]);
+ ArgV[2] = cCmdDVPtr(DVIndex);
+
+ LStatus = pMapLoader->pFunc(OPENWRITEDATA, ArgV[2], NULL, (ULONG *)ArgV[3]);
+
+ //Add entry into FileHandleTable
+ if (LOADER_ERR(LStatus) == SUCCESS)
+ {
+ VarsCmd.FileHandleTable[LOADER_HANDLE(LStatus)][0] = 'w';
+ strcpy((PSZ)(VarsCmd.FileHandleTable[LOADER_HANDLE(LStatus)] + 1), (PSZ)(ArgV[2]));
+ }
+
+ //Status code in high byte of LStatus
+ *((UWORD *)ArgV[0]) = LOADER_ERR(LStatus);
+ //File handle in low byte of LStatus
+ *(ArgV[1]) = LOADER_HANDLE(LStatus);
+
+ return NO_ERR;
+}
+
+//cCmdWrapFileOpenAppend
+//ArgV[0]: (Function return) Loader status, U16 return
+//ArgV[1]: File Handle, U8 return
+//ArgV[2]: Filename, CStr
+//ArgV[3]: Length Remaining, U32 return
+NXT_STATUS cCmdWrapFileOpenAppend(UBYTE * ArgV[])
+{
+ LOADER_STATUS LStatus;
+ DV_INDEX DVIndex;
+
+ //Resolve array argument
+ DVIndex = *(DV_INDEX *)(ArgV[2]);
+ ArgV[2] = cCmdDVPtr(DVIndex);
+
+ LStatus = pMapLoader->pFunc(OPENAPPENDDATA, ArgV[2], NULL, (ULONG *)ArgV[3]);
+
+ //Add entry into FileHandleTable
+ if (LOADER_ERR(LStatus) == SUCCESS)
+ {
+ VarsCmd.FileHandleTable[LOADER_HANDLE(LStatus)][0] = 'w';
+ strcpy((PSZ)(VarsCmd.FileHandleTable[LOADER_HANDLE(LStatus)] + 1), (PSZ)(ArgV[2]));
+ }
+
+ //Status code in high byte of LStatus
+ *((UWORD *)ArgV[0]) = LOADER_ERR(LStatus);
+ //File handle in low byte of LStatus
+ *(ArgV[1]) = LOADER_HANDLE(LStatus);
+
+ return NO_ERR;
+}
+
+//cCmdWrapFileRead
+//ArgV[0]: (Function return) Loader status, U16 return
+//ArgV[1]: File Handle, U8 in/out
+//ArgV[2]: Buffer, CStr out
+//ArgV[3]: Length, U32 in/out
+NXT_STATUS cCmdWrapFileRead(UBYTE * ArgV[])
+{
+ NXT_STATUS Status = NO_ERR;
+ LOADER_STATUS LStatus;
+ DV_INDEX DVIndex;
+
+ //Resolve array argument
+ DVIndex = *(DV_INDEX *)(ArgV[2]);
+ //Size Buffer to Length
+ //Add room for null terminator to length
+ Status = cCmdDVArrayAlloc(DVIndex, (UWORD)(*(ULONG *)ArgV[3] + 1));
+ if (IS_ERR(Status))
+ return Status;
+
+ ArgV[2] = cCmdDVPtr(DVIndex);
+ LStatus = pMapLoader->pFunc(READ, ArgV[1], ArgV[2], (ULONG *)ArgV[3]);
+
+ //Tack on NULL terminator
+ //Note that loader code may have adjusted length (*ArgV[3]) if all requested data was not available
+ //!!! Better solution would be to resize buffer to new length + 1,
+ // but then you must also be wary of side effects if resize allocation fails!
+ *(ArgV[2] + *(ULONG *)ArgV[3]) = '\0';
+
+ //Status code in high byte of LStatus
+ *((UWORD *)ArgV[0]) = LOADER_ERR(LStatus);
+ //File handle in low byte of LStatus
+ *(ArgV[1]) = LOADER_HANDLE(LStatus);
+
+ return Status;
+}
+
+//cCmdWrapFileWrite
+//ArgV[0]: (Function return) Loader status, U16 return
+//ArgV[1]: File Handle, U8 in/out
+//ArgV[2]: Buffer, CStr
+//ArgV[3]: Length, U32 return
+NXT_STATUS cCmdWrapFileWrite(UBYTE * ArgV[])
+{
+ LOADER_STATUS LStatus;
+ DV_INDEX DVIndex;
+
+ //Resolve array argument
+ DVIndex = *(DV_INDEX *)(ArgV[2]);
+ ArgV[2] = cCmdDVPtr(DVIndex);
+
+ LStatus = pMapLoader->pFunc(WRITE, ArgV[1], ArgV[2], (ULONG *)ArgV[3]);
+
+ //Status code in high byte of LStatus
+ *((UWORD *)ArgV[0]) = LOADER_ERR(LStatus);
+ //File handle in low byte of LStatus
+ *(ArgV[1]) = LOADER_HANDLE(LStatus);
+
+ return NO_ERR;
+}
+
+//cCmdWrapFileClose
+//ArgV[0]: (Function return) Loader status, U16 return
+//ArgV[1]: File Handle, U8
+NXT_STATUS cCmdWrapFileClose(UBYTE * ArgV[])
+{
+ LOADER_STATUS LStatus;
+
+ //!!! This bounds check also exists in dLoaderCloseHandle(), but we provide an explicit error code
+ if (*(ArgV[1]) >= MAX_HANDLES)
+ {
+ *((UWORD *)ArgV[0]) = ILLEGALHANDLE;
+ return NO_ERR;
+ }
+
+ LStatus = pMapLoader->pFunc(CLOSE, ArgV[1], NULL, NULL);
+
+ //Clear entry in FileHandleTable
+ memset(VarsCmd.FileHandleTable[*(ArgV[1])], 0, FILENAME_LENGTH + 2);
+
+ //Status code in high byte of LStatus
+ *((UWORD *)ArgV[0]) = LOADER_ERR(LStatus);
+
+ return NO_ERR;
+}
+
+//cCmdWrapFileResolveHandle
+//ArgV[0]: (Function return) Loader status, U16 return
+//ArgV[1]: File Handle, U8 return
+//ArgV[2]: Write Handle?, Bool return
+//ArgV[3]: Filename, CStr
+NXT_STATUS cCmdWrapFileResolveHandle (UBYTE * ArgV[])
+{
+ UBYTE i;
+ DV_INDEX DVIndex;
+
+ //Resolve array argument
+ DVIndex = *(DV_INDEX *)(ArgV[3]);
+ ArgV[3] = cCmdDVPtr(DVIndex);
+
+ for (i = 0; i < MAX_HANDLES; i++)
+ {
+ if (strcmp((PSZ)(ArgV[3]), (PSZ)(VarsCmd.FileHandleTable[i] + 1)) == 0)
+ {
+ *(ArgV[2]) = (VarsCmd.FileHandleTable[i][0] == 'w');
+ break;
+ }
+ }
+
+ if (i == MAX_HANDLES)
+ {
+ i = NOT_A_HANDLE;
+ *((UWORD *)ArgV[0]) = HANDLEALREADYCLOSED;
+ }
+ else
+ {
+ *((UWORD *)ArgV[0]) = SUCCESS;
+ }
+
+ *(ArgV[1]) = i;
+
+ return NO_ERR;
+}
+
+
+//cCmdWrapFileRename
+//ArgV[0]: (Function return) Loader status, U16 return
+//ArgV[1]: Old Filename, CStr
+//ArgV[2]: New Filename, CStr
+NXT_STATUS cCmdWrapFileRename (UBYTE * ArgV[])
+{
+ LOADER_STATUS LStatus;
+ ULONG Tmp;
+ DV_INDEX DVIndex;
+
+ //Resolve array arguments
+ DVIndex = *(DV_INDEX *)(ArgV[1]);
+ ArgV[1] = cCmdDVPtr(DVIndex);
+ DVIndex = *(DV_INDEX *)(ArgV[2]);
+ ArgV[2] = cCmdDVPtr(DVIndex);
+
+ //!!! Tmp placeholder passed into loader code to avoid illegal dereferencing.
+ LStatus = pMapLoader->pFunc(RENAMEFILE, ArgV[1], ArgV[2], &Tmp);
+
+ //Status code in high byte of LStatus
+ *((UWORD *)ArgV[0]) = LOADER_ERR(LStatus);
+
+ return NO_ERR;
+}
+
+
+//cCmdWrapFileDelete
+//ArgV[0]: (Function return) Loader status, U16 return
+//ArgV[1]: Filename, CStr
+NXT_STATUS cCmdWrapFileDelete (UBYTE * ArgV[])
+{
+ LOADER_STATUS LStatus;
+ DV_INDEX DVIndex;
+
+ //Resolve array arguments
+ DVIndex = *(DV_INDEX *)(ArgV[1]);
+ ArgV[1] = cCmdDVPtr(DVIndex);
+
+ LStatus = pMapLoader->pFunc(DELETE, ArgV[1], NULL, NULL);
+
+ //Status code in high byte of LStatus
+ *((UWORD *)ArgV[0]) = LOADER_ERR(LStatus);
+
+ return NO_ERR;
+}
+
+//
+//cCmdWrapSoundPlayFile
+//ArgV[0]: (Return value) Status code, SBYTE
+//ArgV[1]: Filename, CStr
+//ArgV[2]: Loop?, UBYTE (bool)
+//ArgV[3]: Volume, UBYTE
+//
+NXT_STATUS cCmdWrapSoundPlayFile(UBYTE * ArgV[])
+{
+ DV_INDEX DVIndex;
+
+ //Resolve array arguments
+ DVIndex = *(DV_INDEX *)(ArgV[1]);
+ ArgV[1] = cCmdDVPtr(DVIndex);
+
+ //!!! Should check filename and/or existence and return error before proceeding
+ strncpy((PSZ)(pMapSound->SoundFilename), (PSZ)(ArgV[1]), FILENAME_LENGTH);
+
+ if (*(ArgV[2]) == TRUE)
+ pMapSound->Mode = SOUND_LOOP;
+ else
+ pMapSound->Mode = SOUND_ONCE;
+
+ pMapSound->Volume = *(ArgV[3]);
+ //SampleRate of '0' means "let file specify SampleRate"
+ pMapSound->SampleRate = 0;
+ pMapSound->Flags |= SOUND_UPDATE;
+
+ *((SBYTE*)(ArgV[0])) = (NO_ERR);
+
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapSoundPlayTone
+//ArgV[0]: (Return value) Status code, SBYTE
+//ArgV[1]: Frequency, UWORD
+//ArgV[2]: Duration, UWORD
+//ArgV[3]: Loop?, UBYTE (Boolean)
+//ArgV[4]: Volume, UBYTE
+//
+NXT_STATUS cCmdWrapSoundPlayTone(UBYTE * ArgV[])
+{
+ pMapSound->Freq = *(UWORD*)(ArgV[1]);
+ pMapSound->Duration = *(UWORD*)(ArgV[2]);
+ pMapSound->Volume = *(ArgV[4]);
+ pMapSound->Flags |= SOUND_UPDATE;
+
+ if (*(ArgV[3]) == TRUE)
+ pMapSound->Mode = SOUND_TONE | SOUND_LOOP;
+ else
+ pMapSound->Mode = SOUND_TONE;
+
+ *((SBYTE*)(ArgV[0])) = (NO_ERR);
+
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapSoundGetState
+//ArgV[0]: (Return value) sound module state, UBYTE
+//ArgV[1]: Flags, UBYTE
+//
+NXT_STATUS cCmdWrapSoundGetState(UBYTE * ArgV[])
+{
+ *(ArgV[0]) = pMapSound->State;
+ *(ArgV[1]) = pMapSound->Flags;
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapSoundSetState
+//ArgV[0]: (Return value) sound module state, UBYTE
+//ArgV[1]: State, UBYTE
+//ArgV[2]: Flags, UBYTE
+//
+NXT_STATUS cCmdWrapSoundSetState(UBYTE * ArgV[])
+{
+ pMapSound->State = *(ArgV[1]);
+ //Return same state we just set, mostly for interface consistency
+ *(ArgV[0]) = pMapSound->State;
+
+ //OR in provided flags (usually 0)
+ pMapSound->Flags |= *(ArgV[2]);
+
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapReadButton
+//ArgV[0]: (Function return) Status code, SBYTE
+//ArgV[1]: Index (U8)
+//ArgV[2]: Pressed (bool)
+//ArgV[3]: Count (U8) (count of press-then-release cycles)
+//ArgV[4]: ResetCount? (bool in)
+//
+NXT_STATUS cCmdWrapReadButton(UBYTE * ArgV[])
+{
+ UBYTE btnIndex;
+
+ btnIndex = *((UBYTE*)(ArgV[1]));
+
+ if (btnIndex < NO_OF_BTNS)
+ {
+ //Set pressed boolean output
+ if (pMapButton->State[btnIndex] & PRESSED_STATE)
+ *(ArgV[2]) = TRUE;
+ else
+ *(ArgV[2]) = FALSE;
+
+ //Set count output
+ *(ArgV[3]) = (UBYTE)(pMapButton->BtnCnt[btnIndex].RelCnt);
+
+ //Optionally reset internal count
+ if (*(ArgV[4]) != 0)
+ {
+ pMapButton->BtnCnt[btnIndex].RelCnt = 0;
+ //Need to clear short and long counts too, because RelCnt depends on them. No known side effects.
+ pMapButton->BtnCnt[btnIndex].ShortRelCnt = 0;
+ pMapButton->BtnCnt[btnIndex].LongRelCnt = 0;
+ }
+
+ // Set status code 'OK'
+ *((SBYTE*)(ArgV[0])) = NO_ERR;
+ }
+ else
+ {
+ //Bad button index specified, return error and default outputs
+ *((SBYTE*)(ArgV[0])) = ERR_INVALID_PORT;
+ *(ArgV[2]) = FALSE;
+ *(ArgV[3]) = 0;
+ }
+
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapCommLSWrite
+//ArgV[0]: (return) Status code, SBYTE
+//ArgV[1]: Port specifier, UBYTE
+//ArgV[2]: Buffer to send, UBYTE array, only SIZE_OF_LSBUF bytes will be used
+//ArgV[3]: ResponseLength, UBYTE, specifies expected bytes back from slave device
+//
+NXT_STATUS cCmdWrapCommLSWrite(UBYTE * ArgV[])
+{
+ SBYTE * pReturnVal = (SBYTE*)(ArgV[0]);
+ UBYTE Port = *(ArgV[1]);
+ UBYTE * pBuf;
+ UWORD BufLength;
+ UBYTE ResponseLength = *(ArgV[3]);
+ DV_INDEX DVIndex;
+
+ //Resolve array arguments
+ DVIndex = *(DV_INDEX *)(ArgV[2]);
+ pBuf = cCmdDVPtr(DVIndex);
+ BufLength = DV_ARRAY[DVIndex].Count;
+
+ *pReturnVal = cCmdLSWrite(Port, (UBYTE)BufLength, pBuf, ResponseLength);
+
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapCommLSCheckStatus
+//ArgV[0]: (return) Status code, SBYTE
+//ArgV[1]: Port specifier, UBYTE
+//ArgV[2]: BytesReady, UBYTE
+//
+NXT_STATUS cCmdWrapCommLSCheckStatus(UBYTE * ArgV[])
+{
+ UBYTE Port = *(ArgV[1]);
+
+ *((SBYTE*)(ArgV[0])) = cCmdLSCheckStatus(Port);
+ *((UBYTE*)(ArgV[2])) = cCmdLSCalcBytesReady(Port);
+
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapCommLSRead
+//ArgV[0]: (return) Status code, SBYTE
+//ArgV[1]: Port specifier, UBYTE
+//ArgV[2]: Buffer for data, UBYTE array, max SIZE_OF_LSBUF bytes will be written
+//ArgV[3]: BufferLength, UBYTE, specifies size of buffer requested
+//
+NXT_STATUS cCmdWrapCommLSRead(UBYTE * ArgV[])
+{
+ SBYTE * pReturnVal = (SBYTE*)(ArgV[0]);
+ UBYTE Port = *(ArgV[1]);
+ UBYTE * pBuf;
+ UBYTE BufLength = *(ArgV[3]);
+ UBYTE BytesToRead;
+ DV_INDEX DVIndex = *(DV_INDEX *)(ArgV[2]);
+ NXT_STATUS AllocStatus;
+
+ *pReturnVal = cCmdLSCheckStatus(Port);
+ BytesToRead = cCmdLSCalcBytesReady(Port);
+
+ //If channel is OK and has data ready for us, put the data into outgoing buffer
+ if (!IS_ERR(*pReturnVal) && BytesToRead > 0)
+ {
+ //Limit buffer to available data
+ if (BufLength > BytesToRead)
+ BufLength = BytesToRead;
+
+ AllocStatus = cCmdDVArrayAlloc(DVIndex, BufLength);
+ if (IS_ERR(AllocStatus))
+ return (AllocStatus);
+
+ pBuf = cCmdDVPtr(DVIndex);
+ *pReturnVal = cCmdLSRead(Port, BufLength, pBuf);
+ }
+ //Else, the channel has an error and/or there's no data to read; clear the output array
+ else
+ {
+ AllocStatus = cCmdDVArrayAlloc(DVIndex, 0);
+ if (IS_ERR(AllocStatus))
+ return (AllocStatus);
+ }
+
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapRandomNumber
+//ArgV[0]: (return) Random number, SWORD
+//
+NXT_STATUS cCmdWrapRandomNumber(UBYTE * ArgV[])
+{
+ static UBYTE count = 0;
+ SWORD random;
+
+ if (count == 0)
+ srand(dTimerRead());
+
+ if (count > 20)
+ count = 0;
+ else
+ count++;
+
+ //!!! IAR's implementation of the rand() library function returns signed values, and we want it that way.
+ //Some stdlib implementations may return only positive numbers, so be wary if this code is ported.
+ random = rand();
+
+ *((SWORD *)ArgV[0]) = random;
+
+ return NO_ERR;
+}
+
+//
+//cCmdWrapGetStartTick
+//ArgV[0]: (return) Start Tick, ULONG
+//
+NXT_STATUS cCmdWrapGetStartTick(UBYTE * ArgV[])
+{
+ *((ULONG *)ArgV[0]) = VarsCmd.StartTick;
+ return NO_ERR;
+}
+
+//
+//cCmdWrapMessageWrite
+//ArgV[0]: (return) Error Code, SBYTE (NXT_STATUS)
+//ArgV[1]: QueueID, UBYTE
+//ArgV[2]: Message, CStr
+//
+NXT_STATUS cCmdWrapMessageWrite(UBYTE * ArgV[])
+{
+ NXT_STATUS Status = NO_ERR;
+ DV_INDEX DVIndex;
+
+ //Resolve array arguments
+ DVIndex = *(DV_INDEX *)(ArgV[2]);
+ ArgV[2] = cCmdDVPtr(DVIndex);
+
+ Status = cCmdMessageWrite(*(UBYTE *)(ArgV[1]), ArgV[2], DV_ARRAY[DVIndex].Count);
+
+ *(SBYTE *)(ArgV[0]) = Status;
+
+ if (IS_FATAL(Status))
+ return Status;
+ else
+ return (NO_ERR);
+}
+
+#define UNPACK_STATUS(StatusWord) ((SBYTE)(StatusWord))
+
+NXT_STATUS cCmdBTCheckStatus(UBYTE Connection)
+{
+ //If specified connection is invalid, return error code to the user.
+ if (Connection >= SIZE_OF_BT_CONNECT_TABLE)
+ {
+ return (ERR_INVALID_PORT);
+ }
+
+ //INPROGRESS means a request is currently pending completion by the comm module
+ if (VarsCmd.CommStat == INPROGRESS)
+ {
+ return (STAT_COMM_PENDING);
+ }
+ //Translate BTBUSY to ERR_COMM_CHAN_NOT_READY
+ //And check if specified connection is indeed configured
+ else if (VarsCmd.CommStat == (SWORD)BTBUSY
+ || (pMapComm->BtConnectTable[Connection].Name[0]) == '\0')
+ {
+ return (ERR_COMM_CHAN_NOT_READY);
+ }
+ else
+ {
+ return (UNPACK_STATUS(VarsCmd.CommStat));
+ }
+}
+
+//Default packet to send for a remote MESSAGE_READ command.
+//3rd byte must be replaced with remote mailbox (QueueID)
+//4th byte must be replaced with local mailbox
+static UBYTE RemoteMsgReadPacket[5] = {0x00, 0x13, 0xFF, 0xFF, 0x01};
+
+//
+//cCmdWrapMessageRead
+//ArgV[0]: (return) Error Code, SBYTE (NXT_STATUS)
+//ArgV[1]: QueueID, UBYTE
+//ArgV[2]: Remove, UBYTE
+//ArgV[3]: (return) Message, CStr
+//
+NXT_STATUS cCmdWrapMessageRead(UBYTE * ArgV[])
+{
+ NXT_STATUS Status = NO_ERR;
+ NXT_STATUS AllocStatus = NO_ERR;
+ UBYTE QueueID = *(UBYTE *)(ArgV[1]);
+ DV_INDEX DestDVIndex = *(DV_INDEX *)(ArgV[3]);
+ UWORD MessageSize;
+ UBYTE i;
+
+ NXT_ASSERT(IS_DV_INDEX_SANE(DestDVIndex));
+
+ //Check Next Message's size
+ Status = cCmdMessageGetSize(QueueID, &MessageSize);
+
+ //If there is a valid message in local mailbox, read it
+ if (!IS_ERR(Status) && MessageSize > 0 )
+ {
+ //!!! Also check for EMPTY_MAILBOX status?
+ //Size destination string
+ AllocStatus = cCmdDVArrayAlloc(DestDVIndex, MessageSize);
+ if (IS_ERR(AllocStatus))
+ return AllocStatus;
+
+ //Get Message
+ //!!! Should more aggressively enforce null termination before blindly copying to dataspace
+ Status = cCmdMessageRead(QueueID, cCmdDVPtr(DestDVIndex), MessageSize, *(ArgV[2]));
+ }
+ else
+ {
+ //Clear destination string
+ AllocStatus = cCmdDVArrayAlloc(DestDVIndex, 1);
+ if (IS_ERR(AllocStatus))
+ return AllocStatus;
+
+ //Successful allocation, make sure first byte is null terminator
+ *(UBYTE*)(cCmdDVPtr(DestDVIndex)) = '\0';
+ }
+
+ //If there were no local messages, see if there are any waiting in our slaves' outboxes
+ if (Status == STAT_MSG_EMPTY_MAILBOX && QueueID < INCOMING_QUEUE_COUNT)
+ {
+ //If there's an old error code hanging around, clear it before proceeding.
+ //!!! Clearing error here means bytecode status checking loops could get false SUCCESS results?
+ if (VarsCmd.CommStat < 0)
+ VarsCmd.CommStat = SUCCESS;
+
+ //Search through possible slaves, looking for valid connection
+ for (i = 0; i < SIZE_OF_BT_CONNECT_TABLE - 1; i++)
+ {
+ //Advance CommCurrConnection and limit to 1, 2, or 3 (only slave connection slots are checked)
+ VarsCmd.CommCurrConnection++;
+ if (VarsCmd.CommCurrConnection == SIZE_OF_BT_CONNECT_TABLE)
+ VarsCmd.CommCurrConnection = 1;
+
+ if (cCmdBTCheckStatus(VarsCmd.CommCurrConnection) == NO_ERR)
+ break;
+ }
+
+ //If there is at least one configured slave connection, make a remote read request
+ if (i < SIZE_OF_BT_CONNECT_TABLE - 1)
+ {
+ //Outgoing QueueID on slave device is the local QueueID + INCOMING_QUEUE_COUNT
+ RemoteMsgReadPacket[2] = QueueID + INCOMING_QUEUE_COUNT;
+ RemoteMsgReadPacket[3] = QueueID;
+
+ //Request comm module to send assembled packet and not go idle until response comes back (or error)
+ pMapComm->pFunc(SENDDATA, sizeof(RemoteMsgReadPacket), VarsCmd.CommCurrConnection, TRUE, RemoteMsgReadPacket, (UWORD*)&(VarsCmd.CommStat));
+
+ //Read status back after SENDDATA call so bytecode gets STAT_COMM_PENDING or error
+ Status = cCmdBTCheckStatus(VarsCmd.CommCurrConnection);
+
+ //If our request was accepted, set the DirtyComm flag so stream will get cleaned up later
+ if (Status == STAT_COMM_PENDING)
+ VarsCmd.DirtyComm = TRUE;
+ }
+ }
+
+ *(SBYTE *)(ArgV[0]) = Status;
+ if (IS_FATAL(Status))
+ return Status;
+ else
+ return (NO_ERR);
+}
+
+
+//
+//cCmdWrapCommBTCheckStatus
+//ArgV[0]: (return) Status byte, SBYTE
+//ArgV[1]: Connection index, 0-3
+//
+NXT_STATUS cCmdWrapCommBTCheckStatus(UBYTE * ArgV[])
+{
+ *((SBYTE*)(ArgV[0])) = cCmdBTCheckStatus(*(ArgV[1]));
+
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapCommBTWrite
+//ArgV[0]: (return) Status byte, SBYTE
+//ArgV[1]: Connection index, 0-3
+//ArgV[2]: Buffer
+//
+NXT_STATUS cCmdWrapCommBTWrite(UBYTE * ArgV[])
+{
+ SBYTE * pReturnVal = (SBYTE*)(ArgV[0]);
+ UBYTE Connection = *(ArgV[1]);
+ UBYTE * pBuf;
+ UWORD BufLength;
+ DV_INDEX DVIndex;
+
+ //Resolve array arguments
+ DVIndex = *(DV_INDEX *)(ArgV[2]);
+ pBuf = cCmdDVPtr(DVIndex);
+
+ BufLength = DV_ARRAY[DVIndex].Count;
+
+ //If there's an old error code hanging around, clear it before proceeding.
+ if (VarsCmd.CommStat < 0)
+ VarsCmd.CommStat = SUCCESS;
+
+ //!!! Only first 256 bytes could possibly make it through! Should return error on longer input?
+ //!!! Not requesting a wait-for-response because only known use doesn't read responses.
+ pMapComm->pFunc(SENDDATA, (UBYTE)BufLength, Connection, FALSE, pBuf, (UWORD*)&(VarsCmd.CommStat));
+
+ //!!! Reasonable to wrap below code in cCmdCommBTCheckStatus?
+ //INPROGRESS means our request was accepted by His Funkiness of pFunc
+ if (VarsCmd.CommStat == (SWORD)INPROGRESS)
+ {
+ *pReturnVal = STAT_COMM_PENDING;
+
+ //Set DirtyComm flag so stream is reset after program ends
+ VarsCmd.DirtyComm = TRUE;
+ }
+ //Translate BTBUSY to ERR_COMM_CHAN_NOT_READY
+ else if (VarsCmd.CommStat == (SWORD)BTBUSY)
+ {
+ *pReturnVal = ERR_COMM_CHAN_NOT_READY;
+ }
+ else
+ {
+ *pReturnVal = UNPACK_STATUS(VarsCmd.CommStat);
+ }
+
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapCommBTRead
+//ArgV[0]: (return) Status byte, SBYTE
+//ArgV[1]: Count to read
+//ArgV[2]: Buffer
+//
+NXT_STATUS cCmdWrapCommBTRead(UBYTE * ArgV[])
+{
+ //SBYTE * pReturnVal = (SBYTE*)(ArgV[0]);
+ //UBYTE * pBuf = (ArgV[2]);
+ //!!! should provide length and/or connection to read?
+
+ //!!! This syscall is not implemented; return fatal error.
+ return (ERR_INSTR);
+}
+
+//
+//cCmdWrapKeepAlive
+//ArgV[0]: (return) Current timer limit in ms, ULONG
+//
+NXT_STATUS cCmdWrapKeepAlive(UBYTE * ArgV[])
+{
+ pMapUi->Flags |= UI_RESET_SLEEP_TIMER;
+
+ //Convert UI's minute-based timeout value to millisecs
+ //Milliseconds are the "natural" time unit in user-land.
+ *(ULONG*)(ArgV[0]) = (pMapUi->SleepTimeout * 60 * 1000);
+
+ return (NO_ERR);
+}
+
+#define MAX_IOM_BUFFER_SIZE 64
+//
+//cCmdWrapIOMapRead
+//ArgV[0]: (return) Status byte, SBYTE
+//ArgV[1]: Module name, CStr
+//ArgV[2]: Offset, UWORD
+//ArgV[3]: Count, UWORD
+//ArgV[4]: Buffer, UBYTE array
+//
+NXT_STATUS cCmdWrapIOMapRead(UBYTE * ArgV[])
+{
+ UWORD LStatus;
+ NXT_STATUS Status;
+
+ SBYTE * pReturnVal = (SBYTE*)(ArgV[0]);
+ UWORD Offset = *(UWORD*)(ArgV[2]);
+ //Our copy of 'Count' must be a ULONG to match the loader interface
+ ULONG Count = *(UWORD*)(ArgV[3]);
+
+ DV_INDEX DVIndex;
+
+ //Buffer for return of FINDFIRSTMODULE call, structure defined in protocol doc
+ //We need it to transfer the ModuleID to the IOMAPREAD call
+ UBYTE FindBuffer[FILENAME_LENGTH + 10];
+ //Buffer to store data and offset in for IOMAPREAD call
+ //!!! Constant size means only limited reads and writes
+ UBYTE DataBuffer[MAX_IOM_BUFFER_SIZE + 2];
+
+ if (Count > MAX_IOM_BUFFER_SIZE)
+ {
+ //Request to read too much data at once; clear buffer, return error.
+ DVIndex = *(DV_INDEX *)(ArgV[4]);
+ *pReturnVal = cCmdDVArrayAlloc(DVIndex, 0);
+ if (IS_ERR(*pReturnVal))
+ return (*pReturnVal);
+
+ *pReturnVal = ERR_INVALID_SIZE;
+ return (NO_ERR);
+ }
+
+ //Resolve module name
+ DVIndex = *(DV_INDEX *)(ArgV[1]);
+ ArgV[1] = cCmdDVPtr(DVIndex);
+
+ //Find module by name. Note that wildcards are accepted, but only first match matters.
+ LStatus = pMapLoader->pFunc(FINDFIRSTMODULE, ArgV[1], FindBuffer, NULL);
+
+ if (LOADER_ERR(LStatus) == SUCCESS)
+ {
+ //Module was found, transfer Offset into first two bytes of DataBuffer and attempt to read
+ *(UWORD*)(DataBuffer) = Offset;
+ LStatus = pMapLoader->pFunc(IOMAPREAD, &(FindBuffer[FILENAME_LENGTH + 1]), DataBuffer, &Count);
+
+ if (LOADER_ERR(LStatus) == SUCCESS)
+ {
+ //No error from IOMAPREAD, so copy the data into VM's dataspace
+ //Size destination array
+ DVIndex = *(DV_INDEX *)(ArgV[4]);
+ Status = cCmdDVArrayAlloc(DVIndex, (UWORD)Count);
+ if (IS_ERR(Status))
+ {
+ //Alloc failed, so close handle and return
+ pMapLoader->pFunc(CLOSEMODHANDLE, NULL, NULL, NULL);
+ return (Status);
+ }
+
+ //Alloc succeeded, so resolve and copy away
+ ArgV[4] = cCmdDVPtr(DVIndex);
+ memcpy(ArgV[4], &(DataBuffer[2]), Count);
+ }
+ }
+
+ *pReturnVal = LOADER_ERR_BYTE(LStatus);
+
+ pMapLoader->pFunc(CLOSEMODHANDLE, NULL, NULL, NULL);
+ return (NO_ERR);
+}
+
+//
+//cCmdWrapIOMapWrite
+//ArgV[0]: (return) Status byte, SBYTE
+//ArgV[1]: Module name, CStr
+//ArgV[2]: Offset, UWORD
+//ArgV[3]: Buffer, UBYTE array
+//
+NXT_STATUS cCmdWrapIOMapWrite(UBYTE * ArgV[])
+{
+ UWORD LStatus;
+
+ SBYTE * pReturnVal = (SBYTE*)(ArgV[0]);
+ UWORD Offset = *(UWORD*)(ArgV[2]);
+
+ //Our copy of 'Count' must be a ULONG to match the loader interface
+ ULONG Count;
+ DV_INDEX DVIndex;
+
+ //Buffer for return of FINDFIRSTMODULE call, structure defined in protocol doc
+ //We need it to transfer the ModuleID to the IOMAPREAD call
+ UBYTE FindBuffer[FILENAME_LENGTH + 10];
+ //Buffer to store data and offset in for IOMAPREAD call
+ //!!! Constant size means only limited reads and writes
+ UBYTE DataBuffer[MAX_IOM_BUFFER_SIZE + 2];
+
+ //Resolve module name and buffer
+ DVIndex = *(DV_INDEX *)(ArgV[1]);
+ ArgV[1] = cCmdDVPtr(DVIndex);
+
+ DVIndex = *(DV_INDEX *)(ArgV[3]);
+ ArgV[3] = cCmdDVPtr(DVIndex);
+ Count = DV_ARRAY[DVIndex].Count;
+
+ if (Count > MAX_IOM_BUFFER_SIZE)
+ {
+ //Request to read too much data at once; return error and give up
+ *pReturnVal = ERR_INVALID_SIZE;
+ return (NO_ERR);
+ }
+
+ LStatus = pMapLoader->pFunc(FINDFIRSTMODULE, ArgV[1], FindBuffer, NULL);
+
+ if (LOADER_ERR(LStatus) == SUCCESS)
+ {
+ //Module was found, transfer Offset into first two bytes of DataBuffer, copy data into rest of buffer, then write
+ *(UWORD*)(DataBuffer) = Offset;
+ memcpy(&(DataBuffer[2]), ArgV[3], Count);
+ LStatus = pMapLoader->pFunc(IOMAPWRITE, &(FindBuffer[FILENAME_LENGTH + 1]), DataBuffer, &Count);
+ }
+
+ *pReturnVal = LOADER_ERR_BYTE(LStatus);
+
+ pMapLoader->pFunc(CLOSEMODHANDLE, NULL, NULL, NULL);
+ return (NO_ERR);
+}
+
+#if VM_BENCHMARK
+void cCmdWriteBenchmarkFile()
+{
+ LOADER_STATUS LStatus;
+ UBYTE Handle;
+ ULONG BenchFileSize;
+ ULONG i, Length;
+ UBYTE Buffer[256];
+
+ //Remove old benchmark file, create a new one
+ strcpy((char *)Buffer, "benchmark.txt");
+ pMapLoader->pFunc(DELETE, Buffer, NULL, NULL);
+ BenchFileSize = 2048;
+ LStatus = pMapLoader->pFunc(OPENWRITEDATA, Buffer, NULL, &BenchFileSize);
+
+ if (!LOADER_ERR(LStatus))
+ {
+ //Write Benchmark file
+ Handle = LOADER_HANDLE(LStatus);
+
+ //Header
+ sprintf((char *)Buffer, "Program Name: %s\r\n", VarsCmd.ActiveProgName);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ sprintf((char *)Buffer, "InstrCount: %d\r\n", VarsCmd.InstrCount);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ sprintf((char *)Buffer, "Time: %d\r\n", IOMapCmd.Tick - VarsCmd.StartTick);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ sprintf((char *)Buffer, "Instr/Tick: %d\r\n", VarsCmd.Average);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ sprintf((char *)Buffer, "CmdCtrl Calls: %d\r\n", VarsCmd.CmdCtrlCount);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ sprintf((char *)Buffer, "OverTime Rounds: %d\r\n", VarsCmd.OverTimeCount);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ sprintf((char *)Buffer, "Max OverTime Length: %d\r\n", VarsCmd.MaxOverTimeLength);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ sprintf((char *)Buffer, "CompactionCount: %d\r\n", VarsCmd.CompactionCount);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ sprintf((char *)Buffer, "LastCompactionTick: %d\r\n", VarsCmd.LastCompactionTick);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ sprintf((char *)Buffer, "MaxCompactionTime: %d\r\n", VarsCmd.MaxCompactionTime);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+
+ //opcode benchmarks
+ sprintf((char *)Buffer, "Op\tCnt\tOver\tMax\r\n");
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+ for (i = 0; i < OPCODE_COUNT; i++)
+ {
+ sprintf((char *)Buffer, "%x\t%d\t%d\t%d\t%d\r\n", i, VarsCmd.OpcodeBenchmarks[i][0], VarsCmd.OpcodeBenchmarks[i][1], VarsCmd.OpcodeBenchmarks[i][2], VarsCmd.OpcodeBenchmarks[i][3]);
+ Length = strlen((char *)Buffer);
+ LStatus = pMapLoader->pFunc(WRITE, &Handle, Buffer, &Length);
+ }
+ //close file
+ LStatus = pMapLoader->pFunc(CLOSE, &Handle, NULL, NULL);
+ }
+}
+#endif
+
+#ifdef SIM_NXT
+// Accessors for simulator library code
+SWORD cCmdGetCodeWord(CLUMP_ID Clump, CODE_INDEX Index)
+{
+ if (Clump == NOT_A_CLUMP)
+ {
+ NXT_ASSERT(Index < VarsCmd.CodespaceCount);
+ return (VarsCmd.pCodespace[Index]);
+ }
+ else
+ {
+ NXT_ASSERT(cCmdIsClumpIDSane(Clump));
+ return (((SWORD)VarsCmd.pCodespace[VarsCmd.pAllClumps[Clump].CodeStart + Index]));
+ }
+}
+
+
+UBYTE * cCmdGetDataspace(UWORD *DataspaceSize)
+{
+ if (DataspaceSize)
+ *DataspaceSize = VarsCmd.DataspaceSize;
+ return (VarsCmd.pDataspace);
+}
+
+
+DOPE_VECTOR * cCmdGetDopeVectorPtr()
+{
+ return VarsCmd.MemMgr.pDopeVectorArray;
+}
+
+
+MEM_MGR cCmdGetMemMgr(void)
+{
+ return VarsCmd.MemMgr;
+}
+
+
+ULONG cCmdGetPoolSize()
+{
+ return VarsCmd.PoolSize;
+}
+#endif
+
+#else //!ENABLE_VM
+//
+//Implementations of standard interface if VM is disabled.
+//Place low-level test code here if VM is causing issues.
+//Test code must implement cCmdInit(), cCmdCtrl(), and cCmdExit() at a minimum.
+//Recommend using a pattern like #include "c_cmd_alternate.c"
+//
+
+//!!! !ENABLE_VM implementations really should provide a placeholder function for this pointer
+//IOMapCmd.pRCHandler = &cCmdHandleRemoteCommands;
+//#include "c_cmd_alternate.c"
+//#include "c_cmd_FB_LowSpeed_Test.c"
+//#include "c_cmd_FB_LowSpeed_JB_Compass.c"
+//#include "c_cmd_FB_LowSpeed_Continius.c"
+//#include "c_cmd_FB_LowSpeed_JB_Color.c"
+#include "c_cmd_FB_LowSpeed_NorthStar_Demo2.c"
+//#include "c_cmd_FB_LowSpeed_LEGO_TEST.c"
+
+#endif //ENABLE_VM
diff --git a/AT91SAM7S256/Source/c_cmd.h b/AT91SAM7S256/Source/c_cmd.h
new file mode 100644
index 0000000..04f10a3
--- /dev/null
+++ b/AT91SAM7S256/Source/c_cmd.h
@@ -0,0 +1,804 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 24-07-06 8:52 $
+//
+// Filename $Workfile:: c_cmd.h $
+//
+// Version $Revision:: 43 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_cmd.h $
+//
+// Platform C
+//
+
+//
+// File Description:
+// This file contains definitions and prototypes for the VM which runs bytecode
+// programs compatible with LEGO MINDSTORMS NXT Software 1.0.
+//
+
+#ifndef C_CMD
+#define C_CMD
+
+//!!! MAX_HANDLES also defined in m_sched.h
+#ifndef MAX_HANDLES
+#define MAX_HANDLES 16
+#endif
+
+#include "c_cmd_bytecodes.h"
+#define SYSCALL_COUNT 34
+
+extern const HEADER cCmd;
+
+//
+//Standard interface to other modules
+//
+void cCmdInit(void* pHeader);
+void cCmdCtrl(void);
+void cCmdExit(void);
+
+//
+//ARM_NXT vs SIM_NXT
+//These definitions are set up to allow compiling this code for use in a simulated (non-ARM7) environment.
+//If your toolchain doesn't automatically use the __ICCARM__ token, define it to ensure normal compilation.
+//
+#ifdef __ICCARM__
+#define ARM_NXT
+#else
+#define SIM_NXT
+#endif
+
+//
+//ENABLE_VM toggles compilation the main body of VM code.
+//Define it as 0 to compile alternate implementation for testing (see bottom of c_cmd.c)
+//
+#define ENABLE_VM 1
+
+//
+//VM_BENCHMARK enables extra instrumentation code to measure VM performance.
+//When enabled, a file named "benchmark.txt" is produced every time a program completes.
+//
+#define VM_BENCHMARK (ENABLE_VM && 0) //<-- Toggle to turn on benchmark calculations
+
+#if VM_BENCHMARK
+//Prototype for benchmark recording function
+void cCmdWriteBenchmarkFile();
+#endif
+
+//
+//Run-time assert macros
+//Use these to test for unexpected conditions
+//If expr evaluates as false while running under a debugger,
+// a software breakpoint exception is thrown.
+//NXT_BREAK is just a shortcut for unconditional break.
+//
+//Assert definitions behind WIN_DEBUG only make sense when compiling SIM_NXT
+// under an x86 Windows debugger.
+//
+#if defined WIN_DEBUG
+//"int 3" is a break exception on x86
+#define NXT_ASSERT(expr) if (expr) {} else { __asm {int 3} }
+#define NXT_BREAK NXT_ASSERT(0)
+//
+//Assert definitions behind ARM_DEBUG aren't quite as handy as WIN_DEBUG,
+// but they do record the code line causing the last assert failure.
+//
+#elif defined ARM_DEBUG
+#define NXT_ASSERT(expr) if (expr) {}\
+ else\
+ {\
+ VarsCmd.AssertFlag = TRUE;\
+ VarsCmd.AssertLine = __LINE__;\
+ }
+#define NXT_BREAK NXT_ASSERT(0);
+#else
+//Not debugging, so #defined as nothing
+//!!! Note that these definitions means all usages of NXT_ASSERT and NXT_BREAK
+// get stripped out of an unmodified ARM7 build.
+//Unless ARM_DEBUG is enabled, treat them as documentation of expected values.
+#define NXT_ASSERT(expr)
+#define NXT_BREAK
+#endif
+
+//
+//Status byte used to return requests for further action or errors
+//Valid codes #defined in c_cmd.iom
+//!!!JLOFTUS Replace with NXT_STATUS? Same for ASSERTS? Others? Risk factors?
+//
+typedef SBYTE NXT_STATUS;
+
+//dTimerRead() constantly returns latest system MS tick, so empty loop is convenient macro
+#define BUSY_WAIT_NEXT_MS while (IOMapCmd.Tick == dTimerRead())
+
+#if ENABLE_VM
+
+//Intial values for clump records are packed into 4 bytes in the file format.
+#define VM_FILE_CLUMP_REC_SIZE 4
+
+//
+// Definitions for dataspace management, IO Map (IOM) access, and bytecode instruction structure
+//
+
+//Type codes for use in the dataspace table-of-contents (DSTOC)
+typedef UBYTE TYPE_CODE;
+
+enum
+{
+ //VOID type for unused DS elements; never valid to address them from bytecode
+ TC_VOID,
+
+ //Simple scalar integers, equivalent to matching basic types from stdconst.h
+ TC_UBYTE,
+ TC_SBYTE,
+ TC_UWORD,
+ TC_SWORD,
+ TC_ULONG,
+ TC_SLONG,
+
+ //Aggregate types containing one or more scalar
+ TC_ARRAY,
+ TC_CLUSTER,
+
+ //Mutex tracks current holder and any waiting clumps
+ TC_MUTEX
+};
+
+//Sizes (in bytes) of each scalar type
+#define SIZE_UBYTE 1
+#define SIZE_SBYTE 1
+#define SIZE_UWORD 2
+#define SIZE_SWORD 2
+#define SIZE_ULONG 4
+#define SIZE_SLONG 4
+
+//MUTEX record is a struct containing 3 8-bit CLUMP_IDs, packed into 32-bit word
+//See MUTEX_Q typedef
+#define SIZE_MUTEX 4
+
+//Module IDs for IO map addressing
+enum
+{
+ MOD_INPUT,
+ MOD_OUTPUT
+};
+
+//Field IDs for input IOM
+enum
+{
+ IO_IN_TYPE,
+ IO_IN_MODE,
+ IO_IN_ADRAW,
+ IO_IN_NORMRAW,
+ IO_IN_SCALEDVAL,
+ IO_IN_INVALID_DATA
+};
+
+//FPP = Fields Per Port
+#define IO_IN_FPP 6
+#define IO_IN_FIELD_COUNT (IO_IN_FPP * NO_OF_INPUTS)
+
+//Field IDs for input IOM
+enum
+{
+ IO_OUT_FLAGS,
+ IO_OUT_MODE,
+ IO_OUT_SPEED, //AKA "Power"
+ IO_OUT_ACTUAL_SPEED,
+ IO_OUT_TACH_COUNT,
+ IO_OUT_TACH_LIMIT,
+ IO_OUT_RUN_STATE,
+ IO_OUT_TURN_RATIO,
+ IO_OUT_REG_MODE,
+ IO_OUT_OVERLOAD,
+ IO_OUT_REG_P_VAL,
+ IO_OUT_REG_I_VAL,
+ IO_OUT_REG_D_VAL,
+ IO_OUT_BLOCK_TACH_COUNT,
+ IO_OUT_ROTATION_COUNT
+};
+
+#define IO_OUT_FPP 15
+#define IO_OUT_FIELD_COUNT (IO_OUT_FPP * NO_OF_OUTPUTS)
+
+//
+//DS_TOC_ENTRY is a record in the dataspace table of contents
+//The TypeCode describes the data which is stored at Dataspace[DSOffset]
+//
+typedef struct
+{
+ TYPE_CODE TypeCode;
+ UBYTE Flags;
+ SWORD DSOffset;
+} DS_TOC_ENTRY;
+
+//DS_TOC_ENTRY Flags
+//!!! Yes, there's only one flag defined for an 8-bit field.
+//ARM7 alignment rules means those bits would otherwise just be padding, anyway.
+#define DS_DEFAULT_DEFAULT 1 //This entry has no default value in file; fill with zero at activation time
+
+//DS_ELEMENT_ID (AKA "DS item ID") indexes DataspaceTOC
+typedef UWORD DS_ELEMENT_ID;
+
+//Special flag value used for opcode-specific default behavior when real dataspace argument is not provided
+#define NOT_A_DS_ID 0xFFFF
+
+//Macro to bump DS_ELEMENT_IDs +1 with a cast (mostly to quash annoying warnings)
+#define INC_ID(X) ((DS_ELEMENT_ID)(X + 1))
+
+//DATA_ARG may contain a DS_ELEMENT_ID or encoded IO map address
+typedef UWORD DATA_ARG;
+
+//CODE_WORD is a single indexable element of the codespace
+typedef SWORD CODE_WORD;
+
+//CODE_INDEX indexes codespaces for opcodes and args
+//!!! UWORD CODE_INDEX currently limits programs to 128KB code
+// Yes, this is "plenty", but noted here to make sure we think about it
+// when considering code size changes
+typedef UWORD CODE_INDEX;
+
+//Typedef and define to hold and check for valid file handles
+typedef UBYTE FILE_HANDLE;
+
+#define NOT_A_HANDLE 0xFF
+
+//
+// Dynamic Memory Manager
+//
+
+typedef UWORD DV_INDEX; //Dope Vector Index: Index into the DopeVectorArray
+
+//DOPE_VECTOR struct: One instance exists in the DopeVectorArray for every array in the dataspace.
+//!!! BackPtr is an unused field. Intended to enable compaction of DopeVectorArray.
+typedef struct
+{
+ UWORD Offset;
+ UWORD ElemSize;
+ UWORD Count;
+ UWORD BackPtr;
+ DV_INDEX Link;
+} DOPE_VECTOR;
+
+//
+//MEM_MGR struct
+//Head and Tail keep track of the main linked-list of dope vectors,
+// which must be maintained in ascending order according to Offset
+//FreeHead is the head DV of the list of allocated but unused DVs
+//pDopeVectorArray is initialized at activation-time to point to the master DVA
+//
+typedef struct
+{
+ DV_INDEX Head;
+ DV_INDEX Tail;
+ DV_INDEX FreeHead;
+ DOPE_VECTOR * pDopeVectorArray;
+} MEM_MGR;
+
+//Macro to shorten common DVA access code
+#define DV_ARRAY VarsCmd.MemMgr.pDopeVectorArray
+//# of nodes to alloc when the Dope Vector Array is full
+#define DV_ARRAY_GROWTH_COUNT 5
+//Flag value for invalid Offset fields in DVs
+#define NOT_AN_OFFSET 0xFFFF
+//Check for legal index into DVA
+#define IS_DV_INDEX_SANE(X) (((X) > 0) && ((X) < DV_ARRAY[0].Count))
+
+//
+// Message Queuing
+//
+
+//
+//There are 10 incoming and 10 outgoing message queues, each 5 messages deep
+//A "message" is defined as a null-terminated string under MAX_MESSAGE_SIZE
+//
+#define MESSAGES_PER_QUEUE 5
+#define MESSAGE_QUEUE_COUNT 20
+#define INCOMING_QUEUE_COUNT ((MESSAGE_QUEUE_COUNT)/2)
+#define NOT_A_QUEUE 0xFF
+
+//
+//MAX_MESSAGE_SIZE including null-terminator
+//!!! Capped at 59 unless USB protocol assumptions are changed!
+//
+#define MAX_MESSAGE_SIZE 59
+
+//A MESSAGE is a dynamically sized string, so we use a DV_INDEX to get to its information
+typedef DV_INDEX MESSAGE;
+
+//
+//MESSAGE_QUEUE keeps track of last messages read and written (acts as a circular buffer)
+//
+typedef struct
+{
+ UWORD ReadIndex;
+ UWORD WriteIndex;
+ MESSAGE Messages[MESSAGES_PER_QUEUE];
+} MESSAGE_QUEUE;
+
+//Handy macros for accessing MESSAGE_QUEUEs
+#define GET_WRITE_MSG(QueueID) (VarsCmd.MessageQueues[(QueueID)].Messages[VarsCmd.MessageQueues[(QueueID)].WriteIndex])
+#define GET_READ_MSG(QueueID) (VarsCmd.MessageQueues[(QueueID)].Messages[VarsCmd.MessageQueues[(QueueID)].ReadIndex])
+#define SET_WRITE_MSG(QueueID, DVIndex) (VarsCmd.MessageQueues[(QueueID)].Messages[VarsCmd.MessageQueues[(QueueID)].WriteIndex] = (DVIndex))
+#define SET_READ_MSG(QueueID, DVIndex) (VarsCmd.MessageQueues[(QueueID)].Messages[VarsCmd.MessageQueues[(QueueID)].ReadIndex] = (DVIndex))
+
+
+//
+//Definitions related to dataflow scheduling
+//
+
+//CLUMP_IDs are used to index list at pAllClumps
+typedef UBYTE CLUMP_ID;
+
+//
+//The last value in CLUMP_ID's range is reserved as NOT_A_CLUMP
+//This is useful as a queue terminator and general placeholder
+//
+#define NOT_A_CLUMP 0xFF
+#define MAX_CLUMPS 255
+
+//CLUMP_Q struct for tracking head and tail of a queue of clumps
+typedef struct
+{
+ CLUMP_ID Head;
+ CLUMP_ID Tail;
+} CLUMP_Q;
+
+//
+//MUTEX_Q is a struct to be stashed in the dataspace to track state of a mutex
+//If mutex is free, Owner field is NOT_A_CLUMP and WaitQ is empty.
+//The mutex is acquired by stashing a new owner's ID.
+//If others attempt to acquire, they will be put on the WaitQ
+//
+typedef struct
+{
+ CLUMP_ID Owner;
+ CLUMP_Q WaitQ;
+} MUTEX_Q;
+
+//
+// Clump Record, run-time book-keeping for each clump
+//
+// CodeStart: Start of this clump's bytecodes
+// CodeEnd: End of this clump's bytecodes
+// PC: "program counter" -- current offset into codespace relative to CodeStart
+// InitFireCount: Initial count of upstream dependencies
+// CurrFireCount: Run-time count of unsatisfied dependencies
+// Link: ID of next clump in the queue. NOT_A_CLUMP denotes end or bad link.
+//
+// Priority: number of instructions to run per pass on this clump
+//
+// pDependents: pointer to list of downstream dependents' ClumpIDs
+// DependentCount: Count of downstream dependents
+//
+typedef struct
+{
+ CODE_INDEX CodeStart;
+ CODE_INDEX CodeEnd;
+ CODE_INDEX PC;
+ UBYTE InitFireCount;
+ UBYTE CurrFireCount; //AKA ShortCount
+ CLUMP_ID Link;
+
+ UBYTE Priority;
+
+ CLUMP_ID* pDependents;
+ UBYTE DependentCount;
+} CLUMP_REC;
+
+//
+//Definitions for memory pool management
+//
+
+//First valid pointer into the memory pool
+#define POOL_START ((UBYTE*)(VarsCmd.Pool))
+
+//Sentinel points one byte *past* the pool -- i.e. first bad pool pointer
+#define POOL_SENTINEL ((UBYTE*)(VarsCmd.Pool + VarsCmd.PoolSize))
+
+//Alignment mod for Pool and all sub-fields of the Pool
+#define POOL_ALIGN SIZE_SLONG
+
+#define ALIGN_TO_MOD(val,mod) if ((val) % (mod) != 0) { (val) += (mod) - ((val) % (mod)); } else {}
+
+//
+//Internal states of the VM
+//VM_IDLE: Just sitting around. Request to run program will lead to ONE of the VM_RUN* states.
+//VM_RUN_FREE: Attempt to run as many instructions as possible within our timeslice
+//VM_RUN_SINGLE: Run exactly one instruction per timeslice
+//VM_RUN_PAUSE: Program still "active", but someone has asked us to pause
+//VM_RESET2: Final clean up and return to IDLE
+//VM_RESET1: Initialize state variables and some I/O devices -- executed when programs end
+//
+typedef enum
+{
+ VM_IDLE,
+ VM_RUN_FREE,
+ VM_RUN_SINGLE,
+ VM_RUN_PAUSE,
+ VM_RESET1,
+ VM_RESET2,
+} VM_STATE;
+
+//
+// VARSCMD: Private state data for active program and VM system
+//
+//pCodespace: pointer for flat codespace (stored in flash, includes all clumps)
+//CodespaceCount: count of code words
+//
+//pAllClumps: Pointer to list of CLUMP_RECs
+//AllClumpsCount: Count of CLUMP_RECs in list
+//
+//RunQ: Head and tail of run queue (elements in-place in AllClumps list)
+//ScratchPC: Temp PC value for control flow instructions
+//
+//pDataspaceTOC: Pointer to DSTOC entries (stored in flash)
+//DataspaceCount: Count of entries in DSTOC
+//pDataspace: Base pointer of actual dataspace
+//DataspaceSize: Size, in bytes, of dataspace
+//DSStaticSize: Size, in bytes, of static portion of the dataspace (used as an offset to the dynamic dataspace)
+//
+//VMState: Internal state of VM's loader/scheduler (cCmdCtrl())
+//
+//MemMgr: Contains data to manage dynamic arrays
+//
+//PoolSize: Current size of main memory pool, in bytes.
+//Pool: Static pool of bytes for stashing all program run-time data
+//
+//ActiveProgHandle: Handle of the program that is currently running
+//ActiveProgName: Stashed name of currently running program, if any
+//
+//FileHandleTable: Table of file names opened by program while running.
+// First byte of each record is 'r' or 'w' (read or write).
+//
+//MessageQueues: Message buffer tracking data
+//
+//CommStat, CommStatReset, CommCurrConnection, DirtyComm: Helper data for interfacing to c_comm module
+//
+//DirtyDisplay: Boolean reminding us to re-initialize the display if program used it
+//
+//StartTick: MS tick stashed when program started. Used for relative time measurements.
+//
+//Further notes on the memory pool:
+// The main memory pool is used for all clump records, dataspace tracking data,
+// and the dataspace itself. In other words, pAllClumps and
+// pDataspace must all point to memory within the pool. Watch for NXT_ASSERTs
+// to enforce safe indexing into the pool.
+//
+typedef struct
+{
+ CODE_WORD* pCodespace;
+ CLUMP_REC* pAllClumps;
+ DS_TOC_ENTRY* pDataspaceTOC;
+ UBYTE* pDataspace;
+ UBYTE* Pool;
+
+ ULONG PoolSize;
+ UWORD CodespaceCount;
+ CLUMP_ID AllClumpsCount;
+ UWORD DataspaceCount;
+ UWORD DataspaceSize;
+ UWORD DSStaticSize;
+
+ VM_STATE VMState;
+
+ MEM_MGR MemMgr;
+
+ CLUMP_Q RunQ;
+ CODE_INDEX ScratchPC;
+ CLUMP_ID CallerClump;
+
+ UBYTE ActiveProgHandle;
+ UBYTE ActiveProgName[FILENAME_LENGTH + 1];
+
+ UBYTE FileHandleTable[MAX_HANDLES][FILENAME_LENGTH + 2];
+
+ MESSAGE_QUEUE MessageQueues[MESSAGE_QUEUE_COUNT];
+
+ SWORD CommStat;
+ SWORD CommStatReset;
+ UBYTE CommCurrConnection;
+
+ UBYTE DirtyComm;
+ UBYTE DirtyDisplay;
+
+ ULONG StartTick;
+
+#if VM_BENCHMARK
+ ULONG InstrCount;
+ ULONG Average;
+ ULONG OverTimeCount;
+ ULONG MaxOverTimeLength;
+ ULONG CmdCtrlCount;
+ ULONG CompactionCount;
+ ULONG LastCompactionTick;
+ ULONG MaxCompactionTime;
+ ULONG OpcodeBenchmarks[OPCODE_COUNT][4];
+ ULONG SyscallBenchmarks[SYSCALL_COUNT][4];
+ UBYTE Buffer[256];
+#endif
+
+#if defined ARM_DEBUG
+ UBYTE AssertFlag;
+ ULONG AssertLine;
+#endif
+} VARSCMD;
+
+//
+//Activation
+//
+
+//Activate new program by filename (open file and inflate run-time data)
+NXT_STATUS cCmdActivateProgram(UBYTE * pFileName);
+
+//Deactivate currently active program (re-init run-time data and close file)
+void cCmdDeactivateProgram();
+
+//Reset various device state variables
+void cCmdResetDevices(void);
+
+//Parse activation record file header information
+typedef struct
+{
+ UWORD DSTOC;
+ UWORD DSDefaults;
+ UWORD DSDefaultsSize;
+ UWORD DynamicDefaults;
+ UWORD DynamicDefaultsSize;
+ UWORD Clumps;
+ UWORD Codespace;
+} PROG_FILE_OFFSETS;
+
+NXT_STATUS cCmdReadFileHeader(UBYTE* pData, ULONG DataSize,
+ PROG_FILE_OFFSETS* pFileOffsets);
+
+NXT_STATUS cCmdInflateDSDefaults(UBYTE* pDSDefaults, UWORD *pDefaultsOffset, DS_ELEMENT_ID DSElementID);
+
+
+//
+//Clump management
+//
+
+//Clump queuing
+void cCmdEnQClump(CLUMP_Q * Queue, CLUMP_ID NewClump);
+void cCmdDeQClump(CLUMP_Q * Queue, CLUMP_ID Clump);
+void cCmdRotateQ(CLUMP_Q * Queue);
+UBYTE cCmdIsClumpOnQ(CLUMP_Q * Queue, CLUMP_ID Clump);
+UBYTE cCmdIsQSane(CLUMP_Q * Queue);
+
+//Mutex queuing
+NXT_STATUS cCmdAcquireMutex(MUTEX_Q * Mutex, CLUMP_ID Clump);
+NXT_STATUS cCmdReleaseMutex(MUTEX_Q * Mutex, CLUMP_ID Clump);
+
+//Conditionally schedule dependents of given clump (Begin and End specify subset of list)
+NXT_STATUS cCmdSchedDependents(CLUMP_ID Clump, SWORD Begin, SWORD End);
+
+//Conditionally schedule TargetClump
+NXT_STATUS cCmdSchedDependent(CLUMP_ID Clump, CLUMP_ID TargetClump);
+
+//Test if ClumpID is sane at run-time (valid for indexing AllClumps)
+UBYTE cCmdIsClumpIDSane(CLUMP_ID Clump);
+
+//
+//Code stream management
+//
+
+//Instruction masking macros -- get the interesting bits out of an encoded instruction word
+#define COMP_CODE(pInstr) ((UBYTE)((((pInstr)[0]) & 0x0700) >> 8))
+#define INSTR_SIZE(pInstr) ((UBYTE)((((pInstr)[0]) & 0xF000) >> 12))
+
+#ifdef USE_SHORT_OPS
+//!!! IS_SHORT_OP and SHORT_OP_CODE do not check for insane (out of bounds) data. Accessor function would be safer.
+#define IS_SHORT_OP(pInstr) ((UBYTE)((((pInstr)[0]) & 0x0800) >> 8) == 8)
+#define SHORT_OP_CODE(pInstr) COMP_CODE(pInstr)
+#define SHORT_ARG(pInstr) ((SBYTE) (((pInstr)[0]) & 0x00FF))
+//ShortOpMap defined in c_cmd_bytecodes.h
+#define OP_CODE(pInstr) (IS_SHORT_OP(pInstr) ? ShortOpMap[SHORT_OP_CODE(pInstr)] : (UBYTE) (((pInstr)[0]) & 0x00FF))
+#else
+#define OP_CODE(pInstr) ((UBYTE) (((pInstr)[0]) & 0x00FF))
+#endif
+
+//Access count of codewords belonging to Clump. If no clump specified, return count of all codewords in program.
+CODE_INDEX cCmdGetCodespaceCount(CLUMP_ID Clump);
+
+//
+//Memory pool management
+//
+
+//Initialize entire memory pool with default value
+void cCmdInitPool(void);
+
+//Resize dataspace array specified by DSElementID and Offset.
+NXT_STATUS cCmdDSArrayAlloc(DS_ELEMENT_ID DSElementID, UWORD Offset, UWORD NewCount);
+//Resize dataspace array specified by DVIndex. In most cases, call higher-level cCmdDSArrayAlloc instead.
+NXT_STATUS cCmdDVArrayAlloc(DV_INDEX DVIndex, UWORD NewCount);
+
+NXT_STATUS cCmdAllocSubArrayDopeVectors(DS_ELEMENT_ID DSElementID, UWORD Offset);
+NXT_STATUS cCmdFreeSubArrayDopeVectors(DS_ELEMENT_ID DSElementID, UWORD Offset);
+NXT_STATUS cCmdAllocDopeVector(DV_INDEX *pIndex, UWORD ElemSize, UWORD BackPtr);
+NXT_STATUS cCmdFreeDopeVector(DV_INDEX DVIndex);
+NXT_STATUS cCmdGrowDopeVectorArray(UWORD NewCount);
+NXT_STATUS cCmdCompactDopeVectorArray(void);
+
+UWORD cCmdCalcArrayElemSize(DS_ELEMENT_ID DSElementID);
+
+NXT_STATUS cCmdMemMgrMoveToTail(DV_INDEX DVIndex);
+NXT_STATUS cCmdMemMgrInsertAtTail(DV_INDEX DVIndex);
+
+//Utility function to check sanity of MemMgr data structure. Boolean result.
+UBYTE cCmdVerifyMemMgr();
+
+NXT_STATUS cCmdDSCompact(void);
+
+//
+// Message Queue management
+//
+
+NXT_STATUS cCmdMessageWrite(UWORD QueueID, UBYTE * pData, UWORD Length);
+NXT_STATUS cCmdMessageRead(UWORD QueueID, UBYTE * pData, UWORD Length, UBYTE Remove);
+NXT_STATUS cCmdMessageGetSize(UWORD QueueID, UWORD * Size);
+
+//
+//Dataspace management
+//
+
+#define IS_AGGREGATE_TYPE(TypeCode) ((TypeCode == TC_ARRAY) || (TypeCode == TC_CLUSTER))
+#define IS_SIGNED_TYPE(TypeCode) (((TypeCode) == TC_SBYTE) || ((TypeCode) == TC_SWORD) || ((TypeCode) == TC_SLONG))
+
+//Test if DS_ELEMENT_ID is sane at run-time (valid for indexing DS TOC)
+UBYTE cCmdIsDSElementIDSane(DS_ELEMENT_ID Index);
+
+DS_ELEMENT_ID cCmdGetDataspaceCount(void);
+TYPE_CODE cCmdDSType(DS_ELEMENT_ID DSElementID);
+
+//Pointer accessors to resolve actual data locations in RAM
+void* cCmdDSPtr(DS_ELEMENT_ID DSElementID, UWORD Offset);
+void* cCmdDVPtr(DV_INDEX DVIndex);
+
+//Helper to walk the DSTOC to the next entry at the same aggregate nesting level as CurrID
+DS_ELEMENT_ID cCmdNextDSElement(DS_ELEMENT_ID CurrID);
+
+//Recursively compare two complete data type descriptors
+UBYTE cCmdCompareDSType(DS_ELEMENT_ID DSElementID1, DS_ELEMENT_ID DSElementID2);
+
+//Functions for managing data flattened to byte arrays
+UWORD cCmdCalcFlattenedSize(DS_ELEMENT_ID DSElementID, UWORD Offset);
+NXT_STATUS cCmdFlattenToByteArray(UBYTE * pByteArray, UWORD * pByteOffset, DS_ELEMENT_ID DSElementID, UWORD Offset);
+NXT_STATUS cCmdUnflattenFromByteArray(UBYTE * pByteArray, UWORD * pByteOffset, DS_ELEMENT_ID DSElementID, UWORD Offset);
+
+//Comparison evaluation. Comparison codes defined in c_cmd_bytecodes.h.
+//cCmdCompare operates on scalars passed as ULONGs -- type-specific comparisons done inside function.
+UBYTE cCmdCompare(UBYTE CompCode, ULONG Val1, ULONG Val2, TYPE_CODE TypeCode1, TYPE_CODE TypeCode2);
+//cCmdCompareAggregates does polymorphic comparisons (with recursive helper function).
+NXT_STATUS cCmdCompareAggregates(UBYTE CompCode, UBYTE *ReturnBool, DATA_ARG Arg2, UWORD Offset2, DATA_ARG Arg3, UWORD Offset3);
+NXT_STATUS cCmdRecursiveCompareAggregates(UBYTE CompCode, UBYTE *ReturnBool, UBYTE *Finished, DATA_ARG Arg2, UWORD Offset2, DATA_ARG Arg3, UWORD Offset3);
+
+//Cluster functions
+UWORD cCmdClusterCount(DS_ELEMENT_ID DSElementID);
+
+//Array functions
+#define ARRAY_ELEM_OFFSET(DVIndex, Index) ((UWORD)(DV_ARRAY[(DVIndex)].Offset + DV_ARRAY[(DVIndex)].ElemSize * (Index)))
+UWORD cCmdGetDVIndex(DS_ELEMENT_ID DSElementID, UWORD Offset);
+UWORD cCmdArrayCount(DS_ELEMENT_ID DSElementID, UWORD Offset);
+TYPE_CODE cCmdArrayType(DS_ELEMENT_ID DSElementID);
+
+//!!! DATA_ARG masks are for internal use only! (Bytecode programs should never contain them)
+// See cCmdResolveDataArg() calls in the interpreter code for OP_GETOUT, OP_SETIN, and OP_GETIN.
+#define DATA_ARG_ADDR_MASK 0x3FFF
+#define DATA_ARG_IMM_MASK 0x7FFF
+
+//General data accessors (DS and IO Map)
+void * cCmdResolveDataArg(DATA_ARG DataArg, UWORD Offset, TYPE_CODE * TypeCode);
+ULONG cCmdGetVal(void * pVal, TYPE_CODE TypeCode);
+void cCmdSetVal(void * pVal, TYPE_CODE TypeCode, ULONG NewVal);
+UWORD cCmdSizeOf(TYPE_CODE TypeCode);
+
+//
+//Interpreter functions
+//
+
+//Clump-based "master" interpreter
+NXT_STATUS cCmdInterpFromClump(CLUMP_ID Clump);
+
+//Function pointer typedef for sub-interpreters
+typedef NXT_STATUS (*pInterp)(CODE_WORD * const);
+
+//Sub-interpreter dispatch functions
+NXT_STATUS cCmdInterpNoArg(CODE_WORD * const pCode);
+NXT_STATUS cCmdInterpUnop1(CODE_WORD * const pCode);
+NXT_STATUS cCmdInterpUnop2(CODE_WORD * const pCode);
+NXT_STATUS cCmdInterpBinop(CODE_WORD * const pCode);
+NXT_STATUS cCmdInterpOther(CODE_WORD * const pCode);
+
+#define INTERP_COUNT 5
+
+//Polymorphic interpreter functions
+NXT_STATUS cCmdInterpPolyUnop2(CODE_WORD const Code, DATA_ARG Arg1, UWORD Offset1, DATA_ARG Arg2, UWORD Offset2);
+ULONG cCmdUnop2(CODE_WORD const Code, ULONG Operand, TYPE_CODE TypeCode);
+
+NXT_STATUS cCmdInterpPolyBinop(CODE_WORD const Code, DATA_ARG Arg1, UWORD Offset1, DATA_ARG Arg2, UWORD Offset2, DATA_ARG Arg3, UWORD Offset3);
+ULONG cCmdBinop(CODE_WORD const Code, ULONG LeftOp, ULONG RightOp, TYPE_CODE LeftType, TYPE_CODE RightType);
+
+//
+//Support functions for lowspeed (I2C devices, i.e. ultrasonic sensor) communications
+//
+
+NXT_STATUS cCmdLSCheckStatus(UBYTE Port);
+UBYTE cCmdLSCalcBytesReady(UBYTE Port);
+NXT_STATUS cCmdLSWrite(UBYTE Port, UBYTE BufLength, UBYTE *pBuf, UBYTE ResponseLength);
+NXT_STATUS cCmdLSRead(UBYTE Port, UBYTE BufLength, UBYTE * pBuf);
+
+//
+//Support for OP_SYSCALL
+//
+
+//
+//Each cCmdWrap<SysCallName> funtion below implements one system call.
+//The OP_SYSCALL interpreter wrangles the argument vector, ArgV,
+// then calls the appropriate wrapper function according to the SysCallID.
+//Wrapper functions write directly back into the dataspace via ArgV.
+//
+#define MAX_CALL_ARGS 16
+
+typedef NXT_STATUS (*pSysCall)(UBYTE * ArgV[]);
+
+NXT_STATUS cCmdWrapFileOpenRead(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapFileOpenWrite(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapFileOpenAppend(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapFileRead(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapFileWrite(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapFileClose(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapFileResolveHandle (UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapFileRename (UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapFileDelete (UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapSoundPlayFile(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapSoundPlayTone(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapSoundGetState(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapSoundSetState(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapDrawText(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapDrawPoint(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapDrawLine(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapDrawCircle(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapDrawRect(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapDrawPicture(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapSetScreenMode(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapReadButton(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapCommLSWrite(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapCommLSRead(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapCommLSCheckStatus(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapRandomNumber(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapGetStartTick(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapMessageWrite(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapMessageRead(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapCommBTCheckStatus(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapCommBTWrite(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapCommBTRead(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapKeepAlive(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapIOMapRead(UBYTE * ArgV[]);
+NXT_STATUS cCmdWrapIOMapWrite(UBYTE * ArgV[]);
+
+//Handler for remote control protocol packets -- called from comm module via IO map function pointer
+UWORD cCmdHandleRemoteCommands(UBYTE * pInBuf, UBYTE * pOutBuf, UBYTE * pLen);
+
+#ifdef SIM_NXT
+//
+// Helper functions to provide simulator library access to VM internals
+//
+SWORD cCmdGetCodeWord(CLUMP_ID Clump, CODE_INDEX Index);
+UBYTE * cCmdGetDataspace(UWORD *DataspaceSize);
+DOPE_VECTOR * cCmdGetDopeVectorPtr(void);
+ULONG cCmdGetPoolSize(void);
+MEM_MGR cCmdGetMemMgr(void);
+#endif
+
+#else //!ENABLE_VM
+
+//Placeholder VARSCMD for alternate implementation (see bottom of c_cmd.c for usage notes)
+typedef struct
+{
+ UBYTE Tmp;
+} VARSCMD;
+
+#endif //ENABLE_VM
+
+#endif //C_CMD
diff --git a/AT91SAM7S256/Source/c_cmd.iom b/AT91SAM7S256/Source/c_cmd.iom
new file mode 100644
index 0000000..2b36743
--- /dev/null
+++ b/AT91SAM7S256/Source/c_cmd.iom
@@ -0,0 +1,178 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date: 14-06-06 8:09 $
+//
+// Filename $Workfile:: c_cmd.iom $
+//
+// Version $Revision: 21 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_cmd.iom $
+//
+// Platform C
+//
+
+#ifndef CCMD_IOM
+#define CCMD_IOM
+
+#include "modules.h"
+
+#define pMapCmd ((IOMAPCMD*)(pHeaders[ENTRY_CMD]->pIOMap))
+
+//
+// Status/error codes for the VM internal code and bytecodes, loosely categorized
+// Positive values are used for non-error status codes; commonly used by bytecode handlers
+// to affect future execution.
+// Negative values are run-time errors, and the first group is considered "fatal" in that
+// program execution cannot continue when these errors are encountered.
+//
+
+#define STAT_MSG_EMPTY_MAILBOX 64 //0x40 Specified mailbox contains no new messages
+
+#define STAT_COMM_PENDING 32 //0x20 Pending setup operation in progress
+
+#define STOP_REQ 5 //0x05 Abort current program
+#define BREAKOUT_REQ 4 //0x04 Break multi-instruction interpreter loop; give I/O a chance to run
+#define PC_OVERRIDE 3 //0x03 Move program counter according to ScratchPC value
+#define CLUMP_SUSPEND 2 //0x02 Place clump in stasis; execute others until this one returns to RunQ
+#define CLUMP_DONE 1 //0x01 Finish and reset this clump; execute others until this one is rescheduled
+
+#define NO_ERR 0
+
+//Fatal errors
+#define ERR_ARG -1 //0xFF Bad arguments
+#define ERR_INSTR -2 //0xFE Illegal bytecode instruction
+#define ERR_FILE -3 //0xFD Mal-formed file contents
+#define ERR_VER -4 //0xFC Version mismatch between firmware and compiler
+#define ERR_MEM -5 //0xFB Insufficient memory available
+#define ERR_BAD_PTR -6 //0xFA Someone passed us a bad pointer!
+
+//General errors
+#define ERR_INVALID_PORT -16 //0xF0 Bad input or output port specified
+#define ERR_INVALID_FIELD -17 //0xEF Attempted to access invalid field of a structure
+#define ERR_INVALID_QUEUE -18 //0xEE Illegal queue ID specified
+#define ERR_INVALID_SIZE -19 //0xED Illegal size specified
+#define ERR_NO_PROG -20 //0xEC No active program
+
+//Communications specific errors
+#define ERR_COMM_CHAN_NOT_READY -32 //0xE0 Specified channel/connection not configured or busy
+#define ERR_COMM_CHAN_INVALID -33 //0xDF Specified channel/connection is not valid
+#define ERR_COMM_BUFFER_FULL -34 //0xDE No room in comm buffer
+#define ERR_COMM_BUS_ERR -35 //0xDD Something went wrong on the communications bus
+
+//Remote control ("direct commands") errors
+#define ERR_RC_ILLEGAL_VAL -64 //0xC0 Data contains out-of-range values
+#define ERR_RC_BAD_PACKET -65 //0xBF Clearly insane packet
+#define ERR_RC_UNKNOWN_CMD -66 //0xBE Unknown command opcode
+#define ERR_RC_FAILED -67 //0xBD Request failed (i.e. specified file not found)
+
+//NB: Error codes -96 through -128 (0xA0 through 0x80) reserved for loader (file system) errors
+//This whole range isn't actually used by current loader code, but it's a reasonable range to reserve
+
+#define IS_ERR(Status) ((Status) < NO_ERR)
+
+//Errors are considered fatal if they are something we'd consider halting the VM for.
+#define IS_FATAL(Status) ((Status) < NO_ERR && (Status) >= ERR_BAD_PTR)
+
+//Direct command protocol opcodes
+//!!! These MUST be mutually exclusive with c_comm's protocol opcodes.
+// Since all of c_comm's protocol opcodes are above 0x80, we're safe for now.
+enum
+{
+ RC_START_PROGRAM,
+ RC_STOP_PROGRAM,
+ RC_PLAY_SOUND_FILE,
+ RC_PLAY_TONE,
+ RC_SET_OUT_STATE,
+ RC_SET_IN_MODE,
+ RC_GET_OUT_STATE,
+ RC_GET_IN_VALS,
+ RC_RESET_IN_VAL,
+ RC_MESSAGE_WRITE,
+ RC_RESET_POSITION,
+ RC_GET_BATT_LVL,
+ RC_STOP_SOUND,
+ RC_KEEP_ALIVE,
+ RC_LS_GET_STATUS,
+ RC_LS_WRITE,
+ RC_LS_READ,
+ RC_GET_CURR_PROGRAM,
+ RC_GET_BUTTON_STATE,
+ RC_MESSAGE_READ,
+ NUM_RC_OPCODES
+};
+
+
+//
+//Published status of last program to be activated
+//This value is published so outside parties (like the UI) can check if a program is running,
+//and if not, how the last program ended. Initial value is "PROG_OK".
+//PROG_OK: Last program finished normally.
+//PROG_RUNNING: Program currently running
+//PROG_ERROR: Last program ended because of an error
+//PROG_ABORT: Last program ended because of (user) abort
+//
+typedef enum
+{
+ PROG_IDLE,
+ PROG_OK,
+ PROG_RUNNING,
+ PROG_ERROR,
+ PROG_ABORT,
+ PROG_RESET
+} PROGRAM_STATUS;
+
+//Maximum size of memory pool, in bytes
+//!!! Code assumes this value is evenly divisible by 4!
+#define POOL_MAX_SIZE 32768
+
+//Versioning information
+//Format string must exist verbatim in the header of a valid program file.
+//Also included in IOMAPCMD for remote identification of the VM
+#define VM_FORMAT_STRING "MindstormsNXT"
+//Size of format string above, plus version number packed in the last two bytes.
+#define VM_FORMAT_STRING_SIZE 16
+//Current firmware version defined in c_loader.iom as FIRMWAREVERSION
+//This is the oldest compatible version in the same system
+#define VM_OLDEST_COMPATIBLE_VERSION 0x0004
+
+//
+//IO Map for Command Module
+// pRCHandler: Function pointer to handler for remote control protocol
+// Tick: Latest value from 1 ms system timer
+
+//!!! Two offset values below are useful for external debugging. They are only valid after a program has started!
+// OffsetDS: Offset to the dataspace (inside MemoryPool); relative to first byte of IOMapCmd
+// OffsetDVA: Offset to the DopeVectorArray (inside MemoryPool); relative to first byte of IOMapCmd
+
+// ProgStatus: Published status of last program to be activated
+// Awake: Boolean is only true after initialization
+
+// ActivateFlag: Set this flag to notify cCmdCtrl to activate new file
+// DeactivateFlag: Set this flag to notify cCmdCtrl to deactivate current program
+
+// FileName[]: Fill in this buffer when using ActivateFlag
+// MemoryPool[]: Main memory pool for program data.
+// (Declared as ULONG for portable alignment; used internally via a byte pointer.)
+//
+typedef struct
+{
+ UBYTE FormatString[VM_FORMAT_STRING_SIZE];
+ UWORD (*pRCHandler)(UBYTE *, UBYTE *, UBYTE *);
+ ULONG Tick;
+
+ UWORD OffsetDS;
+ UWORD OffsetDVA;
+
+ PROGRAM_STATUS ProgStatus;
+
+ UBYTE Awake;
+
+ UBYTE ActivateFlag;
+ UBYTE DeactivateFlag;
+ UBYTE FileName[FILENAME_LENGTH + 1];
+
+ ULONG MemoryPool[POOL_MAX_SIZE / 4];
+} IOMAPCMD;
+
+#endif //CCMD_IOM
diff --git a/AT91SAM7S256/Source/c_cmd_alternate.c b/AT91SAM7S256/Source/c_cmd_alternate.c
new file mode 100644
index 0000000..9366296
--- /dev/null
+++ b/AT91SAM7S256/Source/c_cmd_alternate.c
@@ -0,0 +1,163 @@
+//
+// File Description:
+// This file contains an alternate implementation of c_cmd for testing purposes.
+// It implements the minimal standard interface for the module, and serves as
+// an example of output module control via C code.
+//
+
+void cCmdInit(void* pHeader)
+{
+ pHeaders = pHeader;
+
+ IOMapCmd.Awake = TRUE;
+
+ dTimerInit();
+ IOMapCmd.Tick = dTimerRead();
+
+ return;
+}
+
+//Test: Start at speed 100 when enter is pressed; then progressively ramp down every half second until -100.
+void cCmdCtrl(void)
+{
+ static UBYTE State = 0;
+ static ULONG MyTick = 0;
+
+ if (pMapButton->State[BTN1] & PRESSED_EV)
+ {
+ pMapButton->State[BTN1] &= ~PRESSED_EV;
+
+ //Coast both motors
+ pMapOutPut->Outputs[0].Mode = MOTORON;
+ pMapOutPut->Outputs[1].Mode = MOTORON;
+
+ pMapOutPut->Outputs[0].Speed = 0;
+ pMapOutPut->Outputs[0].TachoLimit = 0;
+ pMapOutPut->Outputs[0].RunState = MOTOR_RUN_STATE_IDLE;
+ pMapOutPut->Outputs[0].RegMode = REGULATION_MODE_IDLE;
+
+ pMapOutPut->Outputs[1].Speed = 0;
+ pMapOutPut->Outputs[1].TachoLimit = 0;
+ pMapOutPut->Outputs[1].RunState = MOTOR_RUN_STATE_IDLE;
+ pMapOutPut->Outputs[1].RegMode = REGULATION_MODE_IDLE;
+
+ pMapOutPut->Outputs[0].Flags = UPDATE_MODE | UPDATE_SPEED;
+ pMapOutPut->Outputs[1].Flags = UPDATE_MODE | UPDATE_SPEED;
+
+ //Drop out of ongoing state machine
+ State = 255;
+ }
+
+ switch(State)
+ {
+ case 0:
+ {
+ //Initialize
+ pMapOutPut->Outputs[0].Flags = UPDATE_RESET_COUNT;
+ pMapOutPut->Outputs[1].Flags = UPDATE_RESET_COUNT;
+ pMapOutPut->Outputs[0].RunState = MOTOR_RUN_STATE_IDLE;
+ pMapOutPut->Outputs[1].RunState = MOTOR_RUN_STATE_IDLE;
+
+ State++;
+ }
+ break;
+
+ case 1:
+ {
+ //Kick off further states only if Enter button is pressed
+ if ((pMapButton->State[BTN4] & PRESSED_EV))
+ {
+ //Clear pressed event so UI doesn't re-use it.
+ pMapButton->State[BTN4] &= ~PRESSED_EV;
+
+ pMapOutPut->Outputs[0].Mode = MOTORON | BRAKE | REGULATED;
+ pMapOutPut->Outputs[1].Mode = MOTORON | BRAKE | REGULATED;
+
+ pMapOutPut->Outputs[0].Speed = 50;
+ pMapOutPut->Outputs[0].TachoLimit = 1152;
+ pMapOutPut->Outputs[0].RunState = MOTOR_RUN_STATE_RUNNING;
+ pMapOutPut->Outputs[0].SyncTurnParameter = 25;
+ //pMapOutPut->Outputs[0].RegMode = REGULATION_MODE_MOTOR_SPEED;
+ pMapOutPut->Outputs[0].RegMode = REGULATION_MODE_MOTOR_SYNC;
+
+ pMapOutPut->Outputs[1].Speed = 50;
+ pMapOutPut->Outputs[1].TachoLimit = 1152;
+ pMapOutPut->Outputs[1].RunState = MOTOR_RUN_STATE_RUNNING;
+ //pMapOutPut->Outputs[1].SyncTurnParameter = -7;
+ //pMapOutPut->Outputs[1].RegMode = REGULATION_MODE_MOTOR_SPEED;
+ pMapOutPut->Outputs[1].RegMode = REGULATION_MODE_MOTOR_SYNC;
+
+ pMapOutPut->Outputs[0].Flags = UPDATE_MODE | UPDATE_SPEED | UPDATE_TACHO_LIMIT;
+ pMapOutPut->Outputs[1].Flags = UPDATE_MODE | UPDATE_SPEED | UPDATE_TACHO_LIMIT;
+
+ State++;
+ }
+ }
+ break;
+
+ case 2:
+ {
+ if (pMapOutPut->Outputs[0].RunState == MOTOR_RUN_STATE_IDLE)
+ {
+ pMapOutPut->Outputs[0].Mode = MOTORON;
+ pMapOutPut->Outputs[1].Mode = MOTORON;
+
+ pMapOutPut->Outputs[0].Speed = 0;
+ pMapOutPut->Outputs[0].TachoLimit = 0;
+ pMapOutPut->Outputs[0].RunState = MOTOR_RUN_STATE_IDLE;
+ pMapOutPut->Outputs[0].RegMode = REGULATION_MODE_IDLE;
+
+ pMapOutPut->Outputs[1].Speed = 0;
+ pMapOutPut->Outputs[1].TachoLimit = 0;
+ pMapOutPut->Outputs[1].RunState = MOTOR_RUN_STATE_IDLE;
+ pMapOutPut->Outputs[1].RegMode = REGULATION_MODE_IDLE;
+
+ pMapOutPut->Outputs[0].Flags = UPDATE_MODE | UPDATE_SPEED;
+ pMapOutPut->Outputs[1].Flags = UPDATE_MODE | UPDATE_SPEED;
+ State++;
+ }
+ }
+ break;
+
+ case 3:
+ {
+ pMapOutPut->Outputs[0].Mode = MOTORON | BRAKE | REGULATED;
+ pMapOutPut->Outputs[1].Mode = MOTORON | BRAKE | REGULATED;
+
+ pMapOutPut->Outputs[0].Speed = 50;
+ pMapOutPut->Outputs[0].TachoLimit = 1152;
+ pMapOutPut->Outputs[0].RunState = MOTOR_RUN_STATE_RUNNING;
+ //pMapOutPut->Outputs[0].SyncTurnParameter = 5;
+ //pMapOutPut->Outputs[0].RegMode = REGULATION_MODE_MOTOR_SPEED;
+ pMapOutPut->Outputs[0].RegMode = REGULATION_MODE_MOTOR_SYNC;
+
+ pMapOutPut->Outputs[1].Speed = 50;
+ pMapOutPut->Outputs[1].TachoLimit = 1152;
+ pMapOutPut->Outputs[1].RunState = MOTOR_RUN_STATE_RUNNING;
+ //pMapOutPut->Outputs[1].RegMode = REGULATION_MODE_MOTOR_SPEED;
+ pMapOutPut->Outputs[1].RegMode = REGULATION_MODE_MOTOR_SYNC;
+
+ pMapOutPut->Outputs[0].Flags = UPDATE_MODE | UPDATE_SPEED | UPDATE_TACHO_LIMIT;
+ pMapOutPut->Outputs[1].Flags = UPDATE_MODE | UPDATE_SPEED | UPDATE_TACHO_LIMIT;
+
+ State = 2;
+ }
+ break;
+
+ default:
+ break;
+ };
+
+ //Busy loop to ensure return on 1ms boundary
+ BUSY_WAIT_NEXT_MS;
+
+ IOMapCmd.Tick = dTimerRead();
+ MyTick++;
+
+ return;
+}
+
+void cCmdExit(void)
+{
+ return;
+}
diff --git a/AT91SAM7S256/Source/c_cmd_bytecodes.h b/AT91SAM7S256/Source/c_cmd_bytecodes.h
new file mode 100644
index 0000000..6051aba
--- /dev/null
+++ b/AT91SAM7S256/Source/c_cmd_bytecodes.h
@@ -0,0 +1,115 @@
+#ifndef C_CMD_BYTECODES
+#define C_CMD_BYTECODES
+//
+// opcode definitions
+// symbol, bits, arg format
+//
+#define OPCODE_COUNT 0x36
+
+//Family: Math
+#define OP_ADD 0x00 // dest, src1, src2
+#define OP_SUB 0x01 // dest, src1, src2
+#define OP_NEG 0x02 // dest, src
+#define OP_MUL 0x03 // dest, src1, src2
+#define OP_DIV 0x04 // dest, src1, src2
+#define OP_MOD 0x05 // dest, src1, src2
+
+//Family: Logic
+#define OP_AND 0x06 // dest, src1, src2
+#define OP_OR 0x07 // dest, src1, src2
+#define OP_XOR 0x08 // dest, src1, src2
+#define OP_NOT 0x09 // dest, src
+
+//Family: Bit manipulation
+#define OP_CMNT 0x0A // dest, src
+#define OP_LSL 0x0B // dest, src
+#define OP_LSR 0x0C // dest, src
+#define OP_ASL 0x0D // dest, src
+#define OP_ASR 0x0E // dest, src
+#define OP_ROTL 0x0F // dest, src
+#define OP_ROTR 0x10 // dest, src
+
+//Family: Comparison
+#define OP_CMP 0x11 // dest, src1, src2
+#define OP_TST 0x12 // dest, src
+#define OP_CMPSET 0x13 // dest, src, testsrc, testsrc
+#define OP_TSTSET 0x14 // dest, src, testsrc
+
+//Family: Array ops
+#define OP_INDEX 0x15 // dest, src, index
+#define OP_REPLACE 0x16 // dest, src, index, val
+#define OP_ARRSIZE 0x17 // dest, src
+#define OP_ARRBUILD 0x18 // instrsize, dest, src1, src2, …
+#define OP_ARRSUBSET 0x19 // dest, src, index, length
+#define OP_ARRINIT 0x1A // dest, elem, length
+
+//Family: Memory ops
+#define OP_MOV 0x1B // dest, src
+#define OP_SET 0x1C // dest, imm
+
+//Family: String ops
+#define OP_FLATTEN 0x1D // dest, src
+#define OP_UNFLATTEN 0x1E // dest, err, src, type
+#define OP_NUMTOSTRING 0x1F // dest, src
+#define OP_STRINGTONUM 0x20 // dest, offsetpast, src, offset, default
+#define OP_STRCAT 0x21 // instrsize, dest, src1, src2, …
+#define OP_STRSUBSET 0x22 // dest, src, index, length
+#define OP_STRTOBYTEARR 0x23 // dest, src
+#define OP_BYTEARRTOSTR 0x24 // dest, src
+
+//Family: Control flow
+#define OP_JMP 0x25 // offset
+#define OP_BRCMP 0x26 // offset, src1, src2
+#define OP_BRTST 0x27 // offset, src
+#define OP_SYSCALL 0x28 // func, args
+#define OP_STOP 0x29 // stop?
+
+//Family: Clump scheduling
+#define OP_FINCLUMP 0x2A // start, end
+#define OP_FINCLUMPIMMED 0x2B // clumpID
+#define OP_ACQUIRE 0x2C // mutexID
+#define OP_RELEASE 0x2D // mutexID
+#define OP_SUBCALL 0x2E // subroutine, callerID
+#define OP_SUBRET 0x2F // callerID
+
+//Family: IO ops
+#define OP_SETIN 0x30 // src, port, propid
+#define OP_SETOUT 0x31 // instrsize, port/portlist, propid1, src1, ...
+#define OP_GETIN 0x32 // dest, port, propid
+#define OP_GETOUT 0x33 // dest, port, propid
+
+//Family: Timing
+#define OP_WAIT 0x34 // milliseconds
+#define OP_GETTICK 0x35 // dest
+
+// condition code definitions
+#define OPCC1_LT 0x00
+#define OPCC1_GT 0x01
+#define OPCC1_LTEQ 0x02
+#define OPCC1_GTEQ 0x03
+#define OPCC1_EQ 0x04
+#define OPCC1_NEQ 0x05
+
+
+
+//
+// short op definitions
+//
+#define USE_SHORT_OPS
+#define SHORT_OP_MOV 0
+#define SHORT_OP_ACQUIRE 1
+#define SHORT_OP_RELEASE 2
+#define SHORT_OP_SUBCALL 3
+
+//
+// short op mapping table
+//
+static UBYTE ShortOpMap[4] =
+{
+ OP_MOV,
+ OP_ACQUIRE,
+ OP_RELEASE,
+ OP_SUBCALL
+};
+
+#endif // C_CMD_BYTECODES
diff --git a/AT91SAM7S256/Source/c_cmd_drawing.inc b/AT91SAM7S256/Source/c_cmd_drawing.inc
new file mode 100644
index 0000000..0132d44
--- /dev/null
+++ b/AT91SAM7S256/Source/c_cmd_drawing.inc
@@ -0,0 +1,894 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 8/26/05 4:17p $
+//
+// Filename $Workfile:: c_cmd.c $
+//
+// Version $Revision:: 35 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_cmd_drawing.c $
+//
+// Platform C
+//
+
+//absolute value of a
+#define ABS(a) (((a)<0) ? -(a) : (a))
+
+//take binary sign of a, either -1, or 1 if >= 0
+#define SGN(a) (((a)<0) ? -1 : 1)
+
+#define DISP_BUFFER_P ((UBYTE*)&(pMapDisplay->Normal))
+
+//------------------------------------------------------------------
+// cCmdClearScreenIfNeeded - Clear entire sceen buffer if explicitly requested or implicitly required.
+void cCmdClearScreenIfNeeded(ULONG DrawOptions);
+
+//------------------------------------------------------------------
+// cCmdRestorDefaultScreen - Restore screen to default 'Running' screen
+void cCmdRestoreDefaultScreen(void);
+
+//------------------------------------------------------------------
+// cCmdDrawString - Draw string to display buffer
+void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y);
+
+// OP codes supported by RIC files
+enum {
+ IMG_DESCRIPTION_ID = 0, // Ignored at this time
+ IMG_SPRITE_ID = 1,
+ IMG_VARMAP_ID = 2,
+ IMG_COPYBITS_ID = 3,
+ IMG_PIXEL_ID = 4,
+ IMG_LINE_ID = 5,
+ IMG_RECTANGLE_ID = 6,
+ IMG_CIRCLE_ID = 7,
+ IMG_NUMBOX_ID = 8
+};
+
+#define IMG_SYMB_USEARGS(_v) (_v & (SWORD)0xF000)
+#define IMG_SYMB_MAP(_v) ((_v & 0x0F00) >> 8)
+#define IMG_SYMB_ARG(_v) (_v & 0x000F)
+
+// DrawingOptions
+#define DRAW_OPT_CLEAR_WHOLE_SCREEN (0x0001)
+#define DRAW_OPT_CLEAR_EXCEPT_STATUS_SCREEN (0x0002)
+#define DRAW_OPT_CLEAR_MODE(_v) ((_v) & 0x0003)
+
+
+// Clear Before Drawing Modes for Draw functions
+enum {
+ DO_NOT_CLEAR = 0,
+ CLEAR_B4_DRAW = 1
+};
+
+// Screen Modes for SetScreenMode function
+enum {
+ RESTORE_NXT_SCREEN = 0
+};
+
+#define IMG_COMMON_FIELDS UWORD OpSize; UWORD OpCode;
+
+#define TRANSLATE_Y(_y) ((DISPLAY_HEIGHT-1) - (_y))
+
+typedef struct
+{
+ SWORD X, Y;
+} IMG_PT;
+
+typedef struct
+{
+ IMG_PT Pt;
+ SWORD Width, Height;
+} IMG_RECT;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+} IMG_OP_CORE;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+ UWORD Options;
+ UWORD Width;
+ UWORD Height;
+} IMG_OP_DESCRIPTION;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+ UWORD DataAddr; //Address sprite handle will be stored in.
+ UWORD Rows; //Second deminsion of the array below.
+ UWORD RowBytes; //The actual size of the following array. Must be even.
+ UBYTE Bytes[2]; //Minimum of two for alignment purposes
+} IMG_OP_SPRITE;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+ UWORD DataAddr; //Address sprite handle will be stored in.
+ UWORD MapCount; //The actual size of the following array. Must be even.
+ struct
+ { //Minimum of two for alignment purposes
+ UWORD Domain;
+ UWORD Range;
+ } MapElt[1];
+} IMG_OP_VARMAP;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+ UWORD CopyOptions; // Copy, CopyNot, Or, BitClear;
+ UWORD DataAddr; // Address of an already defined sprite
+ IMG_RECT Src; // Source rectangle
+ IMG_PT Dst; // Destination left top
+} IMG_OP_COPYBITS;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+ UWORD CopyOptions;
+ IMG_PT Pt;
+ UWORD Value; // typically mapped to an argument
+} IMG_OP_PIXEL;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+ UWORD CopyOptions;
+ IMG_PT Pt1;
+ IMG_PT Pt2;
+} IMG_OP_LINE;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+ UWORD CopyOptions;
+ IMG_PT Pt;
+ SWORD Width, Height;
+} IMG_OP_RECT;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+ UWORD CopyOptions;
+ IMG_PT Pt;
+ UWORD Radius;
+} IMG_OP_CIRCLE;
+
+typedef struct
+{
+ IMG_COMMON_FIELDS
+ UWORD CopyOptions;
+ IMG_PT Pt;
+ UWORD Value; // typically mapped to an argument
+} IMG_OP_NUMBOX;
+
+typedef union
+{ IMG_OP_CORE Core;
+ IMG_OP_DESCRIPTION Desc;
+ IMG_OP_SPRITE Sprite;
+ IMG_OP_VARMAP VarMap;
+ IMG_OP_COPYBITS CopyBits;
+ IMG_OP_PIXEL Pixel;
+ IMG_OP_LINE Line;
+ IMG_OP_RECT Rect;
+ IMG_OP_CIRCLE Circle;
+ IMG_OP_NUMBOX NumBox;
+} IMG_OP_UNION;
+
+// Variables for DrawImage
+#define IMG_MAX_DATA 11
+IMG_OP_UNION * gpImgData[IMG_MAX_DATA];
+SLONG * gpPassedImgVars;
+SWORD gPassedVarsCount;
+
+// Private Prototypes
+void cCmdDrawLine(SLONG x1, SLONG y1, SLONG x2, SLONG y2);
+void cCmdDrawRect(SLONG left, SLONG bottom, SLONG width, SLONG hieght);
+void cCmdCopyBitMapBits(SLONG dst_x, SLONG dst_y,
+ SLONG src_x, SLONG src_y, SLONG src_width, SLONG src_height,
+ IMG_OP_SPRITE * pSprite);
+SLONG cCmdResolveValue(SWORD Value);
+void cCmdSetPixel(SLONG X, SLONG Y, ULONG Val);
+
+//-----------------------------------------------------------------
+//cCmdWrapDrawText
+//ArgV[0]: (Function return) Status byte, SBYTE
+//ArgV[1]: Location (IMG_PT *)
+//ArgV[2]: Text (CStr)
+//ArgV[3]: Options (ULONG)
+//
+NXT_STATUS cCmdWrapDrawText(UBYTE * ArgV[])
+{
+ IMG_PT * pPt = (IMG_PT*) ArgV[1];
+
+ ArgV[2] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[2])); //Resolve array argument
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[3]);
+
+ // Display the String
+ cCmdDrawString(ArgV[2], (UBYTE)pPt->X, (UBYTE)(pPt->Y));
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+
+ // Set return value
+ *((SBYTE*)(ArgV[0])) = NO_ERR;
+
+ return NO_ERR;
+}
+
+//-----------------------------------------------------------------
+//cCmdWrapDrawPoint
+//ArgV[0]: (Function return) Status byte, SBYTE
+//ArgV[1]: Location (IMG_PT *)
+//ArgV[2]: Options (ULONG)
+NXT_STATUS cCmdWrapDrawPoint(UBYTE * ArgV[])
+{
+ IMG_PT * pPt = (IMG_PT*) ArgV[1];
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[2]);
+
+ // Display the String
+ cCmdSetPixel(pPt->X, pPt->Y, TRUE);
+
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+
+ // Set return value
+ *((SBYTE*)(ArgV[0])) = NO_ERR;
+
+ return NO_ERR;
+}
+
+//-----------------------------------------------------------------
+//cCmdWrapDrawLine
+//ArgV[0]: (Function return) Status byte, SBYTE
+//ArgV[1]: Start Location (IMG_PT *)
+//ArgV[2]: End Location (IMG_PT *)
+//ArgV[3]: Options (ULONG)
+NXT_STATUS cCmdWrapDrawLine(UBYTE * ArgV[])
+{
+ IMG_PT * pPt1 = (IMG_PT*) ArgV[1];
+ IMG_PT * pPt2 = (IMG_PT*) ArgV[2];
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[3]);
+
+ cCmdDrawLine(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y);
+
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+
+ // Set return value
+ *((SBYTE*)(ArgV[0])) = NO_ERR;
+
+ return NO_ERR;
+}
+
+//-----------------------------------------------------------------
+//cCmdWrapDrawCircle
+//ArgV[0]: (Function return) Status byte, SBYTE
+//ArgV[1]: Start Location (IMG_PT *)
+//ArgV[2]: Radius (U8)
+//ArgV[3]: Options (ULONG)
+NXT_STATUS cCmdWrapDrawCircle(UBYTE * ArgV[])
+{
+ SLONG x, x1, y1, y, dp, delta;
+ IMG_PT * pPt = (IMG_PT*) ArgV[1];
+ SLONG radius = *(UBYTE*)ArgV[2];
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[3]);
+
+ x1 = pPt->X;
+ y1 = pPt->Y;
+ x = 0;
+ y = radius;
+ dp=2*(1-radius);
+ while(y >= 0)
+ {
+ cCmdSetPixel((x+x1), (y+y1), TRUE);
+ cCmdSetPixel((-x+x1),(-y+y1), TRUE);
+ cCmdSetPixel((x+x1), (-y+y1), TRUE);
+ cCmdSetPixel((-x+x1),(y+y1), TRUE);
+ if(dp<0)
+ {
+ delta = 2*dp + 2*y - 1;
+ if (delta > 0)
+ {
+ x++;
+ y--;
+ dp += 2*x - 2*y + 2;
+ }
+ else
+ {
+ x++;
+ dp += 2*x + 1;
+ }
+ }
+ else if (dp > 0)
+ {
+ delta = 2*dp - 2*x - 1;
+ if (delta > 0)
+ {
+ y--;
+ dp += 1 - 2*y;
+ }
+ else
+ {
+ x++;
+ y--;
+ dp += 2*x - 2*y + 2;
+ }
+ }
+ else
+ {
+ x++;
+ y--;
+ dp += 2*x - 2*y +2;
+ }
+ }
+
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+
+ // Set return value
+ *((SBYTE*)(ArgV[0])) = NO_ERR;
+
+ return NO_ERR;
+}
+
+//-----------------------------------------------------------------
+//cCmdWrapDrawRect
+//ArgV[0]: (Function return) Status byte, SBYTE
+//ArgV[1]: TopLeft (IMG_PT *)
+//ArgV[2]: BottomRight (IMG_PT *)
+//ArgV[3]: Options (ULONG)
+NXT_STATUS cCmdWrapDrawRect(UBYTE * ArgV[])
+{
+ IMG_PT * pPt1 = (IMG_PT*) ArgV[1];
+ IMG_PT * pPt2 = (IMG_PT*) ArgV[2]; // Second point is actually (width, height)
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[3]);
+
+ cCmdDrawRect(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y);
+
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+
+ // Set return value
+ *((SBYTE*)(ArgV[0])) = NO_ERR;
+
+ return NO_ERR;
+}
+
+//-----------------------------------------------------------------
+IMG_OP_UNION * cCmdGetIMGData(ULONG DataAddr)
+{
+ if (DataAddr >= IMG_MAX_DATA)
+ return NULL;
+ else
+ return gpImgData[DataAddr];
+}
+
+//-----------------------------------------------------------------
+void cCmdSetIMGData(ULONG DataAddr, IMG_OP_UNION * pSprite)
+{
+ if ((DataAddr >= 1) && (DataAddr < IMG_MAX_DATA))
+ gpImgData[DataAddr] = pSprite;
+}
+
+//-----------------------------------------------------------------
+SLONG cCmdResolveValue(SWORD Value)
+{
+ if (!IMG_SYMB_USEARGS(Value))
+ {
+ return Value;
+ }
+ else
+ {
+ IMG_OP_VARMAP * pVarMap;
+ SLONG Arg;
+
+ pVarMap = (IMG_OP_VARMAP *) cCmdGetIMGData((SWORD)IMG_SYMB_MAP(Value));
+ Arg = gpPassedImgVars[IMG_SYMB_ARG(Value)];
+
+ if (!pVarMap)
+ {
+ // No map, this implies a 1:1 mapping.
+ return Arg;
+ }
+ else
+ {
+ // Scan through the list finding the pair the Arg lies between
+ // Then linearly interpolate the mapping.
+ SLONG i, DCur, RCur, DSpread, VSpread, RSpread;
+ SLONG Count = pVarMap->MapCount;
+ SLONG DPrev = pVarMap->MapElt[0].Domain;
+ SLONG RPrev = pVarMap->MapElt[0].Range;
+ if (Arg <= DPrev)
+ {
+ // Too small, map it to the first point
+ return RPrev;
+ }
+
+ for (i = 1; i < Count; i++)
+ {
+ DCur = pVarMap->MapElt[i].Domain;
+ RCur = pVarMap->MapElt[i].Range;
+ if (Arg < DCur)
+ {
+ DSpread = DCur - DPrev;
+ VSpread = Arg - DPrev;
+ RSpread = RCur - RPrev;
+ // Found the point and mapped, it return.
+ return (RPrev+((VSpread*RSpread)/DSpread));
+ }
+ DPrev = DCur;
+ RPrev = RCur;
+ }
+ // If we get this far then it is too large, map it to the last point.
+ return RCur;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------
+//cCmdWrapDrawGraphic
+//ArgV[0]: (Function return) Status Byte, SBYTE
+//ArgV[1]: Left Top (IMG_PT *)
+//ArgV[2]: Filename, CStr
+//ArgV[3]: Variables, array of I32
+//ArgV[4]: Options (ULONG)
+NXT_STATUS cCmdWrapDrawPicture(UBYTE * ArgV[])
+{
+ SBYTE * pReturnVal = (SBYTE*)(ArgV[0]);
+ LOADER_STATUS LStatus;
+ NXT_STATUS DStatus = NO_ERR;
+ ULONG DataSize;
+ SLONG OpSize;
+ IMG_PT Pt; // Where to draw the picture at (up and to the right)
+ UBYTE ImageHandle;
+ IMG_OP_UNION * pImage;
+
+ //Resolve array argument
+ ArgV[2] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[2]));
+ ArgV[3] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[3]));
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[4]);
+
+ //Open the file in memory map mode. return if failure.
+ LStatus = pMapLoader->pFunc(OPENREADLINEAR, ArgV[2], (UBYTE*)(&pImage), &DataSize);
+ ImageHandle = LOADER_HANDLE(LStatus);
+
+ //If error opening file, give up and write loader status back to user.
+ if (LOADER_ERR(LStatus) != SUCCESS || pImage == NULL)
+ {
+ *pReturnVal = (SBYTE)(LOADER_ERR_BYTE(LStatus));
+ return (NO_ERR);
+ }
+ //Else, start interpretting the file
+ else
+ {
+ // Read the ArgV params, Clear the data table.
+ Pt = *(IMG_PT*)ArgV[1];
+ //!!! Unsafe assumption that array is non-empty. Should check and avoid using pointer if empty.
+ gpPassedImgVars = (SLONG*)ArgV[3];
+ memset(gpImgData,0,sizeof(gpImgData));
+
+ // Run through the op codes.
+ while(!IS_ERR(DStatus))
+ {
+ // Setup to look at an opcode, make sure it looke reasonable.
+ if (DataSize < sizeof(IMG_OP_CORE))
+ {
+ DStatus = ERR_FILE;
+ break; // Too small to look at, somethings wrong.
+ }
+ OpSize = pImage->Core.OpSize + sizeof(UWORD);
+ if (OpSize & 0x01)
+ {
+ DStatus = ERR_FILE;
+ break; // Odd sizes not allowed.
+ }
+
+ switch(pImage->Core.OpCode)
+ {
+ case IMG_SPRITE_ID:
+ {
+ if (OpSize >= sizeof(IMG_OP_SPRITE))
+ cCmdSetIMGData(pImage->Sprite.DataAddr, pImage);
+ }
+ break;
+
+ case IMG_VARMAP_ID:
+ {
+ if (OpSize >= sizeof(IMG_OP_VARMAP))
+ cCmdSetIMGData(pImage->VarMap.DataAddr, pImage);
+ }
+ break;
+
+ case IMG_COPYBITS_ID:
+ {
+ if (OpSize >= sizeof(IMG_OP_COPYBITS))
+ {
+ IMG_OP_COPYBITS * pCB = &(pImage->CopyBits);
+ cCmdCopyBitMapBits(
+ (cCmdResolveValue(pCB->Dst.X) + Pt.X),
+ (cCmdResolveValue(pCB->Dst.Y) + Pt.Y),
+ cCmdResolveValue((pCB->Src.Pt.X)),
+ cCmdResolveValue((pCB->Src.Pt.Y)),
+ cCmdResolveValue((pCB->Src.Width)),
+ cCmdResolveValue((pCB->Src.Height)),
+ (IMG_OP_SPRITE*)cCmdGetIMGData(cCmdResolveValue(pCB->DataAddr)));
+ }
+ }
+ break;
+
+ case IMG_LINE_ID:
+ {
+ if (OpSize >= sizeof(IMG_OP_LINE))
+ {
+ IMG_OP_LINE * pL = &(pImage->Line);
+ cCmdDrawLine(
+ (cCmdResolveValue(pL->Pt1.X)+Pt.X),
+ (cCmdResolveValue(pL->Pt1.Y)+Pt.Y),
+ (cCmdResolveValue(pL->Pt2.X)+Pt.X),
+ (cCmdResolveValue(pL->Pt2.Y)+Pt.Y)
+ );
+ }
+ }
+ break;
+
+ case IMG_RECTANGLE_ID:
+ {
+ if (OpSize >= sizeof(IMG_OP_LINE))
+ {
+ IMG_OP_RECT * pL = &(pImage->Rect);
+ cCmdDrawRect(
+ (SWORD)(cCmdResolveValue(pL->Pt.X)+Pt.X),
+ (SWORD)(cCmdResolveValue(pL->Pt.Y)+Pt.Y),
+ (SWORD)(cCmdResolveValue(pL->Width)),
+ (SWORD)(cCmdResolveValue(pL->Height))
+ );
+ }
+ }
+ break;
+
+ case IMG_PIXEL_ID:
+ {
+ if (OpSize >= sizeof(IMG_OP_PIXEL))
+ {
+ cCmdSetPixel(
+ (cCmdResolveValue(pImage->Pixel.Pt.X) + Pt.X),
+ (cCmdResolveValue(pImage->Pixel.Pt.Y) + Pt.Y),
+ TRUE);
+ }
+ }
+ break;
+
+ case IMG_NUMBOX_ID:
+ {
+ if (OpSize >= sizeof(IMG_OP_NUMBOX))
+ {
+ UBYTE NumStr[20];
+ IMG_OP_NUMBOX * pNB = &(pImage->NumBox);
+ sprintf((PSZ)NumStr, "%d", cCmdResolveValue(pNB->Value));
+ cCmdDrawString(
+ NumStr,
+ (UBYTE) (cCmdResolveValue(pNB->Pt.X) + Pt.X),
+ (UBYTE) (cCmdResolveValue(pNB->Pt.Y) + Pt.Y));
+ }
+ }
+ break;
+
+ case IMG_DESCRIPTION_ID:
+ {
+ //No-op
+ }
+ break;
+
+ default:
+ {
+ //Unrecognized opcode, pass an error back to the user.
+ DStatus = ERR_FILE;
+ }
+ break;
+ }
+
+ DataSize -= OpSize;
+ pImage = (IMG_OP_UNION*) ((UBYTE*)pImage + OpSize);
+ }
+
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ }
+
+ // Set return value, close file and return
+ *pReturnVal = DStatus;
+ pMapLoader->pFunc(CLOSE, &ImageHandle, NULL, NULL);
+ return (NO_ERR);
+}
+
+//-----------------------------------------------------------------
+// cCmdDrawLine - draw a line. All clipping is done by the set pixel function.
+void cCmdDrawLine(
+ SLONG x1,
+ SLONG y1,
+ SLONG x2,
+ SLONG y2)
+{
+ SLONG d,x,y,ax,ay,sx,sy,dx,dy;
+
+ // Initialize variables
+ dx = x2-x1; ax = ABS(dx)<<1; sx = SGN(dx);
+ dy = y2-y1; ay = ABS(dy)<<1; sy = SGN(dy);
+ x = x1;
+ y = y1;
+ if (ax>ay)
+ { /* x dominant */
+ d = ay-(ax>>1);
+ for (;;)
+ {
+ cCmdSetPixel(x, y, TRUE);
+ if (x==x2)
+ return;
+ if (d>=0)
+ {
+ y += sy;
+ d -= ax;
+ }
+ x += sx;
+ d += ay;
+ }
+ }
+ else
+ { /* y dominant */
+ d = ax-(ay>>1);
+ for (;;)
+ {
+ cCmdSetPixel(x, y, TRUE);
+ if (y==y2)
+ return;
+ if (d>=0)
+ {
+ x += sx;
+ d -= ay;
+ }
+ y += sy;
+ d += ax;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------
+// cCmdDrawRect - draw a rectangle. All clipping is done by the set pixel function.
+void cCmdDrawRect(
+ SLONG left,
+ SLONG bottom,
+ SLONG width,
+ SLONG height)
+{
+ SLONG right = left + width;
+ SLONG top = bottom + height;
+
+ // Draw the four line segments
+ cCmdDrawLine(left, top, right, top);
+ cCmdDrawLine(right, top, right, bottom);
+ cCmdDrawLine(right, bottom, left, bottom);
+ cCmdDrawLine(left, bottom, left, top);
+}
+
+
+#ifndef DISPLAY_REALWIDTH
+ #define DISPLAY_REALWIDTH DISPLAY_WIDTH
+#endif
+//-----------------------------------------------------------------
+//cCmdCopyBitMapBits
+void cCmdCopyBitMapBits(
+ SLONG dst_x, // left pixel on LCD
+ SLONG dst_y, // bottom pixel on LCD
+ SLONG src_x, // starting pixel x coordinate from source map
+ SLONG src_y, // starting pixel y coordinate from source map
+ SLONG src_width, // width in pixels to the right (negative implies to the left)
+ SLONG src_height, // height in pixels down (negative implies down)
+ IMG_OP_SPRITE * pSprite)
+{
+ SLONG dy; // Location in the destination pixmap , the screen that is
+ SLONG sx;
+ SLONG sy; // Location in the source pixmap.
+ SLONG trim, last_x, last_y, rowbytes;
+ UBYTE *pSrcByte;
+ UBYTE *pDstBytes;
+ UBYTE *pDstByte, *pFirstDstByte;
+ UBYTE *pLastDstByte;
+ UBYTE bit_y, not_bit_y;
+ UBYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+
+ // Data in the image file is row major 8 pixels per byte.top row first.
+ // src and dst coordinates treat the bottom left most pixel as (0,0)
+
+ if (!pSprite || pSprite->OpCode!=IMG_SPRITE_ID)
+ return;
+
+ pDstBytes = DISP_BUFFER_P;
+
+ // Clip the edges. Modify the source and width as well.
+ if (dst_x < 0) { // bounds check start of x
+ trim = (0 - dst_x);
+ dst_x = 0;
+ src_x += trim;
+ src_width -= trim;
+ }
+
+ last_x = dst_x + src_width;
+ if (last_x > DISPLAY_WIDTH) // bound check end of x
+ last_x = DISPLAY_WIDTH;
+
+ if (dst_y < 0) { // bound check start of y
+ trim = (0 - dst_y);
+ dst_y = 0;
+ src_y += trim; // fix up source as well since we are clipping the start of the loop
+ src_height -= trim;
+ }
+
+ last_y = dst_y + src_height;
+ if (last_y > DISPLAY_HEIGHT) // bound check end of y
+ last_y = DISPLAY_HEIGHT;
+
+ // Convert the 0,0 bottom left origin to the top left 0,0 used by the actual
+ // buffer
+ last_y = TRANSLATE_Y(last_y);
+ dst_y = TRANSLATE_Y(dst_y);
+
+ // The last row is the top most scan line in the LCD Buffer
+ // so limit if the copy would copy into memory before the buffer.
+ // The first row copied will be the one closest to the bottom of the LCD
+ // If that is off screen then limit as well and adjust the start point on the start
+
+ // Copy bits top to top moving down.
+ sy = src_y;
+ rowbytes = pSprite->RowBytes;
+
+ pSrcByte = pSprite->Bytes + ((pSprite->Rows - 1 - sy) * rowbytes);
+ pFirstDstByte = pDstBytes + ((dst_y >> 3) * DISPLAY_REALWIDTH) + dst_x;
+ for (dy = dst_y; dy > last_y; dy--)
+ {
+ sx = src_x;
+ bit_y = masks[7 - (dy & 0x07)];
+ not_bit_y = ~ bit_y;
+ pDstByte = pFirstDstByte;
+ pLastDstByte = pDstByte + (last_x - dst_x);
+ for (; pDstByte < pLastDstByte; pDstByte++)
+ {
+ if ( *(pSrcByte + (sx >> 3)) & masks[sx & 0x07] ){
+ *pDstByte |= bit_y;
+ } else {
+ *pDstByte &= not_bit_y;
+ }
+ sx ++;
+ }
+ pSrcByte -= rowbytes;
+ sy ++;
+ if ((dy & 0x07) == 0) // bump back the scan line start point at rollover
+ pFirstDstByte -= DISPLAY_REALWIDTH;
+ }
+
+}
+
+//-----------------------------------------------------------------
+// cCmdSetPixel - Set or clear a pixel based on Val
+void cCmdSetPixel(SLONG X, SLONG Y, ULONG Val)
+{
+ Y = TRANSLATE_Y(Y);
+
+ pMapDisplay->pFunc(DISPLAY_PIXEL, (UBYTE)Val, (UBYTE)X, (UBYTE)Y, 0, 0);
+}
+
+
+//-----------------------------------------------------------------
+//cCmdWrapSetScreenMode
+//ArgV[0]: (Function return) Status code, SBYTE
+//ArgV[1]: ScreenMode ULONG
+NXT_STATUS cCmdWrapSetScreenMode(UBYTE * ArgV[])
+{
+ ULONG ScreenMode = (ULONG)(*ArgV[1]);
+ if (ScreenMode == RESTORE_NXT_SCREEN) {
+ cCmdRestoreDefaultScreen();
+ }
+
+ // Set return value
+ *(SBYTE*)(ArgV[0]) = NO_ERR;
+ return NO_ERR;
+}
+
+//------------------------------------------------------------------
+// cCmdClearScreenIfNeeded - Clear entire sceen buffer if explicitly requested or implicitly required.
+void cCmdClearScreenIfNeeded(ULONG DrawOptions)
+{
+ //If we are the first drawing command, clear the screen and record that we've done so
+ if (VarsCmd.DirtyDisplay == FALSE)
+ {
+ VarsCmd.DirtyDisplay = TRUE;
+ pMapUi->Flags &= ~UI_ENABLE_STATUS_UPDATE;
+
+ //Override DrawOptions because we have to clear anyway
+ DrawOptions = DRAW_OPT_CLEAR_WHOLE_SCREEN;
+ }
+
+ if (DRAW_OPT_CLEAR_MODE(DrawOptions))
+ {
+ pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0);
+
+ //Clear UpdateMask to kill any pending updates
+ pMapDisplay->UpdateMask = 0;
+ }
+
+ return;
+}
+
+//------------------------------------------------------------------
+// cCmdDrawString - Draw string to display buffer
+// Properly uses 'Normal' display buffer to avoid conflicts with popup buffer
+// Clips text at bottom and right hand edges of the screen buffer
+//!!! Function copied and modified from cDisplayString
+void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y)
+{
+ UBYTE *pSource;
+ UBYTE *pDestination;
+ FONT *pFont;
+ ULONG FontWidth;
+ ULONG Items;
+ ULONG Item;
+ ULONG Line;
+
+ //Get current font information
+ pFont = pMapDisplay->pFont;
+ Items = pFont->ItemsX * pFont->ItemsY;
+
+ //Invert Y coordinate to match display buffer
+ Y = TRANSLATE_Y(Y);
+ Line = (Y & 0xF8) / 8;
+
+ //If text line is out of bounds, do nothing.
+ if (Line >= TEXTLINES)
+ return;
+
+ //Calculate pointer to first byte of drawing destination
+ pDestination = &(DISP_BUFFER_P[Line * DISPLAY_WIDTH + X]);
+
+ while (*pString)
+ {
+ FontWidth = pFont->ItemPixelsX;
+ //Calculate X coordinate of the right edge of this character.
+ //If it will extend past the right edge, clip the string.
+ X += FontWidth;
+ if (X >= DISPLAY_WIDTH)
+ break;
+
+ //If Item is defined by the font, display it. Else, ignore it.
+ Item = *pString - ' ';
+ if (Item < Items)
+ {
+ pSource = (UBYTE*)&(pFont->Data[Item * FontWidth]);
+ while (FontWidth--)
+ {
+ *pDestination = *pSource;
+ pDestination++;
+ pSource++;
+ }
+ }
+ pString++;
+ }
+}
+
+//------------------------------------------------------------------
+// cCmdRestoreDefaultScreen - Restore to Default 'Running' screen
+void cCmdRestoreDefaultScreen(void)
+{
+ //If this program has taken over the display, reset it for the UI
+ if (VarsCmd.DirtyDisplay == TRUE)
+ {
+ VarsCmd.DirtyDisplay = FALSE;
+
+ pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0);
+ pMapDisplay->UpdateMask = SCREEN_BIT(SCREEN_BACKGROUND);
+
+ pMapUi->Flags |= UI_ENABLE_STATUS_UPDATE | UI_REDRAW_STATUS;
+ }
+}
diff --git a/AT91SAM7S256/Source/c_comm.c b/AT91SAM7S256/Source/c_comm.c
new file mode 100644
index 0000000..291c96b
--- /dev/null
+++ b/AT91SAM7S256/Source/c_comm.c
@@ -0,0 +1,3658 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:42 $
+//
+// Filename $Workfile:: c_comm.c $
+//
+// Version $Revision:: 172 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_comm.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "modules.h"
+#include "c_comm.iom"
+#include "c_loader.iom"
+#include "c_ioctrl.iom"
+#include "c_ui.iom"
+#include "c_cmd.iom"
+#include "c_display.iom"
+#include "c_comm.h"
+#include "d_usb.h"
+#include "d_hispeed.h"
+#include "d_bt.h"
+#include <string.h>
+#include <ctype.h>
+
+enum
+{
+ DEVICE_VERIFIED,
+ DEVICE_UPDATED,
+ DEVICE_INSERTED
+};
+
+#define DEFAULTBTADR "\x00\x16\x53\xFF\xFF\xFF"
+#define BTSTREAMTOUT 610
+
+#define LOOKUPNO 3
+
+#define CLEARExtMode {\
+ UBYTE Tmp;\
+ for(Tmp = 0; Tmp < NO_OF_CHANNELS; Tmp++)\
+ {\
+ VarsComm.ExtMode[Tmp].Status = FALSE;\
+ }\
+ }
+
+#define CHNumber(Bit) (Bit>>1)
+#define SETBtStateIdle VarsComm.ActiveUpdate = UPD_IDLE;\
+ VarsComm.UpdateState = 0;\
+ VarsComm.StreamStateCnt = 0;\
+ VarsComm.CmdSwitchCnt = 0;\
+ VarsComm.CloseConn0Cnt = 0;\
+ VarsComm.DiscAllCnt = 0;\
+ VarsComm.ResetBtCnt = 0
+
+#define SETBtCmdState VarsComm.BtState = BT_ARM_CMD_MODE;\
+ IOMapComm.BtInBuf.InPtr = 0;\
+ CLEARExtMode;\
+ dBtClearArm7CmdSignal();\
+ dBtInitReceive(VarsComm.BtModuleInBuf.Buf, (UBYTE)CMD_MODE);
+
+#define SETBtDataState IOMapComm.BtInBuf.InPtr = 0;\
+ VarsComm.BtState = BT_ARM_DATA_MODE;\
+ dBtClearTimeOut(); /* stop cmd timeout because in datamode */\
+ dBtSetArm7CmdSignal();\
+ dBtInitReceive(VarsComm.BtModuleInBuf.Buf, (UBYTE)STREAM_MODE)
+
+#define SETBtOff VarsComm.BtState = BT_ARM_OFF;\
+ dBtSetBcResetPinLow()
+
+#define CLEARConnEntry(Index) memset((IOMapComm.BtConnectTable[Index].BdAddr), 0, SIZE_OF_BDADDR);\
+ memset(IOMapComm.BtConnectTable[Index].Name, 0, SIZE_OF_BT_NAME);\
+ memset((IOMapComm.BtConnectTable[Index].ClassOfDevice), 0, SIZE_OF_CLASS_OF_DEVICE);\
+ memset((IOMapComm.BtConnectTable[Index].PinCode), 0, SIZE_OF_BT_PINCODE);\
+ IOMapComm.BtConnectTable[Index].HandleNr = BLUETOOTH_HANDLE_UNDEFIEND;\
+ IOMapComm.BtConnectTable[Index].StreamStatus = 0;\
+ IOMapComm.BtConnectTable[Index].LinkQuality = 0
+
+#define FILETXTOUT 30000
+
+const UBYTE BootString[] = {"Let's dance: SAMBA"};
+const UBYTE NoName[SIZE_OF_BT_NAME] = {"No Name"};
+
+static IOMAPCOMM IOMapComm;
+static VARSCOMM VarsComm;
+static HEADER **pHeaders;
+
+const HEADER cComm =
+{
+ 0x00050001L,
+ "Comm",
+ cCommInit,
+ cCommCtrl,
+ cCommExit,
+ (void *)&IOMapComm,
+ (void *)&VarsComm,
+ (UWORD)sizeof(IOMapComm),
+ (UWORD)sizeof(VarsComm),
+ 0x0000 /* Code size - not used so far */
+};
+
+UWORD cCommReceivedBtData(void);
+void cCommBtCmdInterpreter(void);
+UWORD cCommInterprete(UBYTE *pInBuf, UBYTE *pOutBuf, UBYTE *pLength, UBYTE CmdBit, UWORD MsgLength);
+UWORD cCommInterpreteCmd(UBYTE Cmd, UBYTE *pInBuf, UBYTE *pOutBuf, UBYTE *pLength, UBYTE CmdBit, UWORD MsgLength);
+void cCommCpyToUpper(UBYTE *pDst, UBYTE *pSrc, UBYTE Length);
+void cCommCopyFileName(UBYTE *pDst, UBYTE *pSrc);
+void cCommSendHiSpeedData(void);
+void cCommReceivedHiSpeedData(void);
+UWORD cCommReq(UBYTE Cmd, UBYTE Param1, UBYTE Param2, UBYTE Param3, UBYTE *pName, UWORD *pRetVal);
+UBYTE cCommBtValidateCmd(void);
+
+void cCommClearStreamStatus(void);
+void cCommUpdateBt(void);
+UWORD cCommCopyBdaddr(UBYTE *pDst, UBYTE *pSrc);
+UWORD cCommInsertBtName(UBYTE *pDst, UBYTE *pSrc);
+UWORD cCommCheckBdaddr(UBYTE *pAdr, UBYTE *pSrc);
+UWORD cCommInsertDevice(UBYTE *pBdaddr, UBYTE *pName, UBYTE *pCod, UBYTE DeviceStatus, UBYTE *pAddInfo);
+void cCommsSetCmdMode(UBYTE *pNextState);
+void cCommsOpenStream(UBYTE *pNextState);
+void cCommsCloseConn0(UBYTE *pNextState);
+void cCommsDisconnectAll(UBYTE *pNextState);
+void cCommsBtReset(UBYTE *pNextState);
+void cCommPinCode(UBYTE *pPinCode);
+void cCommClrConnTable(void);
+
+void cCommInit(void* pHeader)
+{
+ UBYTE Tmp;
+
+ pHeaders = pHeader;
+ IOMapComm.pFunc = &cCommReq;
+ IOMapComm.pFunc2 = &cCommPinCode;
+ IOMapComm.UsbState = FALSE;
+ IOMapComm.UsbOutBuf.OutPtr = 0;
+
+ CLEARExtMode;
+
+ dUsbInit();
+ dBtInit();
+
+ SETBtStateIdle;
+ VarsComm.BtModuleInBuf.InPtr = 0;
+ VarsComm.BtWaitTimeCnt = 0;
+
+ /* Force a reset sequence on the BC4 */
+ VarsComm.pRetVal = &(VarsComm.RetVal);
+ VarsComm.ActiveUpdate = UPD_RESET;
+
+ VarsComm.BtState = BT_ARM_CMD_MODE;
+ IOMapComm.BrickData.BtHwStatus = BT_DISABLE;
+
+ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++)
+ {
+ IOMapComm.BtDeviceTable[Tmp].DeviceStatus = BT_DEVICE_EMPTY;
+ }
+ IOMapComm.BtDeviceCnt = 0;
+ IOMapComm.BrickData.BtStateStatus = 0;
+
+ cCommClrConnTable();
+
+ dBtInitReceive(VarsComm.BtModuleInBuf.Buf, (UBYTE)CMD_MODE);
+ dBtStartADConverter();
+
+ dHiSpeedInit();
+ VarsComm.HsState = 0;
+
+ IOMapComm.UsbPollBuf.InPtr = 0;
+ IOMapComm.UsbPollBuf.OutPtr = 0;
+
+ VarsComm.BtAdrStatus = COLDBOOT;
+}
+
+void cCommCtrl(void)
+{
+
+ if (FALSE == cCommReceivedBtData())
+ {
+
+ /* there has been a timeout on the BC4 channel */
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = BTTIMEOUT;
+ if (COLDBOOT == VarsComm.BtAdrStatus)
+ {
+
+ /* there is an BT fatal error - set default bt adr and name*/
+ strcpy((char*)IOMapComm.BrickData.Name, (char*)UI_NAME_DEFAULT);
+ dUsbStoreBtAddress((UBYTE*)DEFAULTBTADR);
+ pMapUi->Flags |= UI_REDRAW_STATUS;
+ dBtSetBcResetPinLow();
+ VarsComm.BtAdrStatus = BTADRERROR;
+ }
+ }
+ cCommUpdateBt();
+ VarsComm.BtBcPinLevel = dBtGetBc4CmdSignal();
+
+ if (UPD_IDLE == VarsComm.ActiveUpdate)
+ {
+ switch (VarsComm.BtState)
+ {
+
+ /* Bluetooth device can either be in CMD, DATA or OFF state at top level */
+ case BT_ARM_OFF:
+ {
+ }
+ break;
+ case BT_ARM_CMD_MODE:
+ {
+ if (VarsComm.BtBcPinLevel)
+ {
+ SETBtDataState;
+ }
+ }
+ break;
+
+ case BT_ARM_DATA_MODE:
+ {
+ if (!(VarsComm.BtBcPinLevel))
+ {
+ SETBtCmdState;
+ }
+ }
+ break;
+ }
+ }
+ IOMapComm.BtInBuf.Buf[BT_CMD_BYTE] = 0;
+
+
+ /* Here comes the the HIGHSPEED_PORT implementation */
+ if (IOMapComm.HsFlags & HS_UPDATE)
+ {
+ IOMapComm.HsFlags &= ~HS_UPDATE;
+ switch (IOMapComm.HsState)
+ {
+ case HS_INITIALISE:
+ {
+ dHiSpeedSetupUart();
+ IOMapComm.HsState = HS_INIT_RECEIVER;
+ IOMapComm.HsFlags |= HS_UPDATE;
+ }
+ break;
+
+ case HS_INIT_RECEIVER:
+ {
+ dHiSpeedInitReceive(VarsComm.HsModuleInBuf.Buf);
+ VarsComm.HsState = 0x01;
+ }
+ break;
+
+ case HS_SEND_DATA:
+ {
+ cCommSendHiSpeedData();
+ }
+ break;
+
+ case HS_DISABLE:
+ {
+ VarsComm.HsState = 0x00;
+ dHiSpeedExit();
+ }
+ break;
+ }
+ }
+
+ if (VarsComm.HsState != 0)
+ {
+ cCommReceivedHiSpeedData();
+ }
+
+ /* Here comes the the USB implementation */
+ ULONG Length;
+ UWORD Status;
+
+ if (0 != IOMapComm.UsbOutBuf.OutPtr)
+ {
+ dUsbWrite((const UBYTE *)IOMapComm.UsbOutBuf.Buf, (ULONG)IOMapComm.UsbOutBuf.OutPtr);
+ IOMapComm.UsbOutBuf.OutPtr = 0;
+ }
+
+ Length = 0;
+
+ if (TRUE == dUsbCheckConnection())
+ {
+ pMapUi->UsbState = 1;
+ if (TRUE == dUsbIsConfigured())
+ {
+ Length = dUsbRead(IOMapComm.UsbInBuf.Buf, sizeof(IOMapComm.UsbInBuf.Buf));
+ IOMapComm.UsbState = TRUE;
+ pMapUi->UsbState = 2;
+ }
+ }
+ else
+ {
+ pMapUi->UsbState = 0;
+ dUsbResetConfig();
+ if (TRUE == IOMapComm.UsbState)
+ {
+ IOMapComm.UsbState = FALSE;
+ Status = dUsbGetFirstHandle();
+ while(0 == LOADER_ERR(Status))
+ {
+ IOMapComm.UsbInBuf.Buf[0] = LOADER_HANDLE(Status);
+ pMapLoader->pFunc(CLOSE, &(IOMapComm.UsbInBuf.Buf[0]), &(IOMapComm.UsbInBuf.Buf[2]), &Length);
+ dUsbRemoveHandle(IOMapComm.UsbInBuf.Buf[0]);
+ Status = dUsbGetNextHandle();
+ }
+ }
+ }
+
+ if (0 != Length)
+ {
+ cCommInterprete(IOMapComm.UsbInBuf.Buf, IOMapComm.UsbOutBuf.Buf, (UBYTE*)&Length, USB_CMD_READY, (UWORD)Length);
+ if (Length)
+ {
+ dUsbWrite((const UBYTE *)IOMapComm.UsbOutBuf.Buf, Length);
+ }
+ }
+ dBtStartADConverter();
+}
+
+void cCommExit(void)
+{
+ dUsbExit();
+ dHiSpeedExit();
+ dBtExit();
+}
+
+UWORD cCommInterprete(UBYTE *pInBuf, UBYTE *pOutBuf, UBYTE *pLength, UBYTE CmdBit, UWORD MsgLength)
+{
+ UWORD ReturnStatus;
+ UBYTE Channel;
+
+ Channel = CHNumber(CmdBit);
+ if (FALSE == VarsComm.ExtMode[Channel].Status)
+ {
+
+ switch (((pInBuf[0]) & ~NO_REPLY_BIT))
+ {
+ case SYSTEM_CMD:
+ {
+ ReturnStatus = cCommInterpreteCmd(pInBuf[1], &(pInBuf[1]), &(pOutBuf[2]), pLength, CmdBit, MsgLength);
+
+ /* Check if reply is requested */
+ if ((pInBuf[0]) & NO_REPLY_BIT)
+ {
+
+ /* Sender has choosen no reply */
+ *pLength = 0;
+
+ /* if extended mode then remember the reply bit */
+ VarsComm.ExtMode[Channel].Type |= NO_REPLY_BIT;
+ }
+ else
+ {
+
+ /* Check if receiver wants to reply */
+ if (*pLength)
+ {
+ (*pLength)+= 2;
+ pOutBuf[0] = REPLY_CMD;
+ pOutBuf[1] = pInBuf[1];
+ }
+ }
+ }
+ break;
+
+ case DIRECT_CMD:
+ {
+
+ /* Adjust length to account for cmd type byte */
+ (*pLength) -= 1;
+
+ /* If no reply requested, pass NULL output buffer pointer and clear *pLength */
+ if ((pInBuf[0]) & NO_REPLY_BIT)
+ {
+ pMapCmd->pRCHandler(&(pInBuf[0]), NULL, pLength);
+ }
+ else
+ {
+ pMapCmd->pRCHandler(&(pInBuf[0]), &(pOutBuf[2]), pLength);
+ if (*pLength)
+ {
+ (*pLength) += 2;
+ pOutBuf[0] = REPLY_CMD;
+ pOutBuf[1] = pInBuf[1];
+ }
+ }
+ }
+ break;
+
+ case REPLY_CMD:
+ {
+
+ /* If this is a reply to a direct command opcode, pRCHandler will handle it */
+ if (pInBuf[1] < NUM_RC_OPCODES)
+ pMapCmd->pRCHandler(&(pInBuf[0]), NULL, pLength);
+
+ /* No Reply ever required on REPLY_CMD messages */
+ *pLength = 0;
+ }
+ break;
+
+ default:
+ {
+
+ /* UNSUPPORTED - don't reply on these messages */
+ *pLength = 0;
+ }
+ break;
+ }
+
+ }
+ else
+ {
+ switch (VarsComm.ExtMode[Channel].Type & ~NO_REPLY_BIT)
+ {
+ case SYSTEM_CMD:
+ {
+ ReturnStatus = cCommInterpreteCmd(VarsComm.ExtMode[Channel].Cmd, &(pInBuf[0]), &(pOutBuf[2]), pLength, CmdBit, MsgLength);
+ if ((VarsComm.ExtMode[Channel].Type) & NO_REPLY_BIT)
+ {
+
+ /* Sender has choosen no reply */
+ *pLength = 0;
+ }
+ else
+ {
+
+ /* Check if receiver wants to reply */
+ if (*pLength)
+ {
+ (*pLength) += 2;
+ pOutBuf[0] = REPLY_CMD;
+ pOutBuf[1] = VarsComm.ExtMode[Channel].Cmd;
+ }
+ }
+ }
+ break;
+ case DIRECT_CMD:
+ {
+ }
+ break;
+ case REPLY_CMD:
+ {
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+ }
+
+ return(ReturnStatus);
+}
+
+
+UWORD cCommInterpreteCmd(UBYTE Cmd, UBYTE *pInBuf, UBYTE *pOutBuf, UBYTE *pLength, UBYTE CmdBit, UWORD MsgLength)
+{
+ ULONG FileLength;
+ UWORD Status;
+ UBYTE Channel;
+
+ Channel = CHNumber(CmdBit);
+ switch(Cmd)
+ {
+ case OPENWRITE:
+ {
+ UBYTE TmpFilename[FILENAME_LENGTH + 1];
+
+ FileLength = pInBuf[21];
+ FileLength += (ULONG)pInBuf[22] << 8;
+ FileLength += (ULONG)pInBuf[23] << 16;
+ FileLength += (ULONG)pInBuf[24] << 24;
+
+ cCommCpyToUpper(TmpFilename, &pInBuf[1], (UBYTE)(FILENAME_LENGTH + 1));
+
+ if ((0 != strstr((PSZ)(TmpFilename), ".RXE")) ||
+ (0 != strstr((PSZ)(TmpFilename), ".SYS")) ||
+ (0 != strstr((PSZ)(TmpFilename), ".RTM")))
+ {
+ Status = pMapLoader->pFunc(OPENWRITELINEAR, &pInBuf[1], NULL, &FileLength);
+ }
+ else
+ {
+ Status = pMapLoader->pFunc(OPENWRITE, &pInBuf[1], NULL, &FileLength);
+ }
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ *pLength = 2;
+ if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY))
+ {
+ dUsbInsertHandle(LOADER_HANDLE(Status));
+ }
+ }
+ break;
+ case WRITE:
+ {
+
+ if (FALSE == VarsComm.ExtMode[Channel].Status)
+ {
+
+ FileLength = *pLength - 3;
+ Status = pMapLoader->pFunc(WRITE, &(pInBuf[1]), &(pInBuf[2]), &FileLength);
+ pOutBuf[2] = (UBYTE)(FileLength);
+ pOutBuf[3] = (UBYTE)(FileLength >> 8);
+ if ((*pLength != MsgLength) && (MsgLength != 0))
+ {
+
+ /* This is the beginnig of and extended write command*/
+ VarsComm.ExtMode[Channel].Cmd = WRITE;
+ VarsComm.ExtMode[Channel].Type = SYSTEM_CMD;
+ VarsComm.ExtMode[Channel].Status = TRUE;
+ VarsComm.ExtMode[Channel].Handle = LOADER_HANDLE(Status);
+ *pLength = 0;
+ }
+ else
+ {
+
+ /* Normal write */
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ *pLength = 4;
+ }
+ }
+ else
+ {
+ UWORD TmpLen;
+ FileLength = *pLength;
+ Status = pMapLoader->pFunc(WRITE, &(VarsComm.ExtMode[Channel].Handle), &(pInBuf[0]), &FileLength);
+ TmpLen = pOutBuf[3];
+ TmpLen <<= 8;
+ TmpLen |= pOutBuf[2];
+ TmpLen += FileLength;
+ pOutBuf[2] = (UBYTE)(TmpLen);
+ pOutBuf[3] = (UBYTE)(TmpLen >> 8);
+ if (MsgLength)
+ {
+
+ /* Don't answer before complete message has been received */
+ *pLength = 0;
+ }
+ else
+ {
+
+ /* Complete msg has been received */
+ VarsComm.ExtMode[Channel].Status = FALSE;
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ *pLength = 4; /* Remember the 2 length bytes */
+
+ }
+ }
+
+ }
+ break;
+ case OPENWRITEDATA:
+ {
+ FileLength = pInBuf[21];
+ FileLength += (ULONG)pInBuf[22] << 8;
+ FileLength += (ULONG)pInBuf[23] << 16;
+ FileLength += (ULONG)pInBuf[24] << 24;
+
+ Status = pMapLoader->pFunc(OPENWRITEDATA, &pInBuf[1], NULL, &FileLength);
+
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ *pLength = 2;
+ if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY))
+ {
+ dUsbInsertHandle(LOADER_HANDLE(Status));
+ }
+ }
+ break;
+ case OPENAPPENDDATA:
+ {
+ Status = pMapLoader->pFunc(OPENAPPENDDATA, &pInBuf[1], NULL, &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+
+ pOutBuf[2] = (UBYTE)FileLength;
+ pOutBuf[3] = (UBYTE)(FileLength >> 8);
+ pOutBuf[4] = (UBYTE)(FileLength >> 16);
+ pOutBuf[5] = (UBYTE)(FileLength >> 24);
+ *pLength = 6;
+ if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY))
+ {
+ dUsbInsertHandle(LOADER_HANDLE(Status));
+ }
+ }
+ break;
+ case CLOSE:
+ {
+ if (CmdBit & USB_CMD_READY)
+ {
+ dUsbRemoveHandle(pInBuf[1]);
+ }
+ Status = pMapLoader->pFunc(CLOSE, &(pInBuf[1]), NULL, &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ *pLength = 2;
+ }
+ break;
+ case OPENREAD:
+ {
+ Status = pMapLoader->pFunc(OPENREAD, &pInBuf[1], NULL, &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ pOutBuf[2] = (UBYTE)FileLength;
+ pOutBuf[3] = (UBYTE)(FileLength >> 8);
+ pOutBuf[4] = (UBYTE)(FileLength >> 16);
+ pOutBuf[5] = (UBYTE)(FileLength >> 24);
+ *pLength = 6;
+ if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY))
+ {
+ dUsbInsertHandle(LOADER_HANDLE(Status));
+ }
+ }
+ break;
+ case READ:
+ {
+ ULONG Length;
+
+ FileLength = pInBuf[3];
+ FileLength <<= 8;
+ FileLength |= pInBuf[2];
+ Length = FileLength;
+
+ /* Here test for channel - USB can only handle a 64 byte return (- wrapping )*/
+ if (CmdBit & USB_CMD_READY)
+ {
+ if (FileLength > (SIZE_OF_USBBUF - 6))
+ {
+
+ /* Buffer cannot hold the requested data adjust to buffer size */
+ FileLength = (SIZE_OF_USBBUF - 6);
+ }
+ *pLength = FileLength + 4;
+ Status = pMapLoader->pFunc(READ, &pInBuf[1], &pOutBuf[4], &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ pOutBuf[2] = (UBYTE)Length;
+ pOutBuf[3] = (UBYTE)(Length >> 8);
+
+ if (FileLength < Length)
+ {
+
+ /* End of file is detcted - add up with zeros to the requested msg length */
+ Length -= FileLength;
+ memset(&(pOutBuf[(FileLength + 4)]),0x00,Length);
+ }
+ }
+ else
+ {
+
+ /* This is a BT request - BT can handle large packets */
+ if (FileLength > (SIZE_OF_BTBUF - 6))
+ {
+
+ /* Read length exceeds buffer length check for extended read back */
+ if (SUCCESS == cCommReq(EXTREAD, 0x00, 0x00, 0x00, NULL, &(VarsComm.RetVal)))
+ {
+
+ /* More data requested than buffer can hold .... go into extended mode */
+ VarsComm.ExtTx.RemMsgSize = FileLength;
+ VarsComm.ExtTx.SrcHandle = pInBuf[1];
+ VarsComm.ExtTx.Cmd = READ;
+ *pLength = 0;
+ }
+ else
+ {
+
+ /* We were not able to go into extended mode bt was busy */
+ /* for now do not try to reply as it is not possible to */
+ /* return the requested bytes */
+ *pLength = 0;
+ }
+ }
+ else
+ {
+
+ *pLength = FileLength + 4;
+ Status = pMapLoader->pFunc(READ, &pInBuf[1], &pOutBuf[4], &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ pOutBuf[2] = (UBYTE)Length;
+ pOutBuf[3] = (UBYTE)(Length >> 8);
+
+ if (FileLength < Length)
+ {
+
+ /* End of file is detcted - add up with zeros to the requested msg length */
+ Length -= FileLength;
+ memset(&(pOutBuf[(FileLength + 4)]),0x00,Length);
+ }
+ }
+ }
+ }
+ break;
+ case DELETE:
+ {
+ Status = pMapLoader->pFunc(DELETE, &pInBuf[1], NULL, &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ cCommCopyFileName(&pOutBuf[1], &pInBuf[1]);
+ *pLength = FILENAME_LENGTH + 1 + 1; /*Filemname + 0 terminator + error byte */
+ }
+ break;
+ case FINDFIRST:
+ {
+ Status = pMapLoader->pFunc(FINDFIRST, &(pInBuf[1]), &(pOutBuf[2]), &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ if (LOADER_ERR_BYTE(SUCCESS) == pOutBuf[0])
+ {
+ pOutBuf[22] = (UBYTE)FileLength;
+ pOutBuf[23] = (UBYTE)(FileLength >> 8);
+ pOutBuf[24] = (UBYTE)(FileLength >> 16);
+ pOutBuf[25] = (UBYTE)(FileLength >> 24);
+ if (CmdBit & USB_CMD_READY)
+ {
+ dUsbInsertHandle(pOutBuf[1]);
+ }
+ }
+ else
+ {
+
+ /* ERROR - Fill with zeros */
+ memset(&(pOutBuf[2]),0x00,24);
+ }
+
+ *pLength = 26;
+ }
+ break;
+ case FINDNEXT:
+ {
+ Status = pMapLoader->pFunc(FINDNEXT, &(pInBuf[1]), &(pOutBuf[2]), &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ if (LOADER_ERR_BYTE(SUCCESS) == pOutBuf[0])
+ {
+ pOutBuf[22] = (UBYTE)FileLength;
+ pOutBuf[23] = (UBYTE)(FileLength >> 8);
+ pOutBuf[24] = (UBYTE)(FileLength >> 16);
+ pOutBuf[25] = (UBYTE)(FileLength >> 24);
+ }
+ else
+ {
+
+ /* ERROR - Fill with zeros */
+ memset(&(pOutBuf[2]),0x00,24);
+ }
+ *pLength = 26;
+ }
+ break;
+ case OPENREADLINEAR:
+ {
+
+ /* For internal use only */
+ }
+ break;
+ case VERSIONS:
+ {
+ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS);
+ pOutBuf[1] = (UBYTE)PROTOCOLVERSION;
+ pOutBuf[2] = (UBYTE)(PROTOCOLVERSION>>8);
+ pOutBuf[3] = (UBYTE)FIRMWAREVERSION;
+ pOutBuf[4] = (UBYTE)(FIRMWAREVERSION>>8);
+ *pLength = 5;
+ }
+ break;
+ case OPENWRITELINEAR:
+ {
+ FileLength = pInBuf[21];
+ FileLength += (ULONG)pInBuf[22] << 8;
+ FileLength += (ULONG)pInBuf[23] << 16;
+ FileLength += (ULONG)pInBuf[24] << 24;
+ Status = pMapLoader->pFunc(OPENWRITELINEAR, &pInBuf[1], NULL, &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = LOADER_HANDLE(Status);
+ *pLength = 2;
+ if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY))
+ {
+ dUsbInsertHandle(LOADER_HANDLE(Status));
+ }
+ }
+ break;
+ case FINDFIRSTMODULE:
+ {
+ Status = pMapLoader->pFunc(FINDFIRSTMODULE, &pInBuf[1], &pOutBuf[2], &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = 0;
+
+ if (LOADER_ERR_BYTE(SUCCESS) != pOutBuf[0])
+ {
+ memset(&pOutBuf[2], 0x00, 30);
+ }
+ *pLength = 32;
+ }
+ break;
+
+ case FINDNEXTMODULE:
+ {
+ Status = pMapLoader->pFunc(FINDNEXTMODULE, pInBuf, &pOutBuf[2], &FileLength);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = 0;
+
+ if (LOADER_ERR_BYTE(SUCCESS) != pOutBuf[0])
+ {
+ memset(&pOutBuf[2], 0x00, 30);
+ }
+ *pLength = 32;
+ }
+ break;
+
+ case CLOSEMODHANDLE:
+ {
+ Status = pMapLoader->pFunc(CLOSEMODHANDLE, NULL, NULL, NULL);
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[1] = 0;
+ *pLength = 2;
+ }
+ break;
+
+ case IOMAPREAD:
+ {
+ ULONG ModuleId;
+ UWORD Length;
+
+ ModuleId = pInBuf[1];
+ ModuleId |= (ULONG)pInBuf[2] << 8;
+ ModuleId |= (ULONG)pInBuf[3] << 16;
+ ModuleId |= (ULONG)pInBuf[4] << 24;
+
+ /* Transfer the Module id */
+ pOutBuf[1] = pInBuf[1];
+ pOutBuf[2] = pInBuf[2];
+ pOutBuf[3] = pInBuf[3];
+ pOutBuf[4] = pInBuf[4];
+
+ /* Transfer the offset into the iomap (pOutBuf[6] is intended...)*/
+ pOutBuf[5] = pInBuf[5];
+ pOutBuf[6] = pInBuf[6];
+
+ /* Get the read *pLength */
+ FileLength = pInBuf[8];
+ FileLength <<= 8;
+ FileLength |= pInBuf[7];
+
+ if (CmdBit & USB_CMD_READY)
+ {
+
+ /* test for USB buffer overrun */
+ if (FileLength > (SIZE_OF_USBBUF - 9))
+ {
+ FileLength = SIZE_OF_USBBUF - 9;
+ }
+ }
+ else
+ {
+
+ /* test for BT buffer overrun */
+ if (FileLength > (SIZE_OF_BTBUF - 9))
+ {
+ FileLength = SIZE_OF_BTBUF - 9;
+ }
+ }
+
+ Length = FileLength;
+ *pLength = Length + 7;
+ Status = pMapLoader->pFunc(IOMAPREAD, (UBYTE *)&ModuleId, &pOutBuf[5], &FileLength);
+
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[5] = (UBYTE)FileLength;
+ pOutBuf[6] = (UBYTE)(FileLength >> 8);
+
+ if (Length > FileLength)
+ {
+ Length -= FileLength;
+ memset(&(pOutBuf[FileLength + 7]), 0x00, Length);
+ }
+ }
+ break;
+
+ case IOMAPWRITE:
+ {
+ ULONG ModuleId;
+
+ pOutBuf[1] = pInBuf[1];
+ pOutBuf[2] = pInBuf[2];
+ pOutBuf[3] = pInBuf[3];
+ pOutBuf[4] = pInBuf[4];
+
+ ModuleId = pInBuf[1];
+ ModuleId |= (ULONG)pInBuf[2] << 8;
+ ModuleId |= (ULONG)pInBuf[3] << 16;
+ ModuleId |= (ULONG)pInBuf[4] << 24;
+
+ FileLength = pInBuf[8];
+ FileLength <<= 8;
+ FileLength |= pInBuf[7];
+
+ /* Place offset right before data */
+ pInBuf[8] = pInBuf[6];
+ pInBuf[7] = pInBuf[5];
+
+ Status = pMapLoader->pFunc(IOMAPWRITE, (UBYTE *)&ModuleId, &pInBuf[7], &FileLength);
+
+ pOutBuf[0] = LOADER_ERR_BYTE(Status);
+ pOutBuf[5] = (UBYTE)FileLength;
+ pOutBuf[6] = (UBYTE)(FileLength >> 8);
+
+ *pLength = 7;
+ }
+ break;
+
+ case BOOTCMD:
+ {
+
+ UBYTE Tmp;
+
+ /* The boot command is only allowed by USB - as firmware download can ONLY */
+ /* be send by USB */
+ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR);
+ memset(&(pOutBuf[1]), 0, 4);
+ *pLength = 5;
+
+ if (CmdBit & USB_CMD_READY)
+ {
+
+ Tmp = 0;
+ while((Tmp < (sizeof(BootString) - 1)) && (BootString[Tmp] == pInBuf[Tmp+1]))
+ {
+ Tmp++;
+ }
+ if (Tmp == (sizeof(BootString) - 1))
+ {
+
+ /* Yes valid boot sequence */
+ pMapDisplay->Flags &= ~DISPLAY_ON;
+ pMapDisplay->Flags |= DISPLAY_REFRESH;
+ pMapIoCtrl->PowerOn = BOOT;
+ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS);
+ pOutBuf[1] = 'Y';
+ pOutBuf[2] = 'e';
+ pOutBuf[3] = 's';
+ pOutBuf[4] = '\0';
+ }
+ }
+ }
+ break;
+
+ case SETBRICKNAME:
+ {
+
+ UWORD RtnVal;
+
+ *pLength = 1;
+
+ /* Update the name in the BT device - reply for this command is send */
+ /* before command is actually executed */
+ if (SUCCESS == cCommReq(SETBTNAME, 0, 0, 0, &pInBuf[1], &RtnVal))
+ {
+ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS);
+ cCommInsertBtName(IOMapComm.BrickData.Name, &pInBuf[1]);
+ pMapUi->Flags |= UI_REDRAW_STATUS;
+ }
+ else
+ {
+ pOutBuf[0] = LOADER_ERR_BYTE(BTBUSY);
+ }
+ }
+ break;
+
+ case BTGETADR:
+ {
+ UBYTE Tmp;
+ UBYTE *pAdr;
+
+ pAdr = (IOMapComm.BrickData.BdAddr);
+ for (Tmp = 0; Tmp < 7; Tmp++)
+ {
+ pOutBuf[Tmp + 1] = pAdr[Tmp];
+ }
+ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS);
+ *pLength = 8;
+ }
+ break;
+
+ case DEVICEINFO:
+ {
+
+ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS);
+
+ /* Brick name */
+ memcpy(&(pOutBuf[1]), IOMapComm.BrickData.Name, 15);
+
+ /* BT address */
+ cCommCopyBdaddr(&(pOutBuf[16]), (IOMapComm.BrickData.BdAddr));
+
+ /* Link quality of the 4 possible connected devices */
+ pOutBuf[23] = IOMapComm.BtConnectTable[0].LinkQuality;
+ pOutBuf[24] = IOMapComm.BtConnectTable[1].LinkQuality;
+ pOutBuf[25] = IOMapComm.BtConnectTable[2].LinkQuality;
+ pOutBuf[26] = IOMapComm.BtConnectTable[3].LinkQuality;
+
+ /* Free user flash */
+ memcpy(&(pOutBuf[27]), &(pMapLoader->FreeUserFlash), sizeof(pMapLoader->FreeUserFlash));
+
+ /* Set answer length */
+ *pLength = 31;
+ }
+ break;
+
+ case DELETEUSERFLASH:
+ {
+ Status = pMapLoader->pFunc(DELETEUSERFLASH, NULL, NULL, NULL);
+ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS);
+ *pLength = 1;
+ }
+ break;
+
+ case POLLCMDLEN:
+ {
+
+ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS);
+ pOutBuf[1] = pInBuf[1]; /* This is the Buf Number */
+ if (0 == pInBuf[1])
+ {
+
+ /* USB poll buffer */
+ pOutBuf[2] = ((IOMapComm.UsbPollBuf.InPtr - IOMapComm.UsbPollBuf.OutPtr) & (SIZE_OF_USBBUF - 1));
+ }
+ else
+ {
+
+ /* HI speed poll buffer */
+ pOutBuf[2] = ((IOMapComm.HsInBuf.InPtr - IOMapComm.HsInBuf.OutPtr) & (SIZE_OF_HSBUF - 1));
+ }
+ *pLength = 3;
+ }
+ break;
+
+ case POLLCMD:
+ {
+ UBYTE Tmp;
+ UBYTE MaxBufData;
+
+ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS);
+ pOutBuf[1] = pInBuf[1];
+ *pLength = pInBuf[2];
+
+ if (CmdBit & USB_CMD_READY)
+ {
+ MaxBufData = (SIZE_OF_USBDATA - 5); /* Substract wrapping */
+ }
+ else
+ {
+ MaxBufData = (SIZE_OF_BTBUF - 7); /* Substract wrapping + length bytes for BT*/
+ }
+
+ if (0x00 == pInBuf[1])
+ {
+
+ /* Data from USB poll buffer are requested */
+ if (*pLength <= MaxBufData)
+ {
+ for (Tmp = 0; ((Tmp < (*pLength)) && (IOMapComm.UsbPollBuf.InPtr != IOMapComm.UsbPollBuf.OutPtr)); Tmp++)
+ {
+ pOutBuf[3 + Tmp] = IOMapComm.UsbPollBuf.Buf[IOMapComm.UsbPollBuf.OutPtr];
+ IOMapComm.UsbPollBuf.OutPtr = ((IOMapComm.UsbPollBuf.OutPtr) + 1) % SIZE_OF_USBBUF;
+ }
+ pOutBuf[2] = Tmp;
+
+ /* if end of buffer has been reached fill up with zeros */
+ memset(&(pOutBuf[Tmp + 3]), 0x00, (*pLength - Tmp));
+ }
+ else
+ {
+
+ /* if more data requested than possible to return */
+ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR);
+ pOutBuf[1] = pInBuf[1]; /* This is buffer number */
+ pOutBuf[2] = 0; /* no of bytes returned */
+ *pLength = 0;
+ }
+ }
+ else
+ {
+
+ /* Data from hi speed buffer are requested */
+ if (*pLength <= MaxBufData)
+ {
+ for (Tmp = 0; ((Tmp < (*pLength)) && (IOMapComm.HsInBuf.InPtr != IOMapComm.HsInBuf.OutPtr)); Tmp++)
+ {
+ pOutBuf[3 + Tmp] = IOMapComm.HsInBuf.Buf[IOMapComm.HsInBuf.OutPtr];
+ IOMapComm.HsInBuf.OutPtr = ((IOMapComm.HsInBuf.OutPtr) + 1) % SIZE_OF_USBBUF;
+ }
+ pOutBuf[2] = Tmp;
+
+ /* if end of buffer has been reached fill up with zeros */
+ memset(&(pOutBuf[Tmp + 3]), 0x00, (*pLength - Tmp));
+ }
+ else
+ {
+
+ /* if more data requested than possible to return */
+ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR);
+ pOutBuf[1] = pInBuf[1]; /* This is buffer number */
+ pOutBuf[2] = 0; /* no of bytes returned */
+ *pLength = 0;
+ }
+ }
+ (*pLength) += 3; /* Add 3 bytes for the status byte, length byte and Buf no */
+ }
+ break;
+
+ case BTFACTORYRESET:
+ {
+ UWORD RtnVal;
+
+ if (CmdBit & USB_CMD_READY)
+ {
+ if (SUCCESS == cCommReq(FACTORYRESET, 0, 0, 0, NULL, &RtnVal))
+ {
+
+ /* Request success */
+ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS);
+ }
+ else
+ {
+
+ /* BT request error */
+ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR);
+ }
+ }
+ else
+ {
+
+ /* Factory reset request cannot be done by bluetooth */
+ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR);
+ }
+ *pLength = 1;
+ }
+ break;
+
+ default:
+ {
+ }
+ break;
+ }
+ return(Status);
+}
+
+
+UWORD cCommReceivedBtData(void)
+{
+ UWORD NumberOfBytes;
+ UWORD BytesToGo;
+ UWORD RtnVal;
+
+ RtnVal = dBtReceivedData(&NumberOfBytes, &BytesToGo);
+ if (TRUE == RtnVal)
+ {
+
+ /* Everything is fine go on */
+ if (NumberOfBytes != 0)
+ {
+
+ /* Copy the bytes into the IOMapBuffer */
+ memcpy((IOMapComm.BtInBuf.Buf), (VarsComm.BtModuleInBuf.Buf), NumberOfBytes);
+
+ if (VarsComm.BtState == BT_ARM_CMD_MODE)
+ {
+
+ /* Call the BC4 command interpreter */
+ cCommBtCmdInterpreter();
+ IOMapComm.BtInBuf.InPtr = 0;
+ }
+ else
+ {
+
+ /* ActiveUpdate has to be idle because BC4 can send stream data even if CMD */
+ /* mode has been requested - dont try to interprete the data */
+ /* VarsComm.CmdSwitchCnt != 0 if a transition to Cmd mode is in process */
+ if ((VarsComm.BtState == BT_ARM_DATA_MODE) && (0 == VarsComm.CmdSwitchCnt))
+ {
+
+ /* Move the inptr ahead */
+ IOMapComm.BtInBuf.InPtr = NumberOfBytes;
+
+ /* using the outbuf inptr in order to get the number of bytes in the return answer at the right place*/
+ IOMapComm.BtOutBuf.InPtr = NumberOfBytes;
+
+ /* call the data stream interpreter */
+ cCommInterprete(IOMapComm.BtInBuf.Buf, IOMapComm.BtOutBuf.Buf, &(IOMapComm.BtOutBuf.InPtr), (UBYTE) BT_CMD_READY, BytesToGo);
+
+ /* if there is a reply to be send then send it */
+ if (IOMapComm.BtOutBuf.InPtr)
+ {
+ dBtSendMsg(IOMapComm.BtOutBuf.Buf, IOMapComm.BtOutBuf.InPtr, IOMapComm.BtOutBuf.InPtr);
+ IOMapComm.BtOutBuf.InPtr = 0;
+ }
+ }
+ }
+ }
+ }
+ return(RtnVal);
+}
+
+void cCommBtCmdInterpreter(void)
+{
+
+ /* this function handles all bluecode commands that can be */
+ /* initiated from the outside, meaning from other devices */
+ if(cCommBtValidateCmd())
+ {
+ switch (IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ case MSG_REQUEST_PIN_CODE:
+ {
+
+ /* Pass the pin request on to cCommReq it'l handle it */
+ cCommReq(PINREQ, 0x00, 0x00, 0x00, NULL, &(VarsComm.RetVal));
+ }
+ break;
+
+ case MSG_REQUEST_CONNECTION:
+ {
+
+ /* Connect request from the outside */
+ cCommReq(CONNECTREQ, 0x00, 0x00, 0x00, NULL, &(VarsComm.RetVal));
+ }
+ break;
+
+ case MSG_LIST_RESULT:
+ {
+ switch (IOMapComm.BtInBuf.Buf[2])
+ {
+ case LR_SUCCESS:
+ {
+ }
+ break;
+ case LR_ENTRY_REMOVED:
+ {
+ }
+ break;
+/*
+ case LR_COULD_NOT_SAVE:
+ case LR_STORE_IS_FULL:
+ case LR_UNKOWN_ADDR:
+*/
+ default:
+ {
+ pMapUi->Error = (UBYTE)IOMapComm.BtInBuf.Buf[2];
+ pMapUi->BluetoothState |= BT_ERROR_ATTENTION;
+ }
+ break;
+ }
+ }
+ break;
+
+ case MSG_CLOSE_CONNECTION_RESULT:
+ {
+ UBYTE ConnNo;
+
+ for (ConnNo = 0; ConnNo < SIZE_OF_BT_CONNECT_TABLE; ConnNo++)
+ {
+ if (IOMapComm.BtConnectTable[ConnNo].HandleNr == IOMapComm.BtInBuf.Buf[3])
+ {
+ IOMapComm.BrickData.BtStateStatus &= ~(BT_CONNECTION_0_ENABLE<<ConnNo);
+ CLEARConnEntry(ConnNo);
+ ConnNo = SIZE_OF_BT_CONNECT_TABLE;
+ }
+ }
+
+ if (!(IOMapComm.BrickData.BtStateStatus & (BT_CONNECTION_0_ENABLE | BT_CONNECTION_1_ENABLE | BT_CONNECTION_2_ENABLE | BT_CONNECTION_3_ENABLE)))
+ {
+ pMapUi->BluetoothState &= ~BT_STATE_CONNECTED;
+ }
+ pMapUi->Flags |= UI_REDRAW_STATUS;
+ }
+ break;
+
+ case MSG_PORT_OPEN_RESULT:
+ {
+ if (IOMapComm.BtInBuf.Buf[2] == 1)
+ {
+ IOMapComm.BtConnectTable[0].HandleNr = IOMapComm.BtInBuf.Buf[3];
+ IOMapComm.BrickData.BtStateStatus |= BT_BRICK_PORT_OPEN;
+ }
+ else
+ {
+
+ /* There was an error setting up the OpenPort command in BC4 */
+ IOMapComm.BtConnectTable[0].HandleNr = BLUETOOTH_HANDLE_UNDEFIEND;
+ IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_PORT_OPEN;
+ }
+ }
+ break;
+
+ case MSG_CLOSE_PORT_RESULT:
+ {
+ if (IOMapComm.BtInBuf.Buf[2] == 1)
+ {
+ IOMapComm.BtConnectTable[0].HandleNr = BLUETOOTH_HANDLE_UNDEFIEND;
+ IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_PORT_OPEN;
+ }
+ }
+ break;
+
+ case MSG_PIN_CODE_ACK:
+ {
+ pMapUi->BluetoothState &= ~BT_PIN_REQUEST;
+ }
+ break;
+
+ case MSG_DISCOVERABLE_ACK:
+ {
+ if (VarsComm.BtCmdData.ParamOne == 1)
+ {
+ IOMapComm.BrickData.BtStateStatus |= BT_BRICK_VISIBILITY;
+ pMapUi->BluetoothState |= BT_STATE_VISIBLE;
+ }
+ else
+ {
+ IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_VISIBILITY;
+ pMapUi->BluetoothState &= ~BT_STATE_VISIBLE;
+ }
+ }
+ break;
+ case MSG_RESET_INDICATION:
+ {
+ if ((UPD_RESET != VarsComm.ActiveUpdate) &&
+ (UPD_BRICKNAME != VarsComm.ActiveUpdate) &&
+ (UPD_FACTORYRESET != VarsComm.ActiveUpdate))
+ {
+
+ /* Not intended reset indication - restart the bluecore */
+ if (VarsComm.ActiveUpdate != UPD_IDLE)
+ {
+
+ /* Something was ongoing send error message */
+ *(VarsComm.pRetVal) = (UWORD)ERR_COMM_BUS_ERR;
+ *(VarsComm.pRetVal) |= 0x8000;
+ }
+
+ SETBtStateIdle;
+ VarsComm.pRetVal = &(VarsComm.RetVal);
+ VarsComm.ActiveUpdate = UPD_RESET;
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ /* Receive a message with wrong checkSum ! */
+ }
+}
+
+void cCommCpyToUpper(UBYTE *pDst, UBYTE *pSrc, UBYTE Length)
+{
+ UBYTE Tmp;
+
+ for(Tmp = 0; Tmp < Length; Tmp++)
+ {
+ pDst[Tmp] =(UBYTE)toupper((UWORD)pSrc[Tmp]);
+ }
+
+ /* The requried length has been copied - now fill with zeros */
+ for(Tmp = Length; Tmp < (FILENAME_LENGTH + 1); Tmp++)
+ {
+ pDst[Tmp] = '\0';
+ }
+}
+
+void cCommCopyFileName(UBYTE *pDst, UBYTE *pSrc)
+{
+ UBYTE Tmp;
+
+ for(Tmp = 0; Tmp < (FILENAME_LENGTH + 1); Tmp++, pDst++)
+ {
+ if ('\0' != *pSrc)
+ {
+ *pDst = *pSrc;
+ pSrc++;
+ }
+ else
+ {
+ *pDst = '\0';
+ }
+ }
+}
+
+void cCommSendHiSpeedData(void)
+{
+ VarsComm.HsModuleOutBuf.OutPtr = 0;
+ for (VarsComm.HsModuleOutBuf.InPtr = 0; VarsComm.HsModuleOutBuf.InPtr < IOMapComm.HsOutBuf.InPtr; VarsComm.HsModuleOutBuf.InPtr++)
+ {
+ VarsComm.HsModuleOutBuf.Buf[VarsComm.HsModuleOutBuf.InPtr] = IOMapComm.HsOutBuf.Buf[IOMapComm.HsOutBuf.OutPtr];
+ IOMapComm.HsOutBuf.OutPtr++;
+ }
+ dHiSpeedSendData(VarsComm.HsModuleOutBuf.Buf, (VarsComm.HsModuleOutBuf.InPtr - VarsComm.HsModuleOutBuf.OutPtr));
+}
+
+void cCommReceivedHiSpeedData(void)
+{
+ UWORD NumberOfBytes;
+ UWORD Tmp;
+
+ dHiSpeedReceivedData(&NumberOfBytes);
+
+ if (NumberOfBytes != 0)
+ {
+ for (Tmp = 0; Tmp < NumberOfBytes; Tmp++)
+ {
+ IOMapComm.HsInBuf.Buf[IOMapComm.HsInBuf.InPtr] = VarsComm.HsModuleInBuf.Buf[Tmp];
+ IOMapComm.HsInBuf.InPtr++;
+ if (IOMapComm.HsInBuf.InPtr > (SIZE_OF_HSBUF - 1))
+ {
+ IOMapComm.HsInBuf.InPtr = 0;
+ }
+ VarsComm.HsModuleInBuf.Buf[Tmp] = 0;
+ }
+
+ /* Now new data is available from the HIGH SPEED port ! */
+ }
+}
+
+UBYTE cCommBtValidateCmd(void)
+{
+ UWORD CheckSumTmp = 0;
+ UBYTE Tmp, CheckSumHigh, CheckSumLow;
+
+ for (Tmp = 0; Tmp < (IOMapComm.BtInBuf.Buf[0] - 1);Tmp++)
+ {
+ CheckSumTmp += IOMapComm.BtInBuf.Buf[Tmp];
+ }
+ CheckSumTmp = (UWORD) (1 + (0xFFFF - CheckSumTmp));
+ CheckSumHigh = (UBYTE)((CheckSumTmp & 0xFF00)>>8);
+ CheckSumLow = (UBYTE)(CheckSumTmp & 0x00FF);
+
+ if ((CheckSumHigh == IOMapComm.BtInBuf.Buf[IOMapComm.BtInBuf.Buf[0] - 1]) && (CheckSumLow == IOMapComm.BtInBuf.Buf[IOMapComm.BtInBuf.Buf[0]]))
+ {
+ return(TRUE);
+ }
+ else
+ {
+ return(FALSE);
+ }
+}
+
+void cCommClearStreamStatus(void)
+{
+ IOMapComm.BtConnectTable[0].StreamStatus = 0;
+ IOMapComm.BtConnectTable[1].StreamStatus = 0;
+ IOMapComm.BtConnectTable[2].StreamStatus = 0;
+ IOMapComm.BtConnectTable[3].StreamStatus = 0;
+}
+
+void cCommUpdateBt(void)
+{
+ UBYTE Tmp, Tmp2, Handle;
+
+ Tmp = 0;
+ Tmp2 = 0;
+
+ switch(VarsComm.ActiveUpdate)
+ {
+ case UPD_RESET:
+ {
+
+ switch(VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ /* Setup Reset sequence */
+ pMapUi->BluetoothState = BT_STATE_OFF;
+ VarsComm.UpdateState = 1;
+ }
+ break;
+
+ case 1:
+ {
+ cCommsBtReset(&(VarsComm.UpdateState));
+ }
+ break;
+
+ case 2:
+ {
+ (VarsComm.UpdateState)++;
+ dBtSendBtCmd((UBYTE)MSG_GET_LOCAL_ADDR, 0, 0, NULL, NULL, NULL, NULL);
+ }
+ break;
+
+ case 3:
+ {
+ if (MSG_GET_LOCAL_ADDR_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ cCommCopyBdaddr((IOMapComm.BrickData.BdAddr), &(IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1]));
+ dUsbStoreBtAddress( &(IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1]));
+ dBtSendBtCmd((UBYTE)MSG_GET_FRIENDLY_NAME, 0, 0, NULL, NULL, NULL, NULL);
+ VarsComm.BtAdrStatus = INITIALIZED;
+ (VarsComm.UpdateState)++;
+ }
+ }
+ break;
+
+ case 4:
+ {
+ if (MSG_GET_FRIENDLY_NAME_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ memcpy(IOMapComm.BrickData.Name, &(IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1]), SIZE_OF_BRICK_NAME);
+ pMapUi->Flags |= UI_REDRAW_STATUS;
+ IOMapComm.BtDeviceCnt = 0;
+ IOMapComm.BtDeviceNameCnt = 0;
+ dBtSendBtCmd((UBYTE)MSG_DUMP_LIST, 0, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ }
+ break;
+
+ case 5:
+ {
+ if (MSG_LIST_ITEM == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ cCommCopyBdaddr((IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].BdAddr), &(IOMapComm.BtInBuf.Buf[2]));
+ cCommInsertBtName(IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].Name, &(IOMapComm.BtInBuf.Buf[9]));
+ IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].DeviceStatus = BT_DEVICE_KNOWN;
+
+ memcpy(IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].ClassOfDevice, &(IOMapComm.BtInBuf.Buf[9+SIZE_OF_BT_NAME]), sizeof(IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].ClassOfDevice));
+
+ IOMapComm.BtDeviceCnt++;
+ IOMapComm.BtDeviceNameCnt++;
+ }
+
+ if (MSG_LIST_DUMP_STOPPED == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ dBtSendBtCmd((UBYTE)MSG_GET_VERSION, 0, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ IOMapComm.BtInBuf.Buf[BT_CMD_BYTE] = 0;
+ }
+ break;
+
+ case 6:
+ {
+ if (MSG_GET_VERSION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ IOMapComm.BrickData.BluecoreVersion[0] = IOMapComm.BtInBuf.Buf[3];
+ IOMapComm.BrickData.BluecoreVersion[1] = IOMapComm.BtInBuf.Buf[2];
+
+ /* BtHwStatus indicates cold boot or user interaction */
+ if (BT_DISABLE == IOMapComm.BrickData.BtHwStatus)
+ {
+
+ /* This is from brick turning on */
+ dBtSendBtCmd((UBYTE)MSG_GET_BRICK_STATUSBYTE, 0, 0, NULL, NULL, NULL, NULL);
+ }
+ else
+ {
+
+ /* this is user interaction setting the brick on */
+ dBtSendBtCmd((UBYTE)MSG_SET_BRICK_STATUSBYTE, BT_ENABLE, 0, NULL, NULL, NULL, NULL);
+ }
+ (VarsComm.UpdateState)++;
+ pMapUi->Flags |= UI_REDRAW_STATUS;
+ }
+ }
+ break;
+
+ case 7:
+ {
+ if (MSG_GET_BRICK_STATUSBYTE_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ IOMapComm.BrickData.TimeOutValue = IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 2];
+
+ /* Check for brick to be on or off */
+ if (BT_ENABLE == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1])
+ {
+ pMapUi->BluetoothState &= ~BT_STATE_OFF;
+ IOMapComm.BrickData.BtHwStatus = BT_ENABLE;
+ dBtSendBtCmd((UBYTE)MSG_GET_DISCOVERABLE, 0, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+ SETBtOff;
+ IOMapComm.BrickData.BtHwStatus = BT_ENABLE;
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = SUCCESS;
+ }
+ }
+ if (MSG_SET_BRICK_STATUSBYTE_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ /* brick to be on*/
+ pMapUi->BluetoothState &= ~BT_STATE_OFF;
+ IOMapComm.BrickData.BtHwStatus = BT_ENABLE;
+ dBtSendBtCmd((UBYTE)MSG_GET_DISCOVERABLE, 0, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ }
+ break;
+
+ case 8:
+ {
+ if (MSG_GET_DISCOVERABLE_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ if (IOMapComm.BtInBuf.Buf[2] & 0x01)
+ {
+ IOMapComm.BrickData.BtStateStatus |= BT_BRICK_VISIBILITY;
+ pMapUi->BluetoothState |= BT_STATE_VISIBLE;
+ }
+ else
+ {
+ IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_VISIBILITY;
+ pMapUi->BluetoothState &= ~BT_STATE_VISIBLE;
+ }
+ dBtSendBtCmd((UBYTE)MSG_OPEN_PORT, 0, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ }
+ break;
+
+ case 9:
+ {
+
+ if (MSG_PORT_OPEN_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ if (IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1] & 0x01)
+ {
+ IOMapComm.BrickData.BtStateStatus |= BT_BRICK_PORT_OPEN;
+ }
+ else
+ {
+ IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_PORT_OPEN;
+ }
+
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = SUCCESS;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_FACTORYRESET:
+ {
+ switch(VarsComm.UpdateState)
+ {
+
+ case 0:
+ {
+ if (BT_STATE_OFF & (pMapUi->BluetoothState))
+ {
+
+ /* Bluetooth is off - now start it up */
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+
+ /* BT is already on - continue */
+ (VarsComm.UpdateState) += 2;
+ }
+ }
+ break;
+ case 1:
+ {
+ cCommsBtReset(&(VarsComm.UpdateState));
+ }
+ break;
+ case 2:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+ case 3:
+ {
+ cCommsDisconnectAll(&(VarsComm.UpdateState));
+ }
+ break;
+ case 4:
+ {
+
+ /* Now bc4 is in cmd mode now factory can be sent */
+ /* Just leave the BC4 in cmd mode */
+ dBtSendBtCmd((UBYTE)MSG_SET_FACTORY_SETTINGS, 0, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ break;
+ case 5:
+ {
+ if (MSG_SET_FACTORY_SETTINGS_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ SETBtStateIdle;
+ IOMapComm.BrickData.BtHwStatus = BT_DISABLE; /* Boot BT like cold boot*/
+ VarsComm.ActiveUpdate = UPD_RESET;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_BRICKNAME:
+ {
+ switch(VarsComm.UpdateState)
+ {
+ case 0:
+ {
+
+ if (BT_STATE_OFF & (pMapUi->BluetoothState))
+ {
+
+ /* Bluetooth is off - now start it up */
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+ VarsComm.UpdateState = 2;
+ }
+ }
+ break;
+
+ case 1:
+ {
+ cCommsBtReset(&(VarsComm.UpdateState));
+ }
+ break;
+
+ case 2:
+ {
+ VarsComm.BtUpdateDataConnectNr = 0;
+ if (BT_ARM_DATA_MODE == VarsComm.BtState)
+ {
+ for (Tmp = 0; Tmp < SIZE_OF_BT_CONNECT_TABLE; Tmp++)
+ {
+ if (IOMapComm.BtConnectTable[Tmp].StreamStatus)
+ {
+ VarsComm.BtUpdateDataConnectNr = Tmp | 0x80;
+ }
+ }
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+ (VarsComm.UpdateState) += 2;
+ }
+ }
+ break;
+
+ case 3:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+
+ case 4:
+ {
+
+ /* Brick name has been updated prior to this */
+ dBtSendBtCmd((UBYTE)MSG_SET_FRIENDLY_NAME, 0, 0, NULL, IOMapComm.BrickData.Name, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ break;
+
+ case 5:
+ {
+ if (MSG_SET_FRIENDLY_NAME_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ /* Set name has been executed */
+ if (VarsComm.BtUpdateDataConnectNr & 0x80)
+ {
+ dBtSendBtCmd((UBYTE)MSG_OPEN_STREAM, IOMapComm.BtConnectTable[(VarsComm.BtUpdateDataConnectNr & ~0x80)].HandleNr,
+ 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+ if (BT_STATE_OFF & (pMapUi->BluetoothState))
+ {
+ SETBtOff;
+ }
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = SUCCESS;
+ }
+ pMapUi->Flags |= UI_REDRAW_STATUS;
+ }
+ }
+ break;
+ case 6:
+ {
+ if (VarsComm.BtBcPinLevel)
+ {
+ IOMapComm.BtConnectTable[(VarsComm.BtUpdateDataConnectNr & ~0x80)].StreamStatus = 1;
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtDataState;
+ SETBtStateIdle;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_REQCMDMODE:
+ {
+ switch(VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+ case 1:
+ {
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_OPENSTREAM:
+ {
+ switch(VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsOpenStream(&(VarsComm.UpdateState));
+ }
+ break;
+
+ case 1:
+ {
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_SENDFILE:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsOpenStream(&(VarsComm.UpdateState));
+ }
+ break;
+
+ case 1:
+ {
+
+ /* Here we wait for the open stream to succeed*/
+ if (IOMapComm.BtConnectTable[VarsComm.ExtTx.SlotNo].StreamStatus)
+ {
+
+ /* Stream has been opened send the openwrite command */
+ VarsComm.BtModuleOutBuf.Buf[0] = SYSTEM_CMD;
+ VarsComm.BtModuleOutBuf.Buf[1] = OPENWRITE;
+ memcpy((UBYTE*)&(VarsComm.BtModuleOutBuf.Buf[2]),(UBYTE*)VarsComm.ExtTx.FileName, FILENAME_LENGTH + 1);
+ memcpy((UBYTE*)&(VarsComm.BtModuleOutBuf.Buf[22]),(UBYTE*)&(VarsComm.ExtTx.RemFileSize), sizeof(VarsComm.ExtTx.RemFileSize));
+ dBtSendMsg(VarsComm.BtModuleOutBuf.Buf, 26, 26);
+
+ VarsComm.ExtTx.Timer = 0;
+ VarsComm.UpdateState = 2;
+
+ }
+ else
+ {
+ if (VarsComm.ExtTx.Timer >= FILETXTOUT)
+ {
+ *(VarsComm.pRetVal) = FILETX_STREAMERROR;
+ VarsComm.UpdateState = 8;
+ }
+ else
+ {
+ (VarsComm.ExtTx.Timer)++;
+ }
+ }
+ }
+ break;
+
+ case 2:
+ {
+
+ if (4 == IOMapComm.BtInBuf.InPtr)
+ {
+
+ /* Data has been received - examine the answer */
+ if ((REPLY_CMD == IOMapComm.BtInBuf.Buf[0]) && (OPENWRITE == IOMapComm.BtInBuf.Buf[1]))
+ {
+
+ /* OpenWrite answer */
+ if (LOADER_ERR_BYTE(SUCCESS) == IOMapComm.BtInBuf.Buf[2])
+ {
+
+ /* save the handle from the other brick */
+ VarsComm.ExtTx.DstHandle = IOMapComm.BtInBuf.Buf[3];
+ VarsComm.UpdateState = 3;
+ IOMapComm.BtInBuf.InPtr = 0;
+ }
+ else
+ {
+
+ /* Open write failiure - terminate file transfer */
+ *(VarsComm.pRetVal) = IOMapComm.BtInBuf.Buf[2];
+ VarsComm.UpdateState = 8;
+ }
+ }
+ }
+
+ if (VarsComm.ExtTx.Timer >= FILETXTOUT)
+ {
+ *(VarsComm.pRetVal) = FILETX_TIMEOUT;
+ VarsComm.UpdateState = 8;
+ }
+ else
+ {
+ (VarsComm.ExtTx.Timer)++;
+ }
+ }
+ break;
+
+ case 3: /*SENDWRITE:*/
+ {
+ ULONG Length;
+ UWORD MsgSize;
+
+ VarsComm.ExtTx.Timer = 0;
+
+ if (VarsComm.ExtTx.RemFileSize > (MAX_BT_MSG_SIZE - 5))
+ {
+
+ /* need to use the maximum size available - approx 64K */
+ VarsComm.ExtTx.RemMsgSize = (MAX_BT_MSG_SIZE - 5);
+ }
+ else
+ {
+
+ /* Message can hold the remaining message */
+ VarsComm.ExtTx.RemMsgSize = VarsComm.ExtTx.RemFileSize;
+ }
+
+ if (VarsComm.ExtTx.RemMsgSize > (SIZE_OF_BTBUF - 5))
+ {
+ Length = SIZE_OF_BTBUF - 5;
+ VarsComm.UpdateState = 4;
+ }
+ else
+ {
+ Length = VarsComm.ExtTx.RemMsgSize;
+ VarsComm.UpdateState = 5;
+ }
+
+ Handle = (UBYTE)(VarsComm.ExtTx.SrcHandle);
+ pMapLoader->pFunc(READ, &Handle, &(VarsComm.BtModuleOutBuf.Buf[3]), &Length);
+ MsgSize = VarsComm.ExtTx.RemMsgSize + 3;
+ VarsComm.BtModuleOutBuf.Buf[0] = SYSTEM_CMD;
+ VarsComm.BtModuleOutBuf.Buf[1] = WRITE;
+ VarsComm.BtModuleOutBuf.Buf[2] = VarsComm.ExtTx.DstHandle;
+ dBtSendMsg(VarsComm.BtModuleOutBuf.Buf, Length + 3, MsgSize);
+
+ VarsComm.ExtTx.RemMsgSize -= Length;
+ VarsComm.ExtTx.RemFileSize -= Length;
+ }
+ break;
+
+ case 4: /* CONTINOUSWRITE:*/
+ {
+ ULONG Length;
+ UWORD Status;
+
+ if(dBtCheckForTxBuf())
+ {
+
+ /* do only send more data if buffer is empty */
+ VarsComm.ExtTx.Timer = 0;
+ if (VarsComm.ExtTx.RemMsgSize >= SIZE_OF_BTBUF)
+ {
+ Length = SIZE_OF_BTBUF;
+ }
+ else
+ {
+ Length = VarsComm.ExtTx.RemMsgSize;
+ }
+
+ VarsComm.ExtTx.RemMsgSize -= Length;
+ VarsComm.ExtTx.RemFileSize -= Length;
+ Handle = (UBYTE)(VarsComm.ExtTx.SrcHandle);
+ Status = pMapLoader->pFunc(READ, &Handle, &(VarsComm.BtModuleOutBuf.Buf[0]), &Length);
+ if (Status >= 0x8000)
+ {
+ Length = 0;
+ }
+ dBtSend(VarsComm.BtModuleOutBuf.Buf, Length);
+ if (!(VarsComm.ExtTx.RemMsgSize))
+ {
+
+ /* at this point due to large write command acknowledge is expected */
+ VarsComm.UpdateState = 5;
+ VarsComm.ExtTx.Timer = 0;
+ IOMapComm.BtInBuf.InPtr = 0;
+ }
+ }
+ }
+ break;
+
+ case 5: /* WRITEACK: */
+ {
+ if (6 == IOMapComm.BtInBuf.InPtr)
+ {
+ if ((WRITE == IOMapComm.BtInBuf.Buf[1]) &&
+ (REPLY_CMD == IOMapComm.BtInBuf.Buf[0]) &&
+ (VarsComm.ExtTx.DstHandle == IOMapComm.BtInBuf.Buf[3]))
+ {
+
+ /* Ok the the return reply is for me - was it ok? */
+ if (LOADER_ERR_BYTE(SUCCESS) == IOMapComm.BtInBuf.Buf[2])
+ {
+
+ /* Ok send next write*/
+ if (VarsComm.ExtTx.RemFileSize)
+ {
+ VarsComm.UpdateState = 3;
+ }
+ else
+ {
+ VarsComm.UpdateState = 6;
+ }
+ IOMapComm.BtInBuf.InPtr = 0;
+ }
+ }
+ }
+
+ if (VarsComm.ExtTx.Timer >= FILETXTOUT)
+ {
+ *(VarsComm.pRetVal) = FILETX_TIMEOUT;
+ VarsComm.UpdateState = 8;
+ }
+ else
+ {
+ (VarsComm.ExtTx.Timer)++;
+ }
+ }
+ break;
+
+ case 6: /*TERMINATESEND: */
+ {
+
+ /* Stream still open close the receiver handle */
+ VarsComm.BtModuleOutBuf.Buf[0] = SYSTEM_CMD;
+ VarsComm.BtModuleOutBuf.Buf[1] = CLOSE;
+ VarsComm.BtModuleOutBuf.Buf[2] = VarsComm.ExtTx.DstHandle;
+ dBtSendMsg(VarsComm.BtModuleOutBuf.Buf, 3, 3);
+
+ VarsComm.ExtTx.Timer = 0;
+ VarsComm.UpdateState = 7;
+ }
+ break;
+ case 7: /* TERMINATEACK:*/
+ {
+
+ if (4 == IOMapComm.BtInBuf.InPtr)
+ {
+
+ if ((CLOSE == IOMapComm.BtInBuf.Buf[1]) &&
+ (REPLY_CMD == IOMapComm.BtInBuf.Buf[0]) &&
+ (VarsComm.ExtTx.DstHandle == IOMapComm.BtInBuf.Buf[3]))
+ {
+ if (LOADER_ERR_BYTE(SUCCESS) == IOMapComm.BtInBuf.Buf[2])
+ {
+ *(VarsComm.pRetVal) = SUCCESS;
+ VarsComm.UpdateState = 8;
+ }
+ else
+ {
+ *(VarsComm.pRetVal) = FILETX_CLOSEERROR;
+ VarsComm.UpdateState = 8;
+ }
+ IOMapComm.BtInBuf.InPtr = 0;
+ }
+ }
+
+ if (VarsComm.ExtTx.Timer >= FILETXTOUT)
+ {
+ *(VarsComm.pRetVal) = FILETX_TIMEOUT;
+ VarsComm.UpdateState = 8;
+ }
+ else
+ {
+ (VarsComm.ExtTx.Timer)++;
+ }
+ }
+ break;
+ case 8:
+ {
+ UBYTE Handle;
+ Handle = (UBYTE)(VarsComm.ExtTx.SrcHandle);
+ pMapLoader->pFunc(CLOSE, &Handle, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ break;
+ case 9:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+ case 10:
+ {
+ SETBtStateIdle;
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_EXTREAD:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ ULONG MsgLength;
+ UWORD Status;
+
+ MsgLength = (SIZE_OF_BTBUF - 8);
+ Handle =(UBYTE)(VarsComm.ExtTx.SrcHandle);
+ Status = pMapLoader->pFunc(READ, &Handle, &(VarsComm.BtModuleOutBuf.Buf[6]), &MsgLength);
+ VarsComm.BtModuleOutBuf.Buf[0] = (UBYTE) (REPLY_CMD);
+ VarsComm.BtModuleOutBuf.Buf[1] = (UBYTE) (VarsComm.ExtTx.Cmd);
+ VarsComm.BtModuleOutBuf.Buf[2] = LOADER_ERR_BYTE(Status);
+ VarsComm.BtModuleOutBuf.Buf[3] = LOADER_HANDLE(Status);
+ VarsComm.BtModuleOutBuf.Buf[4] = (UBYTE)VarsComm.ExtTx.RemMsgSize;
+ VarsComm.BtModuleOutBuf.Buf[5] = (UBYTE)(VarsComm.ExtTx.RemMsgSize >> 8);
+ dBtSendMsg(VarsComm.BtModuleOutBuf.Buf, (UBYTE)(SIZE_OF_BTBUF - 2), (VarsComm.ExtTx.RemMsgSize + 6));
+
+ VarsComm.ExtTx.RemMsgSize -= (SIZE_OF_BTBUF - 8);
+ VarsComm.UpdateState = 1;
+ }
+ break;
+
+ case 1:
+ {
+
+ ULONG Length;
+
+ if(dBtCheckForTxBuf())
+ {
+ if (VarsComm.ExtTx.RemMsgSize > (SIZE_OF_BTBUF))
+ {
+
+ /* Send max number of bytes */
+ VarsComm.ExtTx.RemMsgSize -= SIZE_OF_BTBUF;
+ Length = SIZE_OF_BTBUF;
+ }
+ else
+ {
+
+ /* Buffer can hold the last part of the requested data */
+ Length = VarsComm.ExtTx.RemMsgSize;
+ VarsComm.ExtTx.RemMsgSize = 0;
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ Handle =(UBYTE)(VarsComm.ExtTx.SrcHandle);
+ pMapLoader->pFunc(READ, &Handle, (VarsComm.BtModuleOutBuf.Buf), &Length);
+ dBtSend(VarsComm.BtModuleOutBuf.Buf, Length);
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_SEARCH:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+ case 1:
+ {
+ cCommsCloseConn0(&(VarsComm.UpdateState));
+ }
+ break;
+ case 2:
+ {
+
+ /* Now ready for the actual search */
+ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++)
+ {
+ if ((IOMapComm.BtDeviceTable[Tmp].DeviceStatus) & BT_DEVICE_KNOWN)
+ {
+ (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) = (BT_DEVICE_AWAY | BT_DEVICE_KNOWN);
+ }
+ else
+ {
+ IOMapComm.BtDeviceTable[Tmp].DeviceStatus = BT_DEVICE_EMPTY;
+ }
+ }
+ dBtSendBtCmd((UBYTE)MSG_BEGIN_INQUIRY, (UBYTE)BT_DEFAULT_INQUIRY_MAX,
+ BT_DEFAULT_INQUIRY_TIMEOUT_LO, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ break;
+ case 3:
+ {
+
+ /* this is the stop search flag */
+ /* - meaning that the search should be stopped */
+ if (1 == VarsComm.BtCmdData.ParamOne)
+ {
+ dBtSendBtCmd((UBYTE)MSG_CANCEL_INQUIRY, 0, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState) = 7;
+ }
+ else
+ {
+
+
+ /* when inquiry is running there is 2 alloable return answers */
+ /* either inquiry result or inquiry stopped */
+ if (MSG_INQUIRY_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ dBtResetTimeOut(); /* reset the cmd timeout */
+ Tmp = cCommInsertDevice(&(IOMapComm.BtInBuf.Buf[2]), &(IOMapComm.BtInBuf.Buf[9]),
+ &(IOMapComm.BtInBuf.Buf[25]), (UBYTE) BT_DEVICE_UNKNOWN, &Tmp2);
+ if (SIZE_OF_BT_DEVICE_TABLE > Tmp)
+ {
+
+ /* Remember to check for already existing entry ....*/
+ if (DEVICE_VERIFIED != Tmp2)
+ {
+ (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) &= ~BT_DEVICE_AWAY;
+ IOMapComm.BtDeviceCnt++;
+ }
+ }
+ else
+ {
+
+ /* We will send a stop inquiry cmd as the table is full! */
+ dBtSendBtCmd((UBYTE)MSG_CANCEL_INQUIRY, 0, 0, NULL, NULL, NULL, NULL);
+ }
+ }
+
+ if (MSG_INQUIRY_STOPPED == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ VarsComm.BtDeviceIndex = 0; /* Start looking for found devices at index 0 */
+ VarsComm.LookUpCnt = 0; /* how many times should we try to ask for the name */
+ (VarsComm.UpdateState)++;
+ }
+ }
+ IOMapComm.BtInBuf.Buf[BT_CMD_BYTE] = 0;
+ }
+ break;
+
+ case 4:
+ {
+
+ /* this is the stop search flag */
+ /* - meaning that the search should be stopped */
+ if (1 == VarsComm.BtCmdData.ParamOne)
+ {
+ (VarsComm.UpdateState) = 8;
+ }
+ else
+ {
+
+ /* Needs to run through the hole list as found devices can be placed anywhere */
+ /* in the table */
+ for (Tmp = (VarsComm.BtDeviceIndex); Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++)
+ {
+ if ((BT_DEVICE_UNKNOWN == IOMapComm.BtDeviceTable[Tmp].DeviceStatus) ||
+ (BT_DEVICE_KNOWN == IOMapComm.BtDeviceTable[Tmp].DeviceStatus))
+ {
+ VarsComm.BtDeviceIndex = (Tmp + 1);
+ (VarsComm.UpdateState)++;
+ dBtSendBtCmd((UBYTE)MSG_LOOKUP_NAME, 0, 0, (IOMapComm.BtDeviceTable[Tmp].BdAddr),
+ NULL, NULL, NULL);
+ break;
+ }
+ }
+ if (SIZE_OF_BT_DEVICE_TABLE == Tmp)
+ {
+ (VarsComm.LookUpCnt)++;
+ if (((VarsComm.LookUpCnt) < LOOKUPNO) && ((IOMapComm.BtDeviceNameCnt) != (IOMapComm.BtDeviceCnt)))
+ {
+ VarsComm.BtDeviceIndex = 0;
+ }
+ else
+ {
+
+ // all done
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = SUCCESS;
+ }
+ }
+ }
+ }
+ break;
+
+ case 5:
+ {
+
+ if (MSG_LOOKUP_NAME_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ Tmp2 = FALSE; /* Tmp2 used to indicate name change */
+ (IOMapComm.BtDeviceNameCnt)++;
+
+ /* Try look the most obvious place in the device table */
+ Tmp = VarsComm.BtDeviceIndex - 1;
+ if (TRUE != cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), &(IOMapComm.BtInBuf.Buf[2])))
+ {
+
+ /* there was no match - now look the complete table */
+ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++)
+ {
+ if (TRUE == cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), &(IOMapComm.BtInBuf.Buf[2])))
+ {
+ break;
+ }
+ }
+ }
+
+ if (Tmp < SIZE_OF_BT_DEVICE_TABLE)
+ {
+
+ /* Valid index with matching device adress found */
+ if (0 == IOMapComm.BtInBuf.Buf[9])
+ {
+
+ if (0 == IOMapComm.BtDeviceTable[Tmp].Name[0])
+ {
+
+ /* No valid name recvd and no valid name in table -> insert "No Name" */
+ cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, (UBYTE*)NoName);
+ }
+ }
+ else
+ {
+
+ /* Valid Name - check it against the one allready stored in the device table */
+ /* if it differs then update */
+ if (0 != strcmp((char const*)IOMapComm.BtDeviceTable[Tmp].Name, (char const*)&(IOMapComm.BtInBuf.Buf[9])))
+ {
+ cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, &(IOMapComm.BtInBuf.Buf[9]));
+ Tmp2 = TRUE;
+ }
+ }
+ if ((BT_DEVICE_KNOWN == (IOMapComm.BtDeviceTable[Tmp].DeviceStatus)) && (TRUE == Tmp2))
+ {
+ dBtSendBtCmd((UBYTE)MSG_ADD_DEVICE, 0, 0, (IOMapComm.BtDeviceTable[Tmp].BdAddr),
+ (IOMapComm.BtDeviceTable[Tmp].Name), (IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), NULL);
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+ (VarsComm.UpdateState)--;
+ }
+ }
+
+ /* Update devicestatus (name found) so it doesn't look up the name anymore */
+ IOMapComm.BtDeviceTable[Tmp].DeviceStatus |= BT_DEVICE_NAME;
+ }
+
+ if (MSG_LOOKUP_NAME_FAILURE == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ if ((LOOKUPNO - 1) == VarsComm.LookUpCnt)
+ {
+
+ /* This is the last time we ask this device -> we will not get a valid name */
+ /* Try look the most obvious place in the device table */
+ Tmp = VarsComm.BtDeviceIndex - 1;
+ if (TRUE != cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), &(IOMapComm.BtInBuf.Buf[2])))
+ {
+ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++)
+ {
+ if (TRUE == cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), &(IOMapComm.BtInBuf.Buf[2])))
+ {
+ break;
+ }
+ }
+ if ((Tmp < SIZE_OF_BT_DEVICE_TABLE) && (BT_DEVICE_UNKNOWN == (IOMapComm.BtDeviceTable[Tmp].DeviceStatus)))
+ {
+ cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, (UBYTE*) NoName);
+ }
+ }
+ (IOMapComm.BtDeviceNameCnt)++;
+ }
+ (VarsComm.UpdateState)--;
+ }
+ IOMapComm.BtInBuf.Buf[BT_CMD_BYTE] = 0;
+ }
+ break;
+
+ case 6:
+ {
+
+ /* Waiting for reply on add device command - List result */
+ if (MSG_LIST_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ if (LR_SUCCESS == IOMapComm.BtInBuf.Buf[2])
+ {
+
+ /* Return and go through the list*/
+ (VarsComm.UpdateState) -= 2;
+ }
+ else
+ {
+ pMapUi->Error = (UBYTE)IOMapComm.BtInBuf.Buf[2];
+ pMapUi->BluetoothState |= BT_ERROR_ATTENTION;
+ }
+ }
+ }
+ break;
+ case 7:
+ {
+
+ /* here because search has been stopped by user during inquiry */
+ if (MSG_INQUIRY_STOPPED == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ /* table should be cleared as no names hes been inquired */
+ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++)
+ {
+ if ((IOMapComm.BtDeviceTable[Tmp].DeviceStatus) & BT_DEVICE_KNOWN)
+ {
+ (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) = BT_DEVICE_KNOWN;
+ }
+ else
+ {
+ (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) = BT_DEVICE_EMPTY;
+ }
+ IOMapComm.BtDeviceCnt = 0;
+ IOMapComm.BtDeviceNameCnt = 0;
+ }
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = SUCCESS;
+ }
+ }
+ break;
+ case 8:
+ {
+ for (Tmp = (VarsComm.BtDeviceIndex); Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++)
+ {
+ if (BT_DEVICE_UNKNOWN == IOMapComm.BtDeviceTable[Tmp].DeviceStatus)
+ {
+ IOMapComm.BtDeviceTable[Tmp].DeviceStatus = BT_DEVICE_EMPTY;
+ }
+ }
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = SUCCESS;
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_CONNECTREQ:
+ {
+ switch (VarsComm.UpdateState)
+ {
+
+ case 0:
+ {
+ dBtSendBtCmd((UBYTE)MSG_ACCEPT_CONNECTION, 1, 0, NULL, NULL, NULL, NULL);
+ cCommCopyBdaddr((IOMapComm.BtConnectTable[0].BdAddr), &(IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1]));
+ (VarsComm.UpdateState)++;
+ }
+ break;
+
+ case 1:
+ {
+ if (MSG_CONNECT_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ /* Check for successfull connection */
+ if (1 == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1])
+ {
+
+ /* Save the handle number and look up the name of the master */
+ IOMapComm.BtConnectTable[0].HandleNr = IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 2];
+ pMapUi->BluetoothState |= BT_STATE_CONNECTED;
+ dBtSendBtCmd((UBYTE)MSG_LOOKUP_NAME, 0, 0, (IOMapComm.BtConnectTable[0].BdAddr), NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+
+ /* Unsuccessful connection */
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = BTCONNECTFAIL;
+ }
+ }
+ }
+ break;
+
+ case 2:
+ {
+
+ /* a close connection can happen during connection sequence - if this */
+ /* occurs for connection 0 then abort the rest of the sequence - OxFF */
+ /* is unused handle */
+ if ((MSG_CLOSE_CONNECTION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) &&
+ (0xFF == IOMapComm.BtConnectTable[0].HandleNr))
+ {
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = BTCONNECTFAIL;
+ }
+ else
+ {
+
+ if (MSG_LOOKUP_NAME_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ Tmp = cCommInsertDevice(&(IOMapComm.BtInBuf.Buf[2]), &(IOMapComm.BtInBuf.Buf[9]),
+ &(IOMapComm.BtInBuf.Buf[25]), (UBYTE) BT_DEVICE_KNOWN, &Tmp2);
+
+ if (SIZE_OF_BT_DEVICE_TABLE > Tmp)
+ {
+
+ /* entry has been added or is allready existing in the devicetable */
+ cCommInsertBtName(IOMapComm.BtConnectTable[0].Name, &(IOMapComm.BtInBuf.Buf[9]));
+ cCommCopyBdaddr((IOMapComm.BtConnectTable[0].BdAddr), &(IOMapComm.BtInBuf.Buf[2]));
+ memcpy(IOMapComm.BtConnectTable[0].ClassOfDevice,
+ IOMapComm.BtDeviceTable[Tmp].ClassOfDevice, SIZE_OF_CLASS_OF_DEVICE);
+ dBtSendBtCmd((UBYTE)MSG_ADD_DEVICE, 0, 0, (IOMapComm.BtDeviceTable[Tmp].BdAddr),
+ (IOMapComm.BtDeviceTable[Tmp].Name), (IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), NULL);
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+
+ /* no room in the devicetable -> reject the request. Param2 is index in connect table */
+ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[0].HandleNr,
+ 0, NULL, NULL, NULL, NULL);
+ SETBtStateIdle;
+ *(VarsComm.pRetVal) = BTCONNECTFAIL;
+ }
+ }
+
+ if (MSG_LOOKUP_NAME_FAILURE == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ /* not able to get the name - disconnect*/
+ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[0].HandleNr,
+ 0, NULL, NULL, NULL, NULL);
+ *(VarsComm.pRetVal) = BTCONNECTFAIL;
+ SETBtStateIdle;
+ }
+ }
+ }
+ break;
+
+ case 3:
+ {
+ if (MSG_LIST_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ if (LR_SUCCESS == IOMapComm.BtInBuf.Buf[2])
+ {
+
+ /* All success - open stream (Data mode) */
+ dBtSendBtCmd((UBYTE)MSG_OPEN_STREAM, IOMapComm.BtConnectTable[0].HandleNr, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+
+ /* no room in the BC4 -> reject the request */
+ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[0].HandleNr,
+ 0, NULL, NULL, NULL, NULL);
+ *(VarsComm.pRetVal) = BTCONNECTFAIL;
+ SETBtStateIdle;
+ }
+ }
+ }
+ break;
+
+ case 4:
+ {
+ if (VarsComm.BtBcPinLevel)
+ {
+ IOMapComm.BtConnectTable[0].StreamStatus = 1;
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtDataState;
+ SETBtStateIdle;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_CONNECT:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+ case 1:
+ {
+ cCommsCloseConn0(&(VarsComm.UpdateState));
+ }
+ break;
+ case 2:
+ {
+ dBtSendBtCmd((UBYTE)MSG_CONNECT, 0, 0,
+ IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].BdAddr, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ break;
+
+ case 3:
+ {
+ if (MSG_CONNECT_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ if (IOMapComm.BtInBuf.Buf[2] == 1)
+ {
+
+ IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].HandleNr = IOMapComm.BtInBuf.Buf[3];
+ pMapUi->BluetoothState |= BT_STATE_CONNECTED;
+
+ //Now we need to copy the data to the connectiontable
+ memcpy((IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].BdAddr), (IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].BdAddr), SIZE_OF_BDADDR);
+ cCommInsertBtName(IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].Name, IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].Name);
+ memcpy((IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].ClassOfDevice),
+ (IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].ClassOfDevice), SIZE_OF_CLASS_OF_DEVICE);
+ IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].DeviceStatus = BT_DEVICE_KNOWN;
+
+ if (VarsComm.BtCmdData.ParamTwo == 1)
+ {
+ IOMapComm.BrickData.BtStateStatus |= BT_CONNECTION_1_ENABLE;
+ }
+ else
+ {
+ if (VarsComm.BtCmdData.ParamTwo == 2)
+ {
+ IOMapComm.BrickData.BtStateStatus |= BT_CONNECTION_2_ENABLE;
+ }
+ else
+ {
+ if (VarsComm.BtCmdData.ParamTwo == 3)
+ {
+ IOMapComm.BrickData.BtStateStatus |= BT_CONNECTION_3_ENABLE;
+ }
+ }
+ }
+ dBtSendBtCmd((UBYTE)MSG_ADD_DEVICE, 0, 0, (IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].BdAddr),
+ (IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].Name),
+ (IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].ClassOfDevice), NULL);
+ (VarsComm.UpdateState)+=3; /* skip the pin code part */
+ }
+ else
+ {
+
+ /* Connect request denied */
+ *(VarsComm.pRetVal) = BTCONNECTFAIL;
+ SETBtStateIdle;
+ }
+ }
+ if (MSG_REQUEST_PIN_CODE == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ *(VarsComm.pRetVal) = REQPIN;
+ VarsComm.pValidPinCode = NULL;
+ (VarsComm.UpdateState)++;
+ }
+ }
+ break;
+
+ case 4:
+ {
+ if (NULL != VarsComm.pValidPinCode)
+ {
+
+ memcpy((IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].PinCode),
+ VarsComm.pValidPinCode, SIZE_OF_BT_PINCODE);
+
+ dBtSendBtCmd((UBYTE)MSG_PIN_CODE, 0, 0, IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].BdAddr,
+ NULL, NULL, (VarsComm.pValidPinCode));
+ (VarsComm.UpdateState)++;
+ }
+ if (MSG_CONNECT_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ /* if no pin code has been accepted then timeout indicated */
+ /* by connect failiure - it can only be failiure here */
+ *(VarsComm.pRetVal) = BTCONNECTFAIL;
+ SETBtStateIdle;
+ }
+ }
+ break;
+
+ case 5:
+ {
+
+ if (MSG_CONNECT_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ /* Connect failiure can happen at any time */
+ *(VarsComm.pRetVal) = BTCONNECTFAIL;
+ SETBtStateIdle;
+ }
+ if (MSG_PIN_CODE_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ /* return back and wait for connect ack */
+ (VarsComm.UpdateState) = 3;
+ }
+ }
+ break;
+ case 6:
+ {
+ if (MSG_LIST_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_DISCONNECT:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+
+ case 1:
+ {
+ if (BLUETOOTH_HANDLE_UNDEFIEND != IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamOne].HandleNr)
+ {
+ VarsComm.BtCmdData.ParamOne = IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamOne].HandleNr;
+ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, VarsComm.BtCmdData.ParamOne, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ }
+ break;
+
+ case 2:
+ {
+
+ /* look for right message and right handle */
+ if ((MSG_CLOSE_CONNECTION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) &&
+ (VarsComm.BtCmdData.ParamOne == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 2]))
+ {
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ case UPD_DISCONNECTALL:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+ case 1:
+ {
+ cCommsDisconnectAll(&(VarsComm.UpdateState));
+ }
+ break;
+ case 2:
+ {
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ break;
+ }
+ }
+ break;
+ case UPD_REMOVEDEVICE:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+ case 1:
+ {
+ cCommsCloseConn0(&(VarsComm.UpdateState));
+ }
+ break;
+ case 2:
+ {
+ dBtSendBtCmd((UBYTE)MSG_REMOVE_DEVICE, 0, 0,
+ IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].BdAddr, NULL, NULL, NULL);
+ IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].DeviceStatus = BT_DEVICE_EMPTY;
+ (VarsComm.UpdateState)++;
+ }
+ break;
+ case 3:
+ {
+ if (MSG_LIST_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_PINREQ:
+ {
+
+ /* This is pincode request from the outside - always conn 0*/
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ if (NULL != VarsComm.pValidPinCode)
+ {
+ memcpy((IOMapComm.BtConnectTable[0].PinCode),
+ VarsComm.pValidPinCode, SIZE_OF_BT_PINCODE);
+ dBtSendBtCmd((UBYTE)MSG_PIN_CODE, 0, 0, (IOMapComm.BtConnectTable[0].BdAddr),
+ NULL, NULL, (VarsComm.pValidPinCode));
+ (VarsComm.UpdateState)++;
+ }
+ }
+ break;
+ case 1:
+ {
+ if (MSG_PIN_CODE_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ SETBtStateIdle;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_VISIBILITY:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+ case 1:
+ {
+ cCommsCloseConn0(&(VarsComm.UpdateState));
+ }
+ break;
+ case 2:
+ {
+ dBtSendBtCmd((UBYTE)MSG_SET_DISCOVERABLE, VarsComm.BtCmdData.ParamOne, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ break;
+ case 3:
+ {
+ if (MSG_DISCOVERABLE_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ if (VarsComm.BtCmdData.ParamOne == 1)
+ {
+ IOMapComm.BrickData.BtStateStatus |= BT_BRICK_VISIBILITY;
+ pMapUi->BluetoothState |= BT_STATE_VISIBLE;
+ }
+ else
+ {
+ IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_VISIBILITY;
+ pMapUi->BluetoothState &= ~BT_STATE_VISIBLE;
+ }
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case UPD_OFF:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ cCommsSetCmdMode(&(VarsComm.UpdateState));
+ }
+ break;
+ case 1:
+ {
+ cCommsDisconnectAll(&(VarsComm.UpdateState));
+ }
+ break;
+ case 2:
+ {
+ dBtSendBtCmd((UBYTE)MSG_SET_BRICK_STATUSBYTE, BT_DISABLE, 0, NULL, NULL, NULL, NULL);
+ (VarsComm.UpdateState)++;
+ }
+ break;
+ case 3:
+ {
+ if (MSG_SET_BRICK_STATUSBYTE_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ if (IOMapComm.BtInBuf.Buf[2] == LR_SUCCESS)
+ {
+ SETBtOff;
+ pMapUi->BluetoothState = BT_STATE_OFF;
+ pMapUi->Flags |= UI_REDRAW_STATUS;
+ }
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ case UPD_SENDDATA:
+ {
+ switch (VarsComm.UpdateState)
+ {
+ case 0:
+ {
+ if (1 == IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].StreamStatus)
+ {
+
+ /* Stream is allready open for the requested channel */
+ (VarsComm.UpdateState) += 2;
+ }
+ else
+ {
+
+ /* Stream not open - try open it*/
+ (VarsComm.UpdateState)++;
+ }
+ }
+ break;
+ case 1:
+ {
+ cCommsOpenStream(&(VarsComm.UpdateState));
+ }
+ break;
+ case 2:
+ {
+
+ /* Stream is now opened now send the data */
+ IOMapComm.BtInBuf.Buf[0] = 0;
+ dBtSendMsg((VarsComm.BtModuleOutBuf.Buf), VarsComm.BtCmdData.ParamOne, (UWORD)(VarsComm.BtCmdData.ParamOne));
+ (VarsComm.UpdateState)++;
+ }
+ break;
+ case 3:
+ {
+ if(dBtCheckForTxBuf())
+ {
+ if (VarsComm.BtCmdData.ParamThree)
+ {
+ VarsComm.ExtTx.Timer = 0;
+ (VarsComm.UpdateState)++;
+ }
+ else
+ {
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ }
+ }
+ break;
+ case 4:
+ {
+ if (0x02 == IOMapComm.BtInBuf.Buf[0])
+ {
+
+ /* a reply has been received now release the send sequence */
+ *(VarsComm.pRetVal) = SUCCESS;
+ SETBtStateIdle;
+ }
+ else
+ {
+ if (++VarsComm.ExtTx.Timer > BTSTREAMTOUT)
+ {
+ *(VarsComm.pRetVal) = BTTIMEOUT;
+ SETBtStateIdle;
+ }
+ }
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ {
+
+ /* This is idle */
+ VarsComm.UpdateState = 0;
+ }
+ break;
+ }
+}
+
+UWORD cCommCopyBdaddr(UBYTE *pDst, UBYTE *pSrc)
+{
+ memcpy(pDst, pSrc, SIZE_OF_BDADDR);
+ return((UWORD) SIZE_OF_BDADDR);
+}
+
+UWORD cCommCheckBdaddr(UBYTE *pAdr, UBYTE *pSrc)
+{
+ UWORD RetVal;
+
+ RetVal = FALSE;
+ if (0 == memcmp((UBYTE*)pAdr, pSrc, SIZE_OF_BDADDR))
+ {
+ RetVal = TRUE;
+ }
+ return(RetVal);
+}
+
+UWORD cCommInsertBtName(UBYTE *pDst, UBYTE *pSrc)
+{
+ UBYTE Cnt;
+
+ Cnt = 0;
+
+ /* Complete brick name */
+ while ((pSrc[Cnt]) && (Cnt < (SIZE_OF_BT_NAME - 1)))
+ {
+ pDst[Cnt] = pSrc[Cnt];
+ Cnt++;
+ }
+
+ /* Fill remaining up with zeros */
+ while (Cnt < SIZE_OF_BT_NAME)
+ {
+ pDst[Cnt] = 0;
+ Cnt++;
+ }
+
+ return((UWORD)SIZE_OF_BT_NAME);
+}
+
+
+UWORD cCommInsertDevice(UBYTE *pBdaddr, UBYTE *pName, UBYTE *pCod, UBYTE DeviceStatus, UBYTE *pAddInfo)
+{
+ UWORD Tmp;
+ UWORD RtnVal;
+
+ RtnVal = FALSE;
+ *pAddInfo = DEVICE_VERIFIED;
+ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++)
+ {
+ if ((TRUE == cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), pBdaddr)) &&
+ (IOMapComm.BtDeviceTable[Tmp].DeviceStatus != BT_DEVICE_EMPTY))
+ {
+
+ if ((IOMapComm.BtDeviceTable[Tmp].DeviceStatus) & BT_DEVICE_AWAY)
+ {
+ *pAddInfo = DEVICE_UPDATED;
+ (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) &= ~BT_DEVICE_AWAY;
+ }
+
+ if (BT_DEVICE_UNKNOWN == IOMapComm.BtDeviceTable[Tmp].DeviceStatus)
+ {
+
+ /* Former unknown adresses can be upgraded - downgrading is not possible */
+ IOMapComm.BtDeviceTable[Tmp].DeviceStatus = DeviceStatus;
+ }
+ if (pCod != NULL)
+ {
+
+ /* Class of device can also upgraded - never downgraded to 0 */
+ memcpy(&(IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), pCod, SIZE_OF_CLASS_OF_DEVICE);
+ }
+ if ((*pName) != 0)
+ {
+
+ /* Only upgrade name if name is received */
+ cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, pName);
+ }
+ RtnVal = TRUE;
+
+ /* Break out - entry can only be found once */
+ break;
+ }
+ }
+
+ if (FALSE == RtnVal)
+ {
+ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++)
+ {
+ if (IOMapComm.BtDeviceTable[Tmp].DeviceStatus == BT_DEVICE_EMPTY)
+ {
+ *pAddInfo = DEVICE_INSERTED;
+ IOMapComm.BtDeviceTable[Tmp].DeviceStatus = DeviceStatus;
+ cCommCopyBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), pBdaddr);
+ cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, pName);
+ if (NULL != pCod)
+ {
+ memcpy((IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), pCod, SIZE_OF_CLASS_OF_DEVICE);
+ }
+ else
+ {
+ memset((IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), 0, SIZE_OF_CLASS_OF_DEVICE);
+ }
+ RtnVal = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* Function returns SIZE_OF_BT_DEVICE_TABLE if device is not in the list */
+ return(Tmp);
+}
+
+void cCommsSetCmdMode(UBYTE *pNextState)
+{
+ switch(VarsComm.CmdSwitchCnt)
+ {
+ case 0:
+ {
+ if (BT_ARM_CMD_MODE != VarsComm.BtState)
+ {
+ cCommClearStreamStatus();
+ VarsComm.BtCmdModeWaitCnt = 0;
+ VarsComm.CmdSwitchCnt++;
+ }
+ else
+ {
+
+ /* allready in CMD mode - Exit */
+ VarsComm.CmdSwitchCnt = 0;
+ (*pNextState)++;
+ }
+ }
+ break;
+
+ case 1:
+ {
+
+ /* stream status has been cleared now wait until buffers has been emptied */
+ if (TRUE == dBtTxEnd())
+ {
+
+ /* Wait 100 ms after last byte has been sent to BC4 - else BC4 can crash */
+ if (++(VarsComm.BtCmdModeWaitCnt) > 100)
+ {
+ dBtClearArm7CmdSignal();
+ VarsComm.CmdSwitchCnt++;
+ }
+ }
+ }
+ break;
+
+ case 2:
+ {
+ if (VarsComm.BtBcPinLevel == 0)
+ {
+
+ /* Bluecore has entered cmd mode */
+ SETBtCmdState;
+ VarsComm.CmdSwitchCnt = 0;
+ (*pNextState)++;
+ }
+ }
+ break;
+
+ default:
+ {
+ VarsComm.CmdSwitchCnt = 0;
+ }
+ break;
+ }
+}
+
+void cCommsOpenStream(UBYTE *pNextState)
+{
+ switch(VarsComm.StreamStateCnt)
+ {
+ case 0:
+ {
+
+ if (SIZE_OF_BT_CONNECT_TABLE > VarsComm.BtCmdData.ParamTwo)
+ {
+
+ /* first check if there is a connection on the requested channel */
+ if ('\0' != IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].Name[0])
+ {
+
+ if (1 == IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].StreamStatus)
+ {
+
+ /* Stream is allready open - continue */
+ (*pNextState)++;
+ }
+ else
+ {
+
+ /* There is a connection on requested channel proceed */
+ VarsComm.StreamStateCnt = 1;
+ }
+ }
+ else
+ {
+
+ /* Error - no connecteion on requested channel - exit */
+ *(VarsComm.pRetVal) = (UWORD)ERR_COMM_CHAN_NOT_READY;
+ *(VarsComm.pRetVal) |= 0x8000;
+ SETBtStateIdle;
+ }
+ }
+ else
+ {
+
+ /* Error - Illegal channel no - exit */
+ *(VarsComm.pRetVal) = (UWORD)ERR_COMM_CHAN_INVALID;
+ *(VarsComm.pRetVal) |= 0x8000;
+ SETBtStateIdle;
+ }
+ }
+ break;
+
+ case 1:
+ {
+ cCommsSetCmdMode(&(VarsComm.StreamStateCnt));
+ }
+ break;
+
+ case 2:
+ {
+ cCommsCloseConn0(&(VarsComm.StreamStateCnt));
+ }
+ break;
+
+ case 3:
+ {
+
+ /* Open stream on the specified channel */
+ VarsComm.StreamStateCnt = 4;
+ dBtSendBtCmd((UBYTE)MSG_OPEN_STREAM, IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].HandleNr,
+ 0, NULL, NULL, NULL, NULL);
+ }
+ break;
+
+ case 4:
+ {
+ if (VarsComm.BtBcPinLevel)
+ {
+ SETBtDataState;
+ IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].StreamStatus = 1;
+ VarsComm.StreamStateCnt = 0;
+ (*pNextState)++;
+ }
+ }
+ break;
+
+ default:
+ {
+ VarsComm.StreamStateCnt = 0;
+ }
+ break;
+ }
+}
+
+void cCommsCloseConn0(UBYTE *pNextState)
+{
+ switch(VarsComm.CloseConn0Cnt)
+ {
+ case 0:
+ {
+ if ('\0' != IOMapComm.BtConnectTable[0].Name[0])
+ {
+
+ /* now disconnect channel 0 */
+ VarsComm.CloseConn0Cnt = 1;
+ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[0].HandleNr, 0, NULL, NULL, NULL, NULL);
+ }
+ else
+ {
+ (*pNextState)++;
+ }
+ }
+ break;
+ case 1:
+ {
+ if (MSG_CLOSE_CONNECTION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+ VarsComm.CloseConn0Cnt = 0;
+ (*pNextState)++;
+ }
+ }
+ break;
+ default:
+ {
+ VarsComm.CloseConn0Cnt = 0;
+ }
+ break;
+ }
+}
+
+void cCommsDisconnectAll(UBYTE *pNextState)
+{
+ switch(VarsComm.DiscAllCnt)
+ {
+ case 0:
+ {
+ VarsComm.BtCmdData.ParamOne = 0;
+ (VarsComm.DiscAllCnt)++;
+ }
+ break;
+ case 1:
+ {
+ while (('\0' == IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamOne].Name[0]) &&
+ (VarsComm.BtCmdData.ParamOne < 4))
+ {
+ VarsComm.BtCmdData.ParamOne++;
+ }
+ if (VarsComm.BtCmdData.ParamOne < 4)
+ {
+
+ /* now disconnect selected channel */
+ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamOne].HandleNr,
+ 0, NULL, NULL, NULL, NULL);
+ VarsComm.BtCmdData.ParamOne++;
+ (VarsComm.DiscAllCnt)++;
+ }
+ else
+ {
+
+ /* no more connections - move on */
+ (VarsComm.DiscAllCnt) = 0;
+ (*pNextState)++;
+ }
+ }
+ break;
+ case 2:
+ {
+ if (MSG_CLOSE_CONNECTION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])
+ {
+
+ /* Go back and check for more connections to close */
+ (VarsComm.DiscAllCnt)--;
+ }
+ }
+ break;
+ }
+}
+
+void cCommsBtReset(UBYTE *pNextState)
+{
+ switch(VarsComm.ResetBtCnt)
+ {
+ case 0:
+ {
+
+ /* Setup Reset sequence */
+ VarsComm.BtResetTimeCnt = 0;
+ VarsComm.ResetBtCnt = 1;
+ dBtSetBcResetPinLow();
+ }
+ break;
+ case 1:
+ {
+
+ /* Reset should be held low for a certain time "BLUECORE_RESET_TIME" */
+ VarsComm.BtResetTimeCnt++;
+ if (VarsComm.BtResetTimeCnt > BLUECORE_RESET_TIME)
+ {
+ dBtSetBcResetPinHigh();
+ VarsComm.BtWaitTimeCnt = 0;
+ VarsComm.ResetBtCnt = 2;
+ }
+ }
+ break;
+ case 2:
+ {
+
+ /* Wait after reset is released either wait a minimum time or wait for the reset indication telegram */
+ VarsComm.BtWaitTimeCnt++;
+ if ((VarsComm.BtWaitTimeCnt > BLUECORE_WAIT_BEFORE_INIT) || (MSG_RESET_INDICATION == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]))
+ {
+ memset(&(IOMapComm.BtDeviceTable), 0, sizeof(IOMapComm.BtDeviceTable));
+ cCommClrConnTable();
+ VarsComm.ResetBtCnt = 3;
+ }
+ }
+ break;
+
+ case 3:
+ {
+ SETBtCmdState;
+ VarsComm.ResetBtCnt = 0;
+ (*pNextState)++;
+ }
+ break;
+ }
+}
+
+
+UWORD cCommReq(UBYTE Cmd, UBYTE Param1, UBYTE Param2, UBYTE Param3, UBYTE *pName, UWORD *pRetVal)
+{
+ ULONG Length;
+ UWORD ReturnVal;
+
+ ReturnVal = BTBUSY;
+ *pRetVal = BTBUSY;
+ if ((UPD_IDLE == (VarsComm.ActiveUpdate)) || ((UPD_SEARCH == (VarsComm.ActiveUpdate)) && (STOPSEARCH == Cmd)))
+ {
+
+ ReturnVal = SUCCESS;
+ *pRetVal = INPROGRESS;
+ VarsComm.pRetVal = pRetVal;
+ switch(Cmd)
+ {
+ case SENDFILE:
+ {
+ ReturnVal = SUCCESS;
+
+ /* No file is currently beeing send - Now open the file */
+ VarsComm.ExtTx.SrcHandle = pMapLoader->pFunc(OPENREAD, pName, NULL, &Length);
+ VarsComm.ExtTx.RemFileSize = Length;
+ VarsComm.ExtTx.SlotNo = Param1;
+ VarsComm.BtCmdData.ParamTwo = Param1; /* This is used to open the correct stream */
+
+ if (0x8000 > VarsComm.ExtTx.SrcHandle)
+ {
+
+ /* Source file is ok - go ahead */
+ VarsComm.ActiveUpdate = UPD_SENDFILE;
+ VarsComm.ExtTx.Timer = 0;
+ VarsComm.ExtTx.Cmd = WRITE;
+ cCommCopyFileName(VarsComm.ExtTx.FileName, pName);
+ }
+ else
+ {
+
+ /* Error in opening source file for read - file do not exist */
+ ReturnVal = FILETX_SRCMISSING;
+ }
+ }
+ break;
+
+ case CONNECT:
+ {
+
+ if (BLUETOOTH_HANDLE_UNDEFIEND == IOMapComm.BtConnectTable[Param2].HandleNr)
+ {
+
+ /* Connection not occupied */
+ VarsComm.ActiveUpdate = UPD_CONNECT;
+ VarsComm.BtCmdData.ParamOne = Param1;
+ VarsComm.BtCmdData.ParamTwo = Param2;
+ }
+ else
+ {
+
+ /* Connection occupied */
+ ReturnVal = BTCONNECTFAIL;
+ *pRetVal = BTCONNECTFAIL;
+ }
+ }
+ break;
+
+ case DISCONNECT:
+ {
+ VarsComm.ActiveUpdate = UPD_DISCONNECT;
+ VarsComm.BtCmdData.ParamOne = Param1;
+ }
+ break;
+
+ case DISCONNECTALL:
+ {
+ VarsComm.ActiveUpdate = UPD_DISCONNECTALL;
+ }
+ break;
+
+ case SEARCH:
+ {
+ VarsComm.ActiveUpdate = UPD_SEARCH;
+ IOMapComm.BtDeviceNameCnt = 0;
+ IOMapComm.BtDeviceCnt = 0;
+ VarsComm.BtCmdData.ParamOne = 0;
+ }
+ break;
+ case STOPSEARCH:
+ {
+ if (UPD_SEARCH == (VarsComm.ActiveUpdate))
+ {
+ VarsComm.BtCmdData.ParamOne = 1;
+ }
+ else
+ {
+ *pRetVal = SUCCESS;
+ }
+ }
+ break;
+ case REMOVEDEVICE:
+ {
+ VarsComm.ActiveUpdate = UPD_REMOVEDEVICE;
+ VarsComm.BtCmdData.ParamOne = Param1;
+ }
+ break;
+ case VISIBILITY:
+ {
+ VarsComm.ActiveUpdate = UPD_VISIBILITY;
+ VarsComm.BtCmdData.ParamOne = Param1;
+ }
+ break;
+ case SETCMDMODE:
+ {
+ VarsComm.ActiveUpdate = UPD_REQCMDMODE;
+ }
+ break;
+ case FACTORYRESET:
+ {
+ VarsComm.ActiveUpdate = UPD_FACTORYRESET;
+ }
+ break;
+ case BTON:
+ {
+ if (BT_STATE_OFF & (pMapUi->BluetoothState))
+ {
+ VarsComm.ActiveUpdate = UPD_RESET;
+ }
+ else
+ {
+
+ /* Device is already on*/
+ *pRetVal = SUCCESS;
+ }
+ }
+ break;
+ case BTOFF:
+ {
+ VarsComm.ActiveUpdate = UPD_OFF;
+ }
+ break;
+ case SENDDATA:
+ {
+
+ /* Param2 indicates the port that the data should be */
+ /* be sent on - param1 indicates the number of data */
+ /* to be sent. pName is the pointer to the data */
+ if (Param1 <= sizeof(VarsComm.BtModuleOutBuf.Buf))
+ {
+ if ('\0' != IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].Name[0])
+ {
+ VarsComm.BtCmdData.ParamOne = Param1;
+ VarsComm.BtCmdData.ParamTwo = Param2;
+ VarsComm.BtCmdData.ParamThree = Param3;
+ memcpy((VarsComm.BtModuleOutBuf.Buf), pName, Param1);
+ VarsComm.ActiveUpdate = UPD_SENDDATA;
+ }
+ else
+ {
+ ReturnVal = (UWORD)ERR_COMM_CHAN_NOT_READY;
+ ReturnVal |= 0x8000;
+ }
+ }
+ else
+ {
+ ReturnVal = (UWORD)ERR_COMM_BUFFER_FULL;
+ ReturnVal |= 0x8000;
+ }
+ }
+ break;
+ case OPENSTREAM:
+ {
+ VarsComm.BtCmdData.ParamTwo = Param2;
+ VarsComm.ActiveUpdate = UPD_OPENSTREAM;
+ }
+ break;
+ case SETBTNAME:
+ {
+ VarsComm.ActiveUpdate = UPD_BRICKNAME;
+ }
+ break;
+ case EXTREAD:
+ {
+ VarsComm.ActiveUpdate = UPD_EXTREAD;
+ }
+ break;
+ case PINREQ:
+ {
+
+ /* This is an incomming pinrequest for connection on connection 0 because */
+ /* ActiveUpdate is idle (if it was incomming it is not idle) */
+ cCommCopyBdaddr((IOMapComm.BtConnectTable[0].BdAddr), &(IOMapComm.BtInBuf.Buf[2]));
+ pMapUi->BluetoothState |= (BT_CONNECT_REQUEST | BT_PIN_REQUEST);
+ VarsComm.pValidPinCode = NULL;
+ VarsComm.ActiveUpdate = UPD_PINREQ;
+ }
+ break;
+ case CONNECTREQ:
+ {
+ VarsComm.ActiveUpdate = UPD_CONNECTREQ;
+ }
+ break;
+ }
+ }
+ return(ReturnVal);
+}
+
+void cCommPinCode(UBYTE *pPinCode)
+{
+ VarsComm.pValidPinCode = pPinCode;
+ if (REQPIN == (*(VarsComm.pRetVal)))
+ {
+ *(VarsComm.pRetVal) = INPROGRESS;
+ }
+}
+
+void cCommClrConnTable(void)
+{
+ UBYTE Tmp;
+
+ for (Tmp = 0; Tmp < SIZE_OF_BT_CONNECT_TABLE; Tmp++)
+ {
+ CLEARConnEntry(Tmp);
+ }
+ IOMapComm.BrickData.BtStateStatus &= ~(BT_CONNECTION_0_ENABLE | BT_CONNECTION_1_ENABLE | BT_CONNECTION_2_ENABLE | BT_CONNECTION_3_ENABLE);
+ pMapUi->BluetoothState &= ~BT_STATE_CONNECTED;
+ pMapUi->Flags |= UI_REDRAW_STATUS;
+}
diff --git a/AT91SAM7S256/Source/c_comm.h b/AT91SAM7S256/Source/c_comm.h
new file mode 100644
index 0000000..8487a82
--- /dev/null
+++ b/AT91SAM7S256/Source/c_comm.h
@@ -0,0 +1,151 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:42 $
+//
+// Filename $Workfile:: c_comm.h $
+//
+// Version $Revision:: 54 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_comm.h $
+//
+// Platform C
+//
+
+#ifndef C_COMM
+#define C_COMM
+
+
+#define BLUECORE_RESET_TIME 100 // Time in mS
+#define BLUECORE_WAIT_BEFORE_INIT 5000 // Time in mS
+#define BLUETOOTH_HANDLE_UNDEFIEND 0xFF
+
+/* Constants related to BtAdrStatus*/
+enum
+{
+ COLDBOOT,
+ INITIALIZED,
+ BTADRERROR
+};
+
+
+enum
+{
+ USB_CH,
+ BT_CH,
+ HISPEED_CH,
+ NO_OF_CHANNELS
+};
+
+
+/* enum reffering to BT update */
+enum
+{
+ UPD_BRICKNAME,
+ UPD_FACTORYRESET,
+ UPD_OPENSTREAM,
+ UPD_REQCMDMODE,
+ UPD_CONNECT,
+ UPD_CONNECTREQ,
+ UPD_PINREQ,
+ UPD_DISCONNECT,
+ UPD_DISCONNECTALL,
+ UPD_REMOVEDEVICE,
+ UPD_SEARCH,
+ UPD_RESET,
+ UPD_EXTREAD,
+ UPD_SENDFILE,
+ UPD_OFF,
+ UPD_VISIBILITY,
+ UPD_SENDDATA,
+ UPD_IDLE
+};
+
+/* Constants reffering to Protocol */
+enum
+{
+ DIRECT_CMD = 0x00,
+ SYSTEM_CMD = 0x01,
+ REPLY_CMD = 0x02,
+ NO_REPLY_BIT = 0x80
+};
+
+typedef struct
+{
+ ULONG RemFileSize;
+ UWORD RemMsgSize;
+ UWORD SrcHandle;
+ UWORD DstHandle;
+ UWORD Timer;
+ UBYTE FileName[FILENAME_LENGTH + 1];
+ UBYTE Cmd;
+ UBYTE SlotNo;
+}EXTTX;
+
+typedef struct
+{
+ UBYTE Buf[256];
+ UWORD InPtr;
+ UWORD OutPtr;
+}BTDATA;
+
+typedef struct
+{
+ UBYTE Buf[256];
+ UWORD InPtr;
+ UWORD OutPtr;
+}HSDATA;
+
+typedef struct
+{
+ UBYTE Status;
+ UBYTE Type;
+ UBYTE Handle;
+ UBYTE Cmd;
+}EXTMODE;
+
+typedef struct
+{
+ UBYTE ParamOne;
+ UBYTE ParamTwo;
+ UBYTE ParamThree;
+}BTCMD;
+
+typedef struct
+{
+ UBYTE BtUpdateDataConnectNr;
+ UBYTE BtBcPinLevel;
+ UBYTE BtResetTimeCnt;
+ UWORD BtWaitTimeCnt;
+ BTDATA BtModuleInBuf;
+ BTDATA BtModuleOutBuf;
+ BTCMD BtCmdData;
+ UBYTE HsState;
+ HSDATA HsModuleInBuf;
+ HSDATA HsModuleOutBuf;
+ EXTTX ExtTx;
+ EXTMODE ExtMode[NO_OF_CHANNELS];
+ UBYTE ActiveUpdate;
+ UBYTE UpdateState;
+ UBYTE BtDeviceIndex;
+ UBYTE CmdSwitchCnt;
+ UBYTE StreamStateCnt;
+ UBYTE CloseConn0Cnt;
+ UBYTE DiscAllCnt;
+ UBYTE ResetBtCnt;
+ UBYTE BtState;
+ UWORD *pRetVal;
+ UWORD RetVal;
+ UBYTE *pValidPinCode;
+ UBYTE LookUpCnt;
+ UBYTE BtAdrStatus;
+ UBYTE BtCmdModeWaitCnt;
+}VARSCOMM;
+
+void cCommInit(void* pHeader);
+void cCommCtrl(void);
+void cCommExit(void);
+
+extern const HEADER cComm;
+
+#endif
diff --git a/AT91SAM7S256/Source/c_comm.iom b/AT91SAM7S256/Source/c_comm.iom
new file mode 100644
index 0000000..6a43149
--- /dev/null
+++ b/AT91SAM7S256/Source/c_comm.iom
@@ -0,0 +1,222 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:42 $
+//
+// Filename $Workfile:: c_comm.iom $
+//
+// Version $Revision:: 72 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_comm.iom $
+//
+// Platform C
+//
+
+#ifndef CCOMM_IOM
+#define CCOMM_IOM
+
+#define pMapComm ((IOMAPCOMM*)(pHeaders[ENTRY_COMM]->pIOMap))
+
+#define SIZE_OF_USBBUF 64
+#define USB_PROTOCOL_OVERHEAD 1 + 1 /* Command type byte + Command */
+#define SIZE_OF_USBDATA (SIZE_OF_USBBUF - USB_PROTOCOL_OVERHEAD)
+#define SIZE_OF_HSBUF 128
+#define SIZE_OF_BTBUF 128
+
+#define BT_CMD_BYTE 1
+#define SIZE_OF_BT_DEVICE_TABLE 30
+#define SIZE_OF_BT_CONNECT_TABLE 4 /* Index 0 is alway incomming connections */
+#define MAX_BT_MSG_SIZE 60000L
+
+#define BT_DEFAULT_INQUIRY_MAX 0 /* Unlimited no */
+#define BT_DEFAULT_INQUIRY_TIMEOUT_LO 15 /* 15 x 1,28 Sec = 19,2 Sec */
+
+
+// Constants reffering to BtState
+enum
+{
+ BT_ARM_OFF,
+ BT_ARM_CMD_MODE,
+ BT_ARM_DATA_MODE,
+};
+
+//Constant reffering to BtStateStatus
+#define BT_BRICK_VISIBILITY 0x01
+#define BT_BRICK_PORT_OPEN 0x02
+#define BT_CONNECTION_0_ENABLE 0x10
+#define BT_CONNECTION_1_ENABLE 0x20
+#define BT_CONNECTION_2_ENABLE 0x40
+#define BT_CONNECTION_3_ENABLE 0x80
+
+//Constant reffering to BtHwStatus
+#define BT_ENABLE 0x00
+#define BT_DISABLE 0x01
+
+// Constants reffering to HsFlags
+enum
+{
+ HS_UPDATE = 1
+};
+
+// Constants reffering to HsState
+enum
+{
+ HS_INITIALISE = 1,
+ HS_INIT_RECEIVER,
+ HS_SEND_DATA,
+ HS_DISABLE
+};
+
+//Constants refering to DeviceStatus within DeviceTable
+enum
+{
+ BT_DEVICE_EMPTY = 0x00,
+ BT_DEVICE_UNKNOWN = 0x01,
+ BT_DEVICE_KNOWN = 0x02,
+ BT_DEVICE_NAME = 0x40,
+ BT_DEVICE_AWAY = 0x80
+};
+
+/* Interface between command other modules */
+enum
+{
+ SENDFILE,
+ SEARCH,
+ STOPSEARCH,
+ CONNECT,
+ DISCONNECT,
+ DISCONNECTALL,
+ REMOVEDEVICE,
+ VISIBILITY,
+ SETCMDMODE,
+ OPENSTREAM,
+ SENDDATA,
+ FACTORYRESET,
+ BTON,
+ BTOFF,
+ SETBTNAME,
+ EXTREAD,
+ PINREQ,
+ CONNECTREQ
+};
+
+
+enum
+{
+ LR_SUCCESS = 0x50,
+ LR_COULD_NOT_SAVE,
+ LR_STORE_IS_FULL,
+ LR_ENTRY_REMOVED,
+ LR_UNKOWN_ADDR
+};
+
+enum
+{
+ USB_CMD_READY = 0x01,
+ BT_CMD_READY = 0x02,
+ HS_CMD_READY = 0x04
+};
+
+typedef struct
+{
+ UBYTE Buf[SIZE_OF_USBBUF];
+ UBYTE InPtr;
+ UBYTE OutPtr;
+ UBYTE Spare1;
+ UBYTE Spare2;
+}USBBUF;
+
+typedef struct
+{
+ UBYTE Buf[SIZE_OF_HSBUF];
+ UBYTE InPtr;
+ UBYTE OutPtr;
+ UBYTE Spare1;
+ UBYTE Spare2;
+}HSBUF;
+
+typedef struct
+{
+ UBYTE Buf[SIZE_OF_BTBUF];
+ UBYTE InPtr;
+ UBYTE OutPtr;
+ UBYTE Spare1;
+ UBYTE Spare2;
+}BTBUF;
+
+typedef struct
+{
+ UBYTE Name[SIZE_OF_BT_NAME];
+ UBYTE ClassOfDevice[SIZE_OF_CLASS_OF_DEVICE];
+ UBYTE BdAddr[SIZE_OF_BDADDR];
+ UBYTE DeviceStatus;
+ UBYTE Spare1;
+ UBYTE Spare2;
+ UBYTE Spare3;
+}BDDEVICETABLE;
+
+typedef struct
+{
+ UBYTE Name[SIZE_OF_BT_NAME];
+ UBYTE ClassOfDevice[SIZE_OF_CLASS_OF_DEVICE];
+ UBYTE PinCode[16];
+ UBYTE BdAddr[SIZE_OF_BDADDR];
+ UBYTE HandleNr;
+ UBYTE StreamStatus;
+ UBYTE LinkQuality;
+ UBYTE Spare;
+}BDCONNECTTABLE;
+
+typedef struct
+{
+ UBYTE Name[SIZE_OF_BT_NAME];
+ UBYTE BluecoreVersion[2];
+ UBYTE BdAddr[SIZE_OF_BDADDR];
+ UBYTE BtStateStatus;
+ UBYTE BtHwStatus;
+ UBYTE TimeOutValue;
+ UBYTE Spare1;
+ UBYTE Spare2;
+ UBYTE Spare3;
+}BRICKDATA;
+
+typedef struct
+{
+ UWORD (*pFunc)(UBYTE, UBYTE, UBYTE, UBYTE, UBYTE*, UWORD*);
+ void (*pFunc2)(UBYTE*);
+
+ // BT related entries
+ BDDEVICETABLE BtDeviceTable[SIZE_OF_BT_DEVICE_TABLE];
+ BDCONNECTTABLE BtConnectTable[SIZE_OF_BT_CONNECT_TABLE];
+
+ //General brick data
+ BRICKDATA BrickData;
+
+ BTBUF BtInBuf;
+ BTBUF BtOutBuf;
+
+ // HI Speed related entries
+ HSBUF HsInBuf;
+ HSBUF HsOutBuf;
+
+ // USB related entries
+ USBBUF UsbInBuf;
+ USBBUF UsbOutBuf;
+ USBBUF UsbPollBuf;
+
+ UBYTE BtDeviceCnt;
+ UBYTE BtDeviceNameCnt;
+
+ UBYTE HsFlags;
+ UBYTE HsSpeed;
+ UBYTE HsState;
+
+ UBYTE UsbState;
+
+}IOMAPCOMM;
+
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_display.c b/AT91SAM7S256/Source/c_display.c
new file mode 100644
index 0000000..36d66e7
--- /dev/null
+++ b/AT91SAM7S256/Source/c_display.c
@@ -0,0 +1,859 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 17-02-06 8:45 $
+//
+// Filename $Workfile:: c_display.c $
+//
+// Version $Revision:: 36 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_display. $
+//
+// Platform C
+//
+
+#include <string.h>
+#include "stdconst.h"
+#include "modules.h"
+#include "c_display.iom"
+#include "c_display.h"
+#include "d_display.h"
+
+
+static IOMAPDISPLAY IOMapDisplay;
+static VARSDISPLAY VarsDisplay;
+
+const HEADER cDisplay =
+{
+ 0x000A0001L,
+ "Display",
+ cDisplayInit,
+ cDisplayCtrl,
+ cDisplayExit,
+ (void *)&IOMapDisplay,
+ (void *)&VarsDisplay,
+ (UWORD)sizeof(IOMapDisplay),
+ (UWORD)sizeof(VarsDisplay),
+ 0x0000 //Code size - not used so far
+};
+
+
+const SCREEN_CORDINATE SCREEN_CORDINATES[SCREENS] =
+{
+ { 0, 0,DISPLAY_WIDTH,DISPLAY_HEIGHT }, // Background
+ { 0, 8,DISPLAY_WIDTH,DISPLAY_HEIGHT - 8 }, // Large
+ { 0, 8,DISPLAY_WIDTH,24 } // Small
+};
+
+const SCREEN_CORDINATE SELECT_FRAME_CORDINATES =
+{
+ 38,41,24,24
+};
+
+
+const SCREEN_CORDINATE MENUICON_CORDINATES[MENUICONS] =
+{
+ { DISPLAY_MENUICONS_X_OFFS,DISPLAY_MENUICONS_Y,24,24 }, // Left
+ { DISPLAY_MENUICONS_X_OFFS + DISPLAY_MENUICONS_X_DIFF,DISPLAY_MENUICONS_Y,24,24 }, // Center
+ { DISPLAY_MENUICONS_X_OFFS + DISPLAY_MENUICONS_X_DIFF * 2,DISPLAY_MENUICONS_Y,24,24 },// Right
+};
+
+const SCREEN_CORDINATE STATUSICON_CORDINATES[STATUSICONS] =
+{
+ { 0, 0,12, 8 }, // Bluetooth
+ { 12, 0,12, 8 }, // Usb
+ { 76, 0,12, 8 }, // Vm
+ { 88, 0,12, 8 } // Battery
+};
+
+
+const SCREEN_CORDINATE STEPICON_CORDINATES[STEPICONS] =
+{
+ { 11,16,11,16 }, // Step 1
+ { 28,16,11,16 }, // Step 2
+ { 45,16,11,16 }, // Step 3
+ { 62,16,11,16 }, // Step 4
+ { 79,16,11,16 } // Step 5
+};
+
+
+void cDisplaySetPixel(UBYTE X,UBYTE Y)
+{
+ if ((X < DISPLAY_WIDTH) && (Y < DISPLAY_HEIGHT))
+ {
+ IOMapDisplay.Display[(Y / 8) * DISPLAY_WIDTH + X] |= (1 << (Y % 8));
+ }
+}
+
+
+void cDisplayClrPixel(UBYTE X,UBYTE Y)
+{
+ if ((X < DISPLAY_WIDTH) && (Y < DISPLAY_HEIGHT))
+ {
+ IOMapDisplay.Display[(Y / 8) * DISPLAY_WIDTH + X] &= ~(1 << (Y % 8));
+ }
+}
+
+
+void cDisplayChar(FONT *pFont,UBYTE On,UBYTE X,UBYTE Y,UBYTE Char)
+{
+ UBYTE *pSource;
+ UBYTE FontWidth;
+ UBYTE FontHeight;
+ UBYTE Items;
+ UBYTE Item;
+ UBYTE TmpY;
+
+
+ Items = pFont->ItemsX * pFont->ItemsY;
+ Item = Char - ' ';
+ if (Item < Items)
+ {
+ FontWidth = pFont->ItemPixelsX;
+ pSource = (UBYTE*)&pFont->Data[Item * FontWidth];
+ while (FontWidth--)
+ {
+ TmpY = 0;
+ FontHeight = pFont->ItemPixelsY;
+ while (FontHeight--)
+ {
+ if (On == TRUE)
+ {
+ if (((*pSource) & (1 << TmpY)))
+ {
+ cDisplaySetPixel(X,Y + TmpY);
+ }
+ else
+ {
+ cDisplayClrPixel(X,Y + TmpY);
+ }
+ }
+ else
+ {
+ if (((*pSource) & (1 << TmpY)))
+ {
+ cDisplayClrPixel(X,Y + TmpY);
+ }
+ else
+ {
+ cDisplaySetPixel(X,Y + TmpY);
+ }
+ }
+ TmpY++;
+ }
+ X++;
+ pSource++;
+ }
+ }
+}
+
+
+void cDisplayString(FONT *pFont,UBYTE X,UBYTE Y,UBYTE *pString)
+{
+ UBYTE *pSource;
+ UBYTE *pDestination;
+ UBYTE FontWidth;
+ UBYTE Line;
+ UBYTE Items;
+ UBYTE Item;
+
+
+ Line = (Y & 0xF8) / 8;
+ Items = pFont->ItemsX * pFont->ItemsY;
+ pDestination = (UBYTE*)&IOMapDisplay.Display[Line * DISPLAY_WIDTH + X];
+
+ while (*pString)
+ {
+ Item = *pString - ' ';
+ if (Item < Items)
+ {
+ FontWidth = pFont->ItemPixelsX;
+ pSource = (UBYTE*)&pFont->Data[Item * FontWidth];
+ while (FontWidth--)
+ {
+ *pDestination = *pSource;
+ pDestination++;
+ pSource++;
+ }
+ }
+ pString++;
+ }
+}
+
+
+void cDisplayUpdateScreen(SCREEN_CORDINATE *pCord,BMPMAP *pBitmap)
+{
+ UBYTE *pSource;
+ UBYTE *pDestination;
+ UBYTE Line;
+ UBYTE Lines;
+
+ if (pBitmap)
+ {
+ if ((((pBitmap->StartY + pCord->StartY) & 0x07) == 0) && ((pBitmap->PixelsY & 0x07) == 0))
+ {
+ pSource = pBitmap->Data;
+ Line = (pBitmap->StartY + pCord->StartY) / 8;
+ Lines = Line + pBitmap->PixelsY / 8;
+ while (Line < Lines)
+ {
+ pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pBitmap->StartX + pCord->StartX];
+ memcpy(pDestination,pSource,(size_t)pBitmap->PixelsX);
+ pSource += pBitmap->PixelsX;
+ Line++;
+ }
+ }
+ }
+}
+
+
+void cDisplayCenterString(FONT *pFont,UBYTE *pString,UBYTE Line)
+{
+ UWORD Chars;
+ UBYTE Column;
+
+ if (pString)
+ {
+ Chars = 0;
+ while (pString[Chars])
+ {
+ Chars++;
+ }
+ Column = (DISPLAY_WIDTH - Chars * pFont->ItemPixelsX) / 2;
+ cDisplayString(pFont,Column,Line * 8,pString);
+ }
+}
+
+
+void cDisplayUpdateMenuIcon(UBYTE *pIcon,SCREEN_CORDINATE *pCord)
+{
+ UBYTE *pDestination;
+ UBYTE Line;
+ UBYTE Column;
+ UBYTE Lines;
+ UBYTE Columns;
+
+ if (((pCord->StartY & 0x07) == 0) && ((pCord->PixelsY & 0x07) == 0))
+ {
+ Line = pCord->StartY / 8;
+ Lines = Line + pCord->PixelsY / 8;
+ Columns = pCord->StartX + pCord->PixelsX;
+ if (pIcon != NULL)
+ {
+ while (Line < Lines)
+ {
+ Column = pCord->StartX;
+ pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + Column];
+
+ while (Column < Columns)
+ {
+ *pDestination |= *pIcon;
+ pIcon++;
+ pDestination++;
+ Column++;
+ }
+ Line++;
+ }
+ }
+ else
+ {
+ while (Line < Lines)
+ {
+ pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pCord->StartX];
+ memset(pDestination,0,(size_t)pCord->PixelsX);
+ Line++;
+ }
+ }
+ }
+}
+
+
+void cDisplayUpdateIcon(ICON *pIcons,UBYTE Index,SCREEN_CORDINATE *pCord)
+{
+ UBYTE *pSource;
+ UBYTE *pDestination;
+ UBYTE Line;
+ UBYTE Lines;
+
+ if (pIcons)
+ {
+ if ((Index > 0) && (Index <= (pIcons->ItemsX * pIcons->ItemsY)))
+ {
+ Index--;
+ if (((pCord->StartY & 0x07) == 0) && ((pCord->PixelsY & 0x07) == 0))
+ {
+ Line = pCord->StartY / 8;
+ Lines = Line + pCord->PixelsY / 8;
+ pSource = &pIcons->Data[((Index / pIcons->ItemsX) * pIcons->ItemsX * pIcons->ItemPixelsX * pIcons->ItemPixelsY / 8) + ((Index % pIcons->ItemsX) * pIcons->ItemPixelsX)];
+ while (Line < Lines)
+ {
+ pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pCord->StartX];
+ memcpy(pDestination,pSource,(size_t)pCord->PixelsX);
+ pSource += (pIcons->ItemPixelsX * pIcons->ItemsX);
+ Line++;
+ }
+ }
+ }
+ else
+ {
+ if (((pCord->StartY & 0x07) == 0) && ((pCord->PixelsY & 0x07) == 0))
+ {
+ Line = pCord->StartY / 8;
+ Lines = Line + pCord->PixelsY / 8;
+ while (Line < Lines)
+ {
+ pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pCord->StartX];
+ memset(pDestination,0,(size_t)pCord->PixelsX);
+ Line++;
+ }
+ }
+ }
+ }
+}
+
+
+void cDisplayLineX(UBYTE X1,UBYTE X2,UBYTE Y)
+{
+ UBYTE X;
+ UBYTE M;
+
+ M = 1 << (Y % 8);
+ Y >>= 3;
+ for (X = X1;X < X2;X++)
+ {
+ IOMapDisplay.Display[Y * DISPLAY_WIDTH + X] |= M;
+ }
+}
+
+void cDisplayLineY(UBYTE X,UBYTE Y1,UBYTE Y2)
+{
+ UBYTE Y;
+
+ for (Y = Y1;Y < Y2;Y++)
+ {
+ IOMapDisplay.Display[(Y / 8) * DISPLAY_WIDTH + X] |= (1 << (Y % 8));
+ }
+}
+
+void cDisplayFrame(SCREEN_CORDINATE *pCord)
+{
+ cDisplayLineX(pCord->StartX,pCord->StartX + pCord->PixelsX - 1,pCord->StartY);
+ cDisplayLineY(pCord->StartX,pCord->StartY,pCord->StartY + pCord->PixelsY - 1);
+ cDisplayLineY(pCord->StartX + pCord->PixelsX - 1,pCord->StartY,pCord->StartY + pCord->PixelsY - 1);
+}
+
+
+void cDisplayEraseLine(UBYTE Line)
+{
+ UBYTE Tmp;
+
+ for (Tmp = 0;Tmp < DISPLAY_WIDTH;Tmp++)
+ {
+ IOMapDisplay.Display[Line * DISPLAY_WIDTH + Tmp] = 0x00;
+ }
+}
+
+
+void cDisplayErase(void)
+{
+ UBYTE Tmp;
+
+ for (Tmp = 0;Tmp < (DISPLAY_HEIGHT / 8);Tmp++)
+ {
+ cDisplayEraseLine(Tmp);
+ }
+}
+
+
+void cDisplayEraseScreen(SCREEN_CORDINATE *pCord)
+{
+ UBYTE *pDestination;
+ UBYTE Line;
+ UBYTE Lines;
+
+ if (((pCord->StartY & 0x07) == 0) && ((pCord->PixelsY & 0x07) == 0))
+ {
+ Line = pCord->StartY / 8;
+ Lines = Line + pCord->PixelsY / 8;
+
+ while (Line < Lines)
+ {
+ pDestination = &IOMapDisplay.Display[Line * DISPLAY_WIDTH + pCord->StartX];
+ memset(pDestination,0,(size_t)pCord->PixelsX);
+ Line++;
+ }
+ }
+}
+
+
+void cDisplayDraw(UBYTE Cmd,UBYTE On,UBYTE X1,UBYTE Y1,UBYTE X2,UBYTE Y2)
+{
+ switch (Cmd)
+ {
+ case DISPLAY_ERASE_ALL :
+ {
+ cDisplayErase();
+ }
+ break;
+
+ case DISPLAY_PIXEL :
+ {
+ if (On == TRUE)
+ {
+ cDisplaySetPixel(X1,Y1);
+ }
+ else
+ {
+ cDisplayClrPixel(X1,Y1);
+ }
+ }
+ break;
+
+ case DISPLAY_HORISONTAL_LINE :
+ {
+ if (On == TRUE)
+ {
+ if (X1 > X2)
+ {
+ cDisplayLineX(X2,X1,Y1);
+ }
+ else
+ {
+ cDisplayLineX(X1,X2,Y1);
+ }
+ }
+ }
+ break;
+
+ case DISPLAY_VERTICAL_LINE :
+ {
+ if (On == TRUE)
+ {
+ if (Y1 > Y2)
+ {
+ cDisplayLineY(X1,Y2,Y1);
+ }
+ else
+ {
+ cDisplayLineY(X1,Y1,Y2);
+ }
+ }
+ }
+ break;
+
+ case DISPLAY_CHAR :
+ {
+ cDisplayChar(IOMapDisplay.pFont,On,X1,Y1,X2);
+ }
+ break;
+
+ }
+}
+
+
+void cDisplayInit(void* pHeader)
+{
+ dDisplayInit();
+ IOMapDisplay.Display = (UBYTE*)IOMapDisplay.Normal;
+ IOMapDisplay.pFunc = &cDisplayDraw;
+ IOMapDisplay.EraseMask = 0;
+ IOMapDisplay.UpdateMask = 0;
+ IOMapDisplay.TextLinesCenterFlags = 0;
+ IOMapDisplay.Flags = DISPLAY_REFRESH | DISPLAY_ON;
+ VarsDisplay.ErasePointer = 0;
+ VarsDisplay.UpdatePointer = 0;
+}
+
+
+void cDisplayCtrl(void)
+{
+ ULONG TmpMask;
+ UBYTE Tmp;
+ SCREEN_CORDINATE Cordinate;
+
+ if (!(IOMapDisplay.Flags & DISPLAY_POPUP))
+ {
+ if (IOMapDisplay.Display == (UBYTE*)IOMapDisplay.Popup)
+ {
+ IOMapDisplay.Display = VarsDisplay.DisplaySave;
+ }
+ }
+ else
+ {
+ if (IOMapDisplay.Display != (UBYTE*)IOMapDisplay.Popup)
+ {
+ VarsDisplay.DisplaySave = IOMapDisplay.Display;
+ IOMapDisplay.Display = (UBYTE*)IOMapDisplay.Popup;
+ }
+ }
+
+ if (IOMapDisplay.EraseMask)
+ {
+
+ VarsDisplay.ErasePointer = 31;
+ while ((VarsDisplay.ErasePointer) && (!(IOMapDisplay.EraseMask & (0x00000001 << VarsDisplay.ErasePointer))))
+ {
+ VarsDisplay.ErasePointer--;
+ }
+
+ TmpMask = IOMapDisplay.EraseMask & (1 << VarsDisplay.ErasePointer);
+ if ((TmpMask & TEXTLINE_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & TEXTLINE_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < TEXTLINES)
+ {
+ cDisplayEraseLine(Tmp);
+ }
+ }
+ else
+ {
+ if ((TmpMask & MENUICON_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & MENUICON_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < MENUICONS)
+ {
+ cDisplayEraseScreen((SCREEN_CORDINATE*)&MENUICON_CORDINATES[Tmp]);
+ }
+ }
+ else
+ {
+ if ((TmpMask & STATUSICON_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & STATUSICON_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < STATUSICONS)
+ {
+ cDisplayEraseScreen((SCREEN_CORDINATE*)&STATUSICON_CORDINATES[Tmp]);
+ }
+ }
+ else
+ {
+ if ((TmpMask & SCREEN_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & SCREEN_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < SCREENS)
+ {
+ cDisplayEraseScreen((SCREEN_CORDINATE*)&SCREEN_CORDINATES[Tmp]);
+ }
+ if ((TmpMask & SCREEN_BIT(SCREEN_LARGE)))
+ {
+ if ((IOMapDisplay.UpdateMask & SPECIAL_BIT(TOPLINE)))
+ {
+ cDisplayLineX(0,DISPLAY_WIDTH - 1,9);
+ IOMapDisplay.UpdateMask &= ~SPECIAL_BIT(TOPLINE);
+ }
+ }
+ }
+ else
+ {
+ if ((TmpMask & BITMAP_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & BITMAP_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < BITMAPS)
+ {
+ Cordinate.StartX = VarsDisplay.pOldBitmaps[Tmp]->StartX;
+ Cordinate.StartY = VarsDisplay.pOldBitmaps[Tmp]->StartY;
+ Cordinate.PixelsX = VarsDisplay.pOldBitmaps[Tmp]->PixelsX;
+ Cordinate.PixelsY = VarsDisplay.pOldBitmaps[Tmp]->PixelsY;
+ cDisplayEraseScreen(&Cordinate);
+ }
+ }
+ else
+ {
+ if ((TmpMask & SPECIAL_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & SPECIAL_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ switch (Tmp)
+ {
+ case FRAME_SELECT :
+ {
+ }
+ break;
+
+ case MENUTEXT :
+ {
+ cDisplayEraseLine(TEXTLINE_5);
+ }
+ break;
+
+ case STATUSTEXT :
+ {
+ cDisplayEraseLine(TEXTLINE_1);
+ }
+ break;
+
+ case STEPLINE :
+ {
+ }
+ break;
+
+ case TOPLINE :
+ {
+ }
+ break;
+
+ }
+ }
+ else
+ {
+ if ((TmpMask & STEPICON_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & STEPICON_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < STEPICONS)
+ {
+ cDisplayEraseScreen((SCREEN_CORDINATE*)&STEPICON_CORDINATES[Tmp]);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ IOMapDisplay.EraseMask &= ~TmpMask;
+
+ if (++VarsDisplay.ErasePointer >= 32)
+ {
+ VarsDisplay.ErasePointer = 0;
+ }
+ VarsDisplay.UpdatePointer = 0;
+ }
+ else
+ {
+ if (IOMapDisplay.UpdateMask)
+ {
+
+ VarsDisplay.UpdatePointer = 31;
+ while ((VarsDisplay.UpdatePointer) && (!(IOMapDisplay.UpdateMask & (0x00000001 << VarsDisplay.UpdatePointer))))
+ {
+ VarsDisplay.UpdatePointer--;
+ }
+ TmpMask = IOMapDisplay.UpdateMask & (0x00000001 << VarsDisplay.UpdatePointer);
+
+ if ((TmpMask & TEXTLINE_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & TEXTLINE_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < TEXTLINES)
+ {
+ if ((IOMapDisplay.TextLinesCenterFlags & (UBYTE)TmpMask))
+ {
+ cDisplayCenterString(IOMapDisplay.pFont,IOMapDisplay.pTextLines[Tmp],TEXTLINE_1 + Tmp);
+ }
+ else
+ {
+ cDisplayString(IOMapDisplay.pFont,0,Tmp * 8,IOMapDisplay.pTextLines[Tmp]);
+ }
+ }
+ }
+ else
+ {
+ if ((TmpMask & MENUICON_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & MENUICON_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < MENUICONS)
+ {
+ cDisplayUpdateMenuIcon(IOMapDisplay.pMenuIcons[Tmp],(SCREEN_CORDINATE*)&MENUICON_CORDINATES[Tmp]);
+ }
+ }
+ else
+ {
+ if ((TmpMask & STATUSICON_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & STATUSICON_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < STATUSICONS)
+ {
+ cDisplayUpdateIcon(IOMapDisplay.pStatusIcons,IOMapDisplay.StatusIcons[Tmp],(SCREEN_CORDINATE*)&STATUSICON_CORDINATES[Tmp]);
+ }
+ }
+ else
+ {
+ if ((TmpMask & SCREEN_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & SCREEN_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < SCREENS)
+ {
+ cDisplayUpdateScreen((SCREEN_CORDINATE*)&SCREEN_CORDINATES[Tmp],IOMapDisplay.pScreens[Tmp]);
+ }
+ }
+ else
+ {
+ if ((TmpMask & BITMAP_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & BITMAP_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < BITMAPS)
+ {
+ VarsDisplay.pOldBitmaps[Tmp] = IOMapDisplay.pBitmaps[Tmp];
+ cDisplayUpdateScreen((SCREEN_CORDINATE*)&SCREEN_CORDINATES[SCREEN_BACKGROUND],IOMapDisplay.pBitmaps[Tmp]);
+ }
+ }
+ else
+ {
+ if ((TmpMask & SPECIAL_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & SPECIAL_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ switch (Tmp)
+ {
+ case FRAME_SELECT :
+ {
+ cDisplayFrame((SCREEN_CORDINATE*)&SELECT_FRAME_CORDINATES);
+ }
+ break;
+
+ case MENUTEXT :
+ {
+ cDisplayCenterString(IOMapDisplay.pFont,IOMapDisplay.pMenuText,TEXTLINE_5);
+ }
+ break;
+
+ case STATUSTEXT :
+ {
+ cDisplayCenterString(IOMapDisplay.pFont,IOMapDisplay.pStatusText,TEXTLINE_1);
+ }
+ break;
+
+ case STEPLINE :
+ {
+ cDisplayLineX(22,28,20);
+ cDisplayLineX(39,45,20);
+ cDisplayLineX(56,62,20);
+ cDisplayLineX(73,79,20);
+ }
+ break;
+
+ case TOPLINE :
+ {
+ cDisplayLineX(0,DISPLAY_WIDTH - 1,9);
+ }
+ break;
+
+ }
+ }
+ else
+ {
+ if ((TmpMask & STEPICON_BITS))
+ {
+ Tmp = 0;
+ while (!(TmpMask & STEPICON_BIT(Tmp)))
+ {
+ Tmp++;
+ }
+ if (Tmp < STEPICONS)
+ {
+ cDisplayUpdateIcon(IOMapDisplay.pStepIcons,IOMapDisplay.StepIcons[Tmp],(SCREEN_CORDINATE*)&STEPICON_CORDINATES[Tmp]);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ IOMapDisplay.TextLinesCenterFlags &= (UBYTE)(~TmpMask);
+ IOMapDisplay.UpdateMask &= ~TmpMask;
+ if (++VarsDisplay.UpdatePointer >= 32)
+ {
+ VarsDisplay.UpdatePointer = 0;
+ }
+ }
+ VarsDisplay.ErasePointer = 0;
+ }
+ if (!(IOMapDisplay.Flags & DISPLAY_POPUP))
+ {
+ if (!(IOMapDisplay.Flags & DISPLAY_REFRESH_DISABLED))
+ {
+ if ((IOMapDisplay.Flags & DISPLAY_ON))
+ {
+ dDisplayOn(TRUE);
+ }
+ else
+ {
+ dDisplayOn(FALSE);
+ }
+ if (!(dDisplayUpdate(DISPLAY_HEIGHT,DISPLAY_WIDTH,(UBYTE*)IOMapDisplay.Normal)))
+ {
+ IOMapDisplay.Flags &= ~DISPLAY_BUSY;
+ if (!(IOMapDisplay.Flags & DISPLAY_REFRESH))
+ {
+ IOMapDisplay.Flags |= DISPLAY_REFRESH_DISABLED;
+ }
+ }
+ else
+ {
+ IOMapDisplay.Flags |= DISPLAY_BUSY;
+ }
+ }
+ else
+ {
+ if ((IOMapDisplay.Flags & DISPLAY_REFRESH))
+ {
+ IOMapDisplay.Flags &= ~DISPLAY_REFRESH_DISABLED;
+ }
+ }
+ }
+ else
+ {
+ dDisplayUpdate(DISPLAY_HEIGHT,DISPLAY_WIDTH,(UBYTE*)IOMapDisplay.Popup);
+ }
+}
+
+
+void cDisplayExit(void)
+{
+ dDisplayExit();
+}
+
diff --git a/AT91SAM7S256/Source/c_display.h b/AT91SAM7S256/Source/c_display.h
new file mode 100644
index 0000000..62a89f8
--- /dev/null
+++ b/AT91SAM7S256/Source/c_display.h
@@ -0,0 +1,43 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 17-02-06 8:45 $
+//
+// Filename $Workfile:: c_display.h $
+//
+// Version $Revision:: 8 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_display. $
+//
+// Platform C
+//
+
+#ifndef C_DISPLAY
+#define C_DISPLAY
+
+#ifndef INCLUDE_OS
+
+typedef struct
+{
+ UBYTE *DisplaySave;
+ BMPMAP *pOldBitmaps[BITMAPS];
+ UBYTE ErasePointer;
+ UBYTE UpdatePointer;
+}VARSDISPLAY;
+
+#endif
+
+
+void cDisplayInit(void* pHeader);
+void cDisplayCtrl(void);
+void cDisplayExit(void);
+
+
+extern const HEADER cDisplay;
+
+
+#endif
diff --git a/AT91SAM7S256/Source/c_display.iom b/AT91SAM7S256/Source/c_display.iom
new file mode 100644
index 0000000..79fd86b
--- /dev/null
+++ b/AT91SAM7S256/Source/c_display.iom
@@ -0,0 +1,177 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 17-02-06 8:45 $
+//
+// Filename $Workfile:: c_display.iom $
+//
+// Version $Revision:: 30 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_display. $
+//
+// Platform C
+//
+
+#ifndef CDISPLAY_IOM
+#define CDISPLAY_IOM
+
+#define pMapDisplay ((IOMAPDISPLAY*)(pHeaders[ENTRY_DISPLAY]->pIOMap))
+
+// Constants related to simple draw entry (x = dont care)
+enum
+{
+ DISPLAY_ERASE_ALL = 0x00, // W - erase entire screen (CMD,x,x,x,x,x)
+ DISPLAY_PIXEL = 0x01, // W - set pixel (on/off) (CMD,TRUE/FALSE,X,Y,x,x)
+ DISPLAY_HORISONTAL_LINE = 0x02, // W - draw horisontal line (CMD,TRUE,X1,Y1,X2,x)
+ DISPLAY_VERTICAL_LINE = 0x03, // W - draw vertical line (CMD,TRUE,X1,Y1,x,Y2)
+ DISPLAY_CHAR = 0x04 // W - draw char (actual font) (CMD,TRUE,X1,Y1,Char,x)
+};
+
+// Constants related to Flags
+enum
+{
+ DISPLAY_ON = 0x01, // W - Display on
+ DISPLAY_REFRESH = 0x02, // W - Enable refresh
+ DISPLAY_POPUP = 0x08, // W - Use popup display memory
+ DISPLAY_REFRESH_DISABLED = 0x40, // R - Refresh disabled
+ DISPLAY_BUSY = 0x80 // R - Refresh in progress
+};
+
+
+#define DISPLAY_HEIGHT 64 // Y pixels
+#define DISPLAY_WIDTH 100 // X pixels
+
+#define DISPLAY_MENUICONS_Y 40
+#define DISPLAY_MENUICONS_X_OFFS 7
+#define DISPLAY_MENUICONS_X_DIFF 31
+
+#define DISPLAY_IDLE ((pMapDisplay->EraseMask == 0) && (pMapDisplay->UpdateMask == 0))
+
+enum TEXTLINE_NO // Used in macro "TEXTLINE_BIT"
+{
+ TEXTLINE_1, // Upper most line
+ TEXTLINE_2, //
+ TEXTLINE_3, //
+ TEXTLINE_4, //
+ TEXTLINE_5, //
+ TEXTLINE_6, //
+ TEXTLINE_7, //
+ TEXTLINE_8, // Buttom line
+ TEXTLINES
+};
+
+enum MENUICON_NO // Used in macro "MENUICON_BIT"
+{
+ MENUICON_LEFT, // Left icon
+ MENUICON_CENTER, // Center icon
+ MENUICON_RIGHT, // Right icon
+ MENUICONS
+};
+
+enum SPECIAL_NO // Used in macro "SPECIAL_BIT"
+{
+ FRAME_SELECT, // Center icon select frame
+ STATUSTEXT, // Status text (BT name)
+ MENUTEXT, // Center icon text
+ STEPLINE, // Step collection lines
+ TOPLINE, // Top status underline
+ SPECIALS
+};
+
+enum STATUSICON_NO // Used in macro "STATUSICON_BIT"
+{
+ STATUSICON_BLUETOOTH, // BlueTooth status icon collection
+ STATUSICON_USB, // USB status icon collection
+ STATUSICON_VM, // VM status icon collection
+ STATUSICON_BATTERY, // Battery status icon collection
+ STATUSICONS
+};
+
+enum SCREEN_NO // Used in macro "SCREEN_BIT"
+{
+ SCREEN_BACKGROUND, // Entire screen
+ SCREEN_LARGE, // Entire screen except status line
+ SCREEN_SMALL, // Screen between menu icons and status line
+ SCREENS
+};
+
+enum BITMAP_NO // Used in macro "BITMAP_BIT"
+{
+ BITMAP_1, // Bitmap 1
+ BITMAP_2, // Bitmap 2
+ BITMAP_3, // Bitmap 3
+ BITMAP_4, // Bitmap 4
+ BITMAPS
+};
+
+enum STEP_NO // Used in macro "STEPICON_BIT"
+{
+ STEPICON_1, // Left most step icon
+ STEPICON_2, //
+ STEPICON_3, //
+ STEPICON_4, //
+ STEPICON_5, // Right most step icon
+ STEPICONS
+};
+
+#define SCREEN_BITS ((ULONG)0xE0000000) // Executed as 1.
+#define STEPICON_BITS ((ULONG)0x1F000000) // Executed as 2.
+#define BITMAP_BITS ((ULONG)0x00F00000) // Executed as 3.
+#define MENUICON_BITS ((ULONG)0x000E0000) // Executed as 4.
+#define STATUSICON_BITS ((ULONG)0x0001E000) // Executed as 5.
+#define SPECIAL_BITS ((ULONG)0x00001F00) // Executed as 6.
+#define TEXTLINE_BITS ((ULONG)0x000000FF) // Executed as 7.
+
+#define SCREEN_BIT(No) ((ULONG)0x20000000 << (No))
+#define STEPICON_BIT(No) ((ULONG)0x01000000 << (No))
+#define BITMAP_BIT(No) ((ULONG)0x00100000 << (No))
+#define MENUICON_BIT(No) ((ULONG)0x00020000 << (No))
+#define STATUSICON_BIT(No) ((ULONG)0x00002000 << (No))
+#define SPECIAL_BIT(No) ((ULONG)0x00000100 << (No))
+#define TEXTLINE_BIT(No) ((ULONG)0x00000001 << (No))
+
+
+typedef struct
+{
+ void (*pFunc)(UBYTE,UBYTE,UBYTE,UBYTE,UBYTE,UBYTE); // Simple draw entry
+
+ ULONG EraseMask; // Section erase mask (executed first)
+ ULONG UpdateMask; // Section update mask (executed next)
+
+ FONT *pFont; // Pointer to font file
+ UBYTE *pTextLines[TEXTLINES]; // Pointer to text strings
+
+ UBYTE *pStatusText; // Pointer to status text string
+ ICON *pStatusIcons; // Pointer to status icon collection file
+
+ BMPMAP *pScreens[SCREENS]; // Pointer to screen bitmap file
+ BMPMAP *pBitmaps[BITMAPS]; // Pointer to free bitmap files
+
+ UBYTE *pMenuText; // Pointer to menu icon text (NULL == none)
+ UBYTE *pMenuIcons[MENUICONS]; // Pointer to menu icon images (NULL == none)
+
+ ICON *pStepIcons; // Pointer to step icon collection file
+
+ UBYTE *Display; // Display content copied to physical display every 17 mS
+
+ UBYTE StatusIcons[STATUSICONS]; // Index in status icon collection file (index = 0 -> none)
+
+ UBYTE StepIcons[STEPICONS]; // Index in step icon collection file (index = 0 -> none)
+
+ UBYTE Flags; // Update flags enumerated above
+
+ UBYTE TextLinesCenterFlags; // Mask to center TextLines
+
+ UBYTE Normal[DISPLAY_HEIGHT / 8][DISPLAY_WIDTH]; // Raw display memory for normal screen
+ UBYTE Popup[DISPLAY_HEIGHT / 8][DISPLAY_WIDTH]; // Raw display memory for popup screen
+}
+IOMAPDISPLAY;
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_input.c b/AT91SAM7S256/Source/c_input.c
new file mode 100644
index 0000000..d17c546
--- /dev/null
+++ b/AT91SAM7S256/Source/c_input.c
@@ -0,0 +1,777 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:06 $
+//
+// Filename $Workfile:: c_input.c $
+//
+// Version $Revision:: 25 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_input.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "modules.h"
+#include "c_input.h"
+#include "d_input.h"
+#include "c_output.iom"
+
+#define INVALID_RELOAD_NORMAL 20
+#define INVALID_RELOAD_SOUND 300
+
+#define ROT_SLOW_SPEED 30
+#define ROT_OV_SAMPLING 7
+
+#define VCC_SENSOR 5000L
+#define VCC_SENSOR_DIODE 4300L
+#define AD_MAX 1023L
+
+#define REFLECTIONSENSORMIN (1906L/(VCC_SENSOR/AD_MAX))
+#define REFLECTIONSENSORMAX ((AD_MAX * 4398L)/VCC_SENSOR)
+#define REFLECTIONSENSORPCTDYN (UBYTE)(((REFLECTIONSENSORMAX - REFLECTIONSENSORMIN) * 100L)/AD_MAX)
+
+#define NEWLIGHTSENSORMIN (800L/(VCC_SENSOR/AD_MAX))
+#define NEWLIGHTSENSORMAX ((AD_MAX * 4400L)/VCC_SENSOR)
+#define NEWLIGHTSENSORPCTDYN (UBYTE)(((NEWLIGHTSENSORMAX - NEWLIGHTSENSORMIN) * 100L)/AD_MAX)
+
+#define NEWSOUNDSENSORMIN (650L/(VCC_SENSOR/AD_MAX))
+#define NEWSOUNDSENSORMAX ((AD_MAX * 4980L)/VCC_SENSOR)
+#define NEWSOUNDSENSORPCTDYN (UBYTE)(((NEWSOUNDSENSORMAX - NEWSOUNDSENSORMIN) * 100L)/AD_MAX)
+
+enum
+{
+ POWER = 0x00,
+ NO_POWER = 0x01,
+ ACTIVE = 0x02,
+ ALWAYS_ACTIVE = 0x04,
+ DIGI_0_HIGH = 0x08,
+ DIGI_1_HIGH = 0x10,
+ CUSTOM_SETUP = 0x20
+};
+
+static const UBYTE ActiveList[NO_OF_SENSOR_TYPES] =
+{
+ NO_POWER, /* NO_SENSOR */
+ NO_POWER, /* SWITCH */
+ NO_POWER, /* TEMPERATURE */
+ ACTIVE, /* REFLECTION */
+ ACTIVE, /* ANGLE */
+ DIGI_0_HIGH, /* LIGHT_ACTIVE */
+ POWER, /* LIGHT_INACTIVE */
+ DIGI_0_HIGH, /* SOUND_DB */
+ DIGI_1_HIGH, /* SOUND_DBA */
+ CUSTOM_SETUP, /* CUSTOM */
+ DIGI_0_HIGH | DIGI_1_HIGH, /* LOWSPEED */
+ ALWAYS_ACTIVE | DIGI_0_HIGH | DIGI_1_HIGH /* LOWSPEED_9V on */
+
+};
+
+static IOMAPINPUT IOMapInput;
+static VARSINPUT VarsInput;
+
+const HEADER cInput =
+{
+ 0x00030001L,
+ "Input",
+ cInputInit,
+ cInputCtrl,
+ cInputExit,
+ (void *)&IOMapInput,
+ (void *)&VarsInput,
+ (UWORD)sizeof(IOMapInput),
+ (UWORD)sizeof(VarsInput),
+ 0x0000 //Code size - not used so far
+};
+
+void cInputCalcSensorRaw(UWORD *pRaw, UBYTE Type, UBYTE No);
+void cInputCalcFullScale(UWORD *pRawVal, UWORD ZeroPointOffset, UBYTE PctFullScale, UBYTE InvState);
+void cInputCalcSensorValue(UWORD *pRaw, UBYTE Slope, UBYTE Mode, UBYTE Tmp);
+void cInputCalcSensor(UBYTE Tmp);
+void cInputSetupType(UBYTE Port);
+void cInputSetupCustomSensor(UBYTE Port);
+
+
+void cInputInit(void* pHeader)
+{
+ UBYTE Tmp;
+
+ /* Init IO map */
+ for (Tmp = 0; Tmp < NO_OF_INPUTS; Tmp++)
+ {
+ IOMapInput.Inputs[Tmp].SensorType = NO_SENSOR;
+ IOMapInput.Inputs[Tmp].SensorMode = RAWMODE;
+ IOMapInput.Inputs[Tmp].SensorRaw = 0;
+ IOMapInput.Inputs[Tmp].SensorValue = 0;
+ IOMapInput.Inputs[Tmp].SensorBoolean = 0;
+ IOMapInput.Inputs[Tmp].InvalidData = INVALID_DATA;
+ IOMapInput.Inputs[Tmp].DigiPinsDir = 0;
+ IOMapInput.Inputs[Tmp].DigiPinsOut = 0;
+ IOMapInput.Inputs[Tmp].CustomActiveStatus = CUSTOMINACTIVE;
+ IOMapInput.Inputs[Tmp].CustomZeroOffset = 0;
+ IOMapInput.Inputs[Tmp].CustomPctFullScale = 0;
+ dInputRead0(Tmp, &(IOMapInput.Inputs[Tmp].DigiPinsIn));
+ dInputRead1(Tmp, &(IOMapInput.Inputs[Tmp].DigiPinsIn));
+
+ VarsInput.EdgeCnt[Tmp] = 0;
+ VarsInput.InputDebounce[Tmp] = 0;
+ VarsInput.LastAngle[Tmp] = 0;
+ VarsInput.SampleCnt[Tmp] = 0;
+ VarsInput.InvalidTimer[Tmp] = INVALID_RELOAD_NORMAL;
+ VarsInput.OldSensorType[Tmp] = NO_SENSOR;
+ }
+ dInputInit();
+}
+
+void cInputCtrl(void)
+{
+ UBYTE Tmp;
+
+ for (Tmp = 0; Tmp < NO_OF_INPUTS; Tmp++)
+ {
+
+ if ((IOMapInput.Inputs[Tmp].SensorType) != (VarsInput.OldSensorType[Tmp]))
+ {
+
+ /* Clear all variables for this sensor */
+ VarsInput.EdgeCnt[Tmp] = 0;
+ VarsInput.InputDebounce[Tmp] = 0;
+ VarsInput.LastAngle[Tmp] = 0;
+ VarsInput.SampleCnt[Tmp] = 0;
+
+ /* Has the type change any influence on pin setup? */
+ if ((ActiveList[IOMapInput.Inputs[Tmp].SensorType]) != (ActiveList[VarsInput.OldSensorType[Tmp]]))
+ {
+
+ /* The type change has influence on pin setup - therefore a delay is inserted */
+ /* to ensure valid data representation (delay is: time for data to get down into */
+ /* the avr + delay before ad conversion + time for data to get up to the ARM */
+ /* processor */
+ if ((SOUND_DB == IOMapInput.Inputs[Tmp].SensorType) || (SOUND_DBA == IOMapInput.Inputs[Tmp].SensorType))
+ {
+
+ /* Sound Sensors have a long hardware stabilizing time */
+ VarsInput.InvalidTimer[Tmp] = INVALID_RELOAD_SOUND;
+ }
+ else
+ {
+ VarsInput.InvalidTimer[Tmp] = INVALID_RELOAD_NORMAL;
+ }
+
+ /* Setup the pins for the new sensortype */
+ cInputSetupType(Tmp);
+ IOMapInput.Inputs[Tmp].InvalidData = INVALID_DATA;
+ }
+ VarsInput.OldSensorType[Tmp] = IOMapInput.Inputs[Tmp].SensorType;
+ }
+ else
+ {
+ if (VarsInput.InvalidTimer[Tmp])
+ {
+
+ /* A type change has bee carried out earlier - waiting for valid data */
+ (VarsInput.InvalidTimer[Tmp])--;
+ if (0 == VarsInput.InvalidTimer[Tmp])
+ {
+
+ /* Time elapsed - data are now valid */
+ IOMapInput.Inputs[Tmp].InvalidData &= ~INVALID_DATA;
+ }
+ }
+ else
+ {
+
+ /* The invalid bit could have been set by the VM due to Mode change */
+ /* but input module needs to be called once to update the values */
+ IOMapInput.Inputs[Tmp].InvalidData &= ~INVALID_DATA;
+ }
+ }
+
+ if (!(INVALID_DATA & (IOMapInput.Inputs[Tmp].InvalidData)))
+ {
+ cInputCalcSensor(Tmp);
+ }
+ }
+}
+
+
+void cInputCalcSensor(UBYTE Tmp)
+{
+ UWORD InputRaw;
+
+ /* Get the RCX hardware compensated AD values put values in */
+ /* InputRaw array */
+ dInputGetRawAd(&InputRaw, Tmp);
+ IOMapInput.Inputs[Tmp].ADRaw = InputRaw;
+
+ /* Calculate the sensor hardware compensated AD values and put then */
+ /* in IOMapInput.Inputs[Tmp].SensorRaw */
+ cInputCalcSensorRaw(&InputRaw, IOMapInput.Inputs[Tmp].SensorType, Tmp);
+
+ /* Calculate the sensor value compensated for sensor mode and put */
+ /* them in IOMapInput.Inputs[Tmp].SensorValue */
+ cInputCalcSensorValue( &InputRaw,
+ ((IOMapInput.Inputs[Tmp].SensorMode) & SLOPEMASK),
+ ((IOMapInput.Inputs[Tmp].SensorMode) & MODEMASK),
+ Tmp);
+
+}
+
+
+
+void cInputCalcSensorValue(UWORD *pRaw, UBYTE Slope, UBYTE Mode, UBYTE Tmp)
+{
+ SWORD Delta;
+ UBYTE PresentBoolean;
+ UBYTE Sample;
+
+ if (0 == Slope)
+ {
+
+ /* This is absolute measure method */
+ if (*pRaw > THRESHOLD_FALSE)
+ {
+ PresentBoolean = FALSE;
+ }
+ else
+ {
+ if (*pRaw < THRESHOLD_TRUE)
+ {
+ PresentBoolean = TRUE;
+ }
+ }
+ }
+ else
+ {
+
+ /* This is dynamic measure method */
+ if (*pRaw > (ACTUAL_AD_RES - Slope))
+ {
+ PresentBoolean = FALSE;
+ }
+ else
+ {
+ if (*pRaw < Slope)
+ {
+ PresentBoolean = TRUE;
+ }
+ else
+ {
+ Delta = IOMapInput.Inputs[Tmp].SensorRaw - *pRaw;
+ if (Delta < 0)
+ {
+ if (-Delta > Slope)
+ {
+ PresentBoolean = FALSE;
+ }
+ }
+ else
+ {
+ if (Delta > Slope)
+ {
+ PresentBoolean = TRUE;
+ }
+ }
+ }
+ }
+ }
+ IOMapInput.Inputs[Tmp].SensorRaw = *pRaw;
+
+ switch(Mode)
+ {
+
+ case RAWMODE:
+ {
+ IOMapInput.Inputs[Tmp].SensorValue = *pRaw;
+ }
+ break;
+
+ case BOOLEANMODE:
+ {
+ IOMapInput.Inputs[Tmp].SensorValue = PresentBoolean;
+ }
+ break;
+
+ case TRANSITIONCNTMODE:
+ {
+ if (VarsInput.InputDebounce[Tmp] > 0)
+ {
+ VarsInput.InputDebounce[Tmp]--;
+ }
+ else
+ {
+ if (IOMapInput.Inputs[Tmp].SensorBoolean != PresentBoolean)
+ {
+ VarsInput.InputDebounce[Tmp] = DEBOUNCERELOAD;
+ (IOMapInput.Inputs[Tmp].SensorValue)++;
+ }
+ }
+ }
+ break;
+
+ case PERIODCOUNTERMODE:
+ {
+ if (VarsInput.InputDebounce[Tmp] > 0)
+ {
+ VarsInput.InputDebounce[Tmp]--;
+ }
+ else
+ {
+ if (IOMapInput.Inputs[Tmp].SensorBoolean != PresentBoolean)
+ {
+ VarsInput.InputDebounce[Tmp] = DEBOUNCERELOAD;
+ IOMapInput.Inputs[Tmp].SensorBoolean = PresentBoolean;
+ if (++VarsInput.EdgeCnt[Tmp] > 1)
+ {
+ if (PresentBoolean == 0)
+ {
+ VarsInput.EdgeCnt[Tmp] = 0;
+ (IOMapInput.Inputs[Tmp].SensorValue)++;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case PCTFULLSCALEMODE:
+ {
+
+ /* Output is 0-100 pct */
+ IOMapInput.Inputs[Tmp].SensorValue = ((*pRaw) * 100)/SENSOR_RESOLUTION;
+ }
+ break;
+
+ case FAHRENHEITMODE:
+ {
+
+ /* Fahrenheit mode goes from -40 to 158 degrees */
+ IOMapInput.Inputs[Tmp].SensorValue = (((ULONG)(*pRaw) * 900L)/SENSOR_RESOLUTION) - 200;
+ IOMapInput.Inputs[Tmp].SensorValue = ((180L * (ULONG)(IOMapInput.Inputs[Tmp].SensorValue))/100L) + 320;
+ }
+ break;
+
+ case CELSIUSMODE:
+ {
+
+ /* Celsius mode goes from -20 to 70 degrees */
+ IOMapInput.Inputs[Tmp].SensorValue = (((ULONG)(*pRaw) * 900L)/SENSOR_RESOLUTION) - 200;
+ }
+ break;
+
+ case ANGLESTEPSMODE:
+ {
+ IOMapInput.Inputs[Tmp].SensorBoolean = PresentBoolean;
+
+ if (*pRaw < ANGLELIMITA)
+ {
+ Sample = 0;
+ }
+ else
+ {
+ if (*pRaw < ANGLELIMITB)
+ {
+ Sample = 1;
+ }
+ else
+ {
+ if (*pRaw < ANGLELIMITC)
+ {
+ Sample = 2;
+ }
+ else
+ {
+ Sample = 3;
+ }
+ }
+ }
+
+ switch (VarsInput.LastAngle[Tmp])
+ {
+ case 0 :
+ {
+ if (Sample == 1)
+ {
+ if (VarsInput.SampleCnt[Tmp] >= ROT_SLOW_SPEED )
+ {
+
+ if (++(VarsInput.SampleCnt[Tmp]) >= (ROT_SLOW_SPEED + ROT_OV_SAMPLING))
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)++;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ }
+ else
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)++;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ }
+ if (Sample == 2)
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)--;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ if (Sample == 0)
+ {
+ if (VarsInput.SampleCnt[Tmp] < ROT_SLOW_SPEED)
+ {
+ (VarsInput.SampleCnt[Tmp])++;
+ }
+ }
+ }
+ break;
+ case 1 :
+ {
+ if (Sample == 3)
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)++;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ if (Sample == 0)
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)--;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ VarsInput.SampleCnt[Tmp] = 0;
+ }
+ break;
+ case 2 :
+ {
+ if (Sample == 0)
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)++;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ if (Sample == 3)
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)--;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ VarsInput.SampleCnt[Tmp] = 0;
+ }
+ break;
+ case 3 :
+ {
+ if (Sample == 2)
+ {
+ if (VarsInput.SampleCnt[Tmp] >= ROT_SLOW_SPEED)
+ {
+
+ if (++(VarsInput.SampleCnt[Tmp]) >= (ROT_SLOW_SPEED + ROT_OV_SAMPLING))
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)++;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ }
+ else
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)++;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ }
+ if (Sample == 1)
+ {
+ (IOMapInput.Inputs[Tmp].SensorValue)--;
+ VarsInput.LastAngle[Tmp] = Sample;
+ }
+ if (Sample == 3)
+ {
+ if (VarsInput.SampleCnt[Tmp] < ROT_SLOW_SPEED)
+ {
+ (VarsInput.SampleCnt[Tmp])++;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ IOMapInput.Inputs[Tmp].SensorBoolean = PresentBoolean;
+}
+
+
+const SWORD TempConvTable[] =
+{
+ 1500, 1460, 1430, 1400, 1380, 1360, 1330, 1310, 1290, 1270, 1250, 1230, 1220, 1200, 1190, 1170,
+ 1160, 1150, 1140, 1130, 1110, 1100, 1090, 1080, 1070, 1060, 1050, 1040, 1030, 1020, 1010, 1000,
+ 994, 988, 982, 974, 968, 960, 954, 946, 940, 932, 926, 918, 912, 906, 900, 894,
+ 890, 884, 878, 874, 868, 864, 858, 854, 848, 844, 838, 832, 828, 822, 816, 812,
+ 808, 802, 798, 794, 790, 786, 782, 780, 776, 772, 768, 764, 762, 758, 754, 750,
+ 748, 744, 740, 736, 732, 730, 726, 722, 718, 716, 712, 708, 704, 700, 696, 694,
+ 690, 688, 684, 682, 678, 674, 672, 668, 666, 662, 660, 656, 654, 650, 648, 644,
+ 642, 640, 638, 634, 632, 630, 628, 624, 622, 620, 616, 614, 612, 610, 608, 604,
+ 602, 600, 598, 596, 592, 590, 588, 586, 584, 582, 580, 578, 576, 574, 572, 570,
+ 568, 564, 562, 560, 558, 556, 554, 552, 550, 548, 546, 544, 542, 540, 538, 536,
+ 534, 532, 530, 528, 526, 524, 522, 520, 518, 516, 514, 512, 510, 508, 508, 506,
+ 504, 502, 500, 498, 496, 494, 494, 492, 490, 488, 486, 486, 484, 482, 480, 478,
+ 476, 476, 474, 472, 470, 468, 468, 466, 464, 462, 460, 458, 458, 456, 454, 452,
+ 450, 448, 448, 446, 444, 442, 442, 440, 438, 436, 436, 434, 432, 432, 430, 428,
+ 426, 426, 424, 422, 420, 420, 418, 416, 416, 414, 412, 410, 408, 408, 406, 404,
+ 404, 402, 400, 398, 398, 396, 394, 394, 392, 390, 390, 388, 386, 386, 384, 382,
+ 382, 380, 378, 378, 376, 374, 374, 372, 370, 370, 368, 366, 366, 364, 362, 362,
+ 360, 358, 358, 356, 354, 354, 352, 350, 350, 348, 348, 346, 344, 344, 342, 340,
+ 340, 338, 338, 336, 334, 334, 332, 332, 330, 328, 328, 326, 326, 324, 322, 322,
+ 320, 320, 318, 316, 316, 314, 314, 312, 310, 310, 308, 308, 306, 304, 304, 302,
+ 300, 300, 298, 298, 296, 296, 294, 292, 292, 290, 290, 288, 286, 286, 284, 284,
+ 282, 282, 280, 280, 278, 278, 276, 274, 274, 272, 272, 270, 270, 268, 268, 266,
+ 264, 264, 262, 262, 260, 260, 258, 258, 256, 254, 254, 252, 252, 250, 250, 248,
+ 248, 246, 244, 244, 242, 240, 240, 240, 238, 238, 236, 236, 234, 234, 232, 230,
+ 230, 228, 228, 226, 226, 224, 224, 222, 220, 220, 218, 218, 216, 216, 214, 214,
+ 212, 212, 210, 210, 208, 208, 206, 204, 204, 202, 202, 200, 200, 198, 198, 196,
+ 196, 194, 194, 192, 190, 190, 188, 188, 186, 186, 184, 184, 182, 182, 180, 180,
+ 178, 178, 176, 176, 174, 174, 172, 172, 170, 170, 168, 168, 166, 166, 164, 164,
+ 162, 162, 160, 160, 158, 156, 156, 154, 154, 152, 152, 150, 150, 148, 148, 146,
+ 146, 144, 144, 142, 142, 140, 140, 138, 136, 136, 136, 134, 134, 132, 130, 130,
+ 128, 128, 126, 126, 124, 124, 122, 122, 120, 120, 118, 118, 116, 116, 114, 114,
+ 112, 110, 110, 108, 108, 106, 106, 104, 104, 102, 102, 100, 100, 98, 98, 96,
+ 94, 94, 92, 92, 90, 90, 88, 88, 86, 86, 84, 82, 82, 80, 80, 78,
+ 78, 76, 76, 74, 74, 72, 72, 70, 70, 68, 68, 66, 66, 64, 62, 62,
+ 60, 60, 58, 56, 56, 54, 54, 52, 52, 50, 50, 48, 48, 46, 46, 44,
+ 44, 42, 40, 40, 38, 38, 36, 34, 34, 32, 32, 30, 30, 28, 28, 26,
+ 24, 24, 22, 22, 20, 20, 18, 16, 16, 14, 14, 12, 12, 10, 10, 8,
+ 6, 6, 4, 2, 2, 0, 0, -2, -4, -4, -6, -6, -8, -10, -10, -12,
+ -12, -14, -16, -16, -18, -20, -20, -22, -22, -24, -26, -26, -28, -30, -30, -32,
+ -34, -34, -36, -36, -38, -40, -40, -42, -42, -44, -46, -46, -48, -50, -50, -52,
+ -54, -54, -56, -58, -58, -60, -60, -62, -64, -66, -66, -68, -70, -70, -72, -74,
+ -76, -76, -78, -80, -80, -82, -84, -86, -86, -88, -90, -90, -92, -94, -94, -96,
+ -98, -98, -100, -102, -104, -106, -106, -108, -110, -112, -114, -114, -116, -118, -120, -120,
+ -122, -124, -126, -128, -130, -130, -132, -134, -136, -138, -140, -142, -144, -146, -146, -148,
+ -150, -152, -154, -156, -158, -160, -162, -164, -166, -166, -168, -170, -172, -174, -176, -178,
+ -180, -182, -184, -186, -188, -190, -192, -194, -196, -196, -198, -200, -202, -204, -206, -208,
+ -210, -212, -214, -216, -218, -220, -224, -226, -228, -230, -232, -234, -236, -238, -242, -246,
+ -248, -250, -254, -256, -260, -262, -264, -268, -270, -274, -276, -278, -282, -284, -286, -290,
+ -292, -296, -298, -300, -306, -308, -312, -316, -320, -324, -326, -330, -334, -338, -342, -344,
+ -348, -354, -358, -362, -366, -370, -376, -380, -384, -388, -394, -398, -404, -410, -416, -420,
+ -428, -432, -440, -446, -450, -460, -468, -476, -484, -492, -500, -510, -524, -534, -546, -560,
+ -572, -588, -600, -630, -656, -684, -720, -770
+};
+
+
+void cInputCalcSensorRaw(UWORD *pRaw, UBYTE Type, UBYTE No)
+{
+
+ switch (Type)
+ {
+ case SWITCH:
+ {
+ }
+ break;
+ case TEMPERATURE:
+ {
+ if (*pRaw < 290)
+ {
+ *pRaw = 290;
+ }
+ else
+ {
+ if (*pRaw > 928)
+ {
+ *pRaw = 928;
+ }
+ }
+ *pRaw = TempConvTable[(*pRaw) - 197];
+ *pRaw = *pRaw + 200;
+ *pRaw = (UWORD)(((SLONG)*pRaw * (SLONG)1023)/(SLONG)900);
+ }
+ break;
+ case REFLECTION:
+ {
+
+ /* Sensor dynanmic is restricted by a double diode connected to ground, */
+ /* and it cannot go to the top either, dynamic is approx. 390 - 900 count*/
+ cInputCalcFullScale(pRaw, REFLECTIONSENSORMIN, REFLECTIONSENSORPCTDYN, TRUE);
+ }
+ break;
+ case ANGLE:
+ {
+ }
+ break;
+ case LIGHT_ACTIVE:
+ {
+ cInputCalcFullScale(pRaw, NEWLIGHTSENSORMIN, NEWLIGHTSENSORPCTDYN, TRUE);
+ }
+ break;
+ case LIGHT_INACTIVE:
+ {
+ cInputCalcFullScale(pRaw, NEWLIGHTSENSORMIN, NEWLIGHTSENSORPCTDYN, TRUE);
+ }
+ break;
+ case SOUND_DB:
+ {
+ cInputCalcFullScale(pRaw, NEWSOUNDSENSORMIN, NEWSOUNDSENSORPCTDYN, TRUE);
+ }
+ break;
+ case SOUND_DBA:
+ {
+ cInputCalcFullScale(pRaw, NEWSOUNDSENSORMIN, NEWSOUNDSENSORPCTDYN, TRUE);
+ }
+ break;
+ case LOWSPEED:
+ {
+ /* Intended empty Low Speed module takes over */
+ }
+ break;
+ case HIGHSPEED:
+ {
+ }
+ break;
+ case CUSTOM:
+ {
+
+ /* Setup and read digital IO */
+ cInputSetupCustomSensor(No);
+ dInputRead0(No, &(IOMapInput.Inputs[No].DigiPinsIn));
+ dInputRead1(No, &(IOMapInput.Inputs[No].DigiPinsIn));
+ cInputCalcFullScale(pRaw, IOMapInput.Inputs[No].CustomZeroOffset, IOMapInput.Inputs[No].CustomPctFullScale, FALSE);
+ }
+ break;
+ case NO_SENSOR:
+ {
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+}
+
+void cInputCalcFullScale(UWORD *pRawVal, UWORD ZeroPointOffset, UBYTE PctFullScale, UBYTE InvStatus)
+{
+ if (*pRawVal >= ZeroPointOffset)
+ {
+ *pRawVal -= ZeroPointOffset;
+ }
+ else
+ {
+ *pRawVal = 0;
+ }
+
+ *pRawVal = (*pRawVal * 100)/PctFullScale;
+ if (*pRawVal > SENSOR_RESOLUTION)
+ {
+ *pRawVal = SENSOR_RESOLUTION;
+ }
+ if (TRUE == InvStatus)
+ {
+ *pRawVal = SENSOR_RESOLUTION - *pRawVal;
+ }
+}
+
+void cInputSetupType(UBYTE Port)
+{
+ UBYTE Setup;
+
+ Setup = (ActiveList[IOMapInput.Inputs[Port].SensorType]);
+
+ if (CUSTOM_SETUP & Setup)
+ {
+ cInputSetupCustomSensor(Port);
+ }
+ else
+ {
+ if (NO_POWER & Setup)
+ {
+
+ /* Setup is not used - set pins in unconfigured state */
+ dInputSetInactive(Port);
+ dInputSetDirInDigi0(Port);
+ dInputSetDirInDigi1(Port);
+ }
+ else
+ {
+ if (ACTIVE & Setup)
+ {
+ dInputSetActive(Port);
+ }
+ else
+ {
+ if(ALWAYS_ACTIVE & Setup)
+ {
+ dInputSet9v(Port);
+ }
+ else
+ {
+ dInputSetInactive(Port);
+ }
+ }
+ if (DIGI_0_HIGH & Setup)
+ {
+ dInputSetDigi0(Port);
+ dInputSetDirOutDigi0(Port);
+ }
+ else
+ {
+ dInputClearDigi0(Port);
+ dInputSetDirOutDigi0(Port);
+ }
+
+ if (DIGI_1_HIGH & Setup)
+ {
+ dInputSetDigi1(Port);
+ dInputSetDirOutDigi1(Port);
+ }
+ else
+ {
+ dInputClearDigi1(Port);
+ dInputSetDirOutDigi1(Port);
+ }
+ }
+ }
+}
+
+void cInputSetupCustomSensor(UBYTE Port)
+{
+ if ((IOMapInput.Inputs[Port].DigiPinsDir) & 0x01)
+ {
+ if ((IOMapInput.Inputs[Port].DigiPinsOut) & 0x01)
+ {
+ dInputSetDigi0(Port);
+ }
+ else
+ {
+ dInputClearDigi0(Port);
+ }
+ dInputSetDirOutDigi0(Port);
+ }
+ if ((IOMapInput.Inputs[Port].DigiPinsDir) & 0x02)
+ {
+ if ((IOMapInput.Inputs[Port].DigiPinsOut) & 0x02)
+ {
+ dInputSetDigi1(Port);
+ }
+ else
+ {
+ dInputClearDigi1(Port);
+ }
+ dInputSetDirOutDigi1(Port);
+ }
+ else
+ {
+ dInputSetDirInDigi1(Port);
+ }
+
+ if (CUSTOMACTIVE == (IOMapInput.Inputs[Port].CustomActiveStatus))
+ {
+ dInputSetActive(Port);
+ }
+ else
+ {
+ if (CUSTOM9V == (IOMapInput.Inputs[Port].CustomActiveStatus))
+ {
+ dInputSet9v(Port);
+ }
+ else
+ {
+ dInputSetInactive(Port);
+ }
+ }
+}
+
+void cInputExit(void)
+{
+ dInputExit();
+}
diff --git a/AT91SAM7S256/Source/c_input.h b/AT91SAM7S256/Source/c_input.h
new file mode 100644
index 0000000..dfa981b
--- /dev/null
+++ b/AT91SAM7S256/Source/c_input.h
@@ -0,0 +1,53 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:06 $
+//
+// Filename $Workfile:: c_input.h $
+//
+// Version $Revision:: 9 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_input.h $
+//
+// Platform C
+//
+
+#ifndef C_INPUT
+#define C_INPUT
+
+#ifdef INCLUDE_OS
+extern const HEADER cInput;
+#endif
+
+#include "c_input.iom"
+
+#define ACTUAL_AD_RES 1023L
+#define SENSOR_RESOLUTION 1023L
+#define DEBOUNCERELOAD 100
+#define THRESHOLD_FALSE (UWORD)(ACTUAL_AD_RES * 45L / 100L)
+#define THRESHOLD_TRUE (UWORD)(ACTUAL_AD_RES * 55L / 100L)
+
+#define ANGLELIMITA (UWORD)(ACTUAL_AD_RES * 4400L / 10000L)
+#define ANGLELIMITB (UWORD)(ACTUAL_AD_RES * 6600L / 10000L)
+#define ANGLELIMITC (UWORD)(ACTUAL_AD_RES * 8900L / 10000L)
+
+#define FWDDIR 1
+#define RWDDIR 2
+#define MAXSAMPLECNT 5
+
+typedef struct
+{
+ UWORD InvalidTimer[NO_OF_INPUTS];
+ UBYTE InputDebounce[NO_OF_INPUTS];
+ UBYTE EdgeCnt[NO_OF_INPUTS];
+ UBYTE LastAngle[NO_OF_INPUTS];
+ UBYTE OldSensorType[NO_OF_INPUTS];
+ UBYTE SampleCnt[NO_OF_INPUTS];
+}VARSINPUT;
+
+void cInputInit(void* pHeader);
+void cInputCtrl(void);
+void cInputExit(void);
+
+
+#endif
diff --git a/AT91SAM7S256/Source/c_input.iom b/AT91SAM7S256/Source/c_input.iom
new file mode 100644
index 0000000..8d651b8
--- /dev/null
+++ b/AT91SAM7S256/Source/c_input.iom
@@ -0,0 +1,109 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:06 $
+//
+// Filename $Workfile:: c_input.iom $
+//
+// Version $Revision:: 15 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_input.io $
+//
+// Platform C
+//
+
+#ifndef CINPUT_IOM
+#define CINPUT_IOM
+
+#define NO_OF_INPUTS 4
+#define pMapInput ((IOMAPINPUT*)(pHeaders[ENTRY_INPUT]->pIOMap))
+
+
+/* Constants related to sensor type */
+enum
+{
+ NO_SENSOR = 0,
+ SWITCH = 1,
+ TEMPERATURE = 2,
+ REFLECTION = 3,
+ ANGLE = 4,
+ LIGHT_ACTIVE = 5,
+ LIGHT_INACTIVE = 6,
+ SOUND_DB = 7,
+ SOUND_DBA = 8,
+ CUSTOM = 9,
+ LOWSPEED = 10,
+ LOWSPEED_9V = 11,
+ HIGHSPEED = 12,
+ NO_OF_SENSOR_TYPES = 13
+};
+
+/* Constants related to sensor mode */
+enum
+{
+ RAWMODE = 0x00,
+ BOOLEANMODE = 0x20,
+ TRANSITIONCNTMODE = 0x40,
+ PERIODCOUNTERMODE = 0x60,
+ PCTFULLSCALEMODE = 0x80,
+ CELSIUSMODE = 0xA0,
+ FAHRENHEITMODE = 0xC0,
+ ANGLESTEPSMODE = 0xE0,
+ SLOPEMASK = 0x1F,
+ MODEMASK = 0xE0
+};
+
+/* Constants related to Digital I/O */
+enum
+{
+ DIGI0 = 1,
+ DIGI1 = 2
+};
+
+enum
+{
+ CUSTOMINACTIVE = 0x00,
+ CUSTOM9V = 0x01,
+ CUSTOMACTIVE = 0x02
+};
+
+enum
+{
+ INVALID_DATA = 0x01
+};
+
+typedef struct
+{
+ UWORD CustomZeroOffset; /* Set the offset of the custom sensor */
+ UWORD ADRaw;
+ UWORD SensorRaw;
+ SWORD SensorValue;
+
+ UBYTE SensorType;
+ UBYTE SensorMode;
+ UBYTE SensorBoolean;
+
+ UBYTE DigiPinsDir; /* Direction of the Digital pins 1 is output 0 is input */
+ UBYTE DigiPinsIn; /* Contains the status of the digital pins */
+ UBYTE DigiPinsOut; /* Sets the output level of the digital pins */
+ UBYTE CustomPctFullScale; /* Sets the Pct full scale of the custom sensor */
+ UBYTE CustomActiveStatus; /* Sets the active or inactive state of the custom sensor */
+
+ UBYTE InvalidData; /* Indicates wether data is invalid (1) or valid (0) */
+
+ UBYTE Spare1;
+ UBYTE Spare2;
+ UBYTE Spare3;
+
+}INPUT;
+
+
+typedef struct
+{
+ INPUT Inputs[NO_OF_INPUTS];
+}IOMAPINPUT;
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_ioctrl.c b/AT91SAM7S256/Source/c_ioctrl.c
new file mode 100644
index 0000000..2964f33
--- /dev/null
+++ b/AT91SAM7S256/Source/c_ioctrl.c
@@ -0,0 +1,78 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:50 $
+//
+// Filename $Workfile:: c_ioctrl.c $
+//
+// Version $Revision:: 13 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_ioctrl.c $
+//
+// Platform C
+//
+
+
+#include "stdconst.h"
+#include "modules.h"
+#include "c_ioctrl.iom"
+#include "c_ioctrl.h"
+#include "d_ioctrl.h"
+
+static IOMAPIOCTRL IOMapIOCtrl;
+static VARSIOCTRL VarsIOCtrl;
+
+const HEADER cIOCtrl =
+{
+ 0x00060001L,
+ "IOCtrl",
+ cIOCtrlInit,
+ cIOCtrlCtrl,
+ cIOCtrlExit,
+ (void *)&IOMapIOCtrl,
+ (void *)&VarsIOCtrl,
+ (UWORD)sizeof(IOMapIOCtrl),
+ (UWORD)sizeof(VarsIOCtrl),
+ 0x0000 //Code size - not used so far
+};
+
+
+void cIOCtrlInit(void* pHeader)
+{
+ dIOCtrlSetPower(0);
+ dIOCtrlInit();
+}
+
+
+void cIOCtrlCtrl(void)
+{
+ switch(IOMapIOCtrl.PowerOn)
+ {
+ case POWERDOWN:
+ {
+ dIOCtrlSetPower((POWERDOWN>>8));
+ }
+ break;
+ case BOOT:
+ {
+ dIOCtrlSetPower((UBYTE)(BOOT>>8));
+ dIOCtrlSetPwm((UBYTE)BOOT);
+ }
+ break;
+ default:
+ {
+ /* No need to change the default value */
+ /* if value is boot or reset it should come */
+ /* back from reset - setting the value to 0 */
+ }
+ break;
+ }
+ dIOCtrlTransfer();
+}
+
+
+void cIOCtrlExit(void)
+{
+ dIOCtrlExit();
+}
+
diff --git a/AT91SAM7S256/Source/c_ioctrl.h b/AT91SAM7S256/Source/c_ioctrl.h
new file mode 100644
index 0000000..a2bd892
--- /dev/null
+++ b/AT91SAM7S256/Source/c_ioctrl.h
@@ -0,0 +1,28 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:50 $
+//
+// Filename $Workfile:: c_ioctrl.h $
+//
+// Version $Revision:: 4 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_ioctrl.h $
+//
+// Platform C
+//
+
+#ifndef C_IOCTRL
+#define C_IOCTRL
+
+typedef struct
+{
+ UBYTE Tmp;
+}VARSIOCTRL;
+
+void cIOCtrlInit(void* pHeader);
+void cIOCtrlCtrl(void);
+void cIOCtrlExit(void);
+
+extern const HEADER cIOCtrl;
+#endif
diff --git a/AT91SAM7S256/Source/c_ioctrl.iom b/AT91SAM7S256/Source/c_ioctrl.iom
new file mode 100644
index 0000000..3385caa
--- /dev/null
+++ b/AT91SAM7S256/Source/c_ioctrl.iom
@@ -0,0 +1,35 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:50 $
+//
+// Filename $Workfile:: c_ioctrl.iom $
+//
+// Version $Revision:: 8 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_ioctrl.i $
+//
+// Platform C
+//
+
+#ifndef CIOCTRL_IOM
+#define CIOCTRL_IOM
+
+#define pMapIoCtrl ((IOMAPIOCTRL*)(pHeaders[ENTRY_IOCTRL]->pIOMap))
+
+enum
+{
+ POWERDOWN = 0x5A00,
+ BOOT = 0xA55A
+};
+
+typedef struct
+{
+ UWORD PowerOn;
+}IOMAPIOCTRL;
+
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_loader.c b/AT91SAM7S256/Source/c_loader.c
new file mode 100644
index 0000000..8b43bd8
--- /dev/null
+++ b/AT91SAM7S256/Source/c_loader.c
@@ -0,0 +1,458 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 8:27 $
+//
+// Filename $Workfile:: c_loader.c $
+//
+// Version $Revision:: 79 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_loader.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "modules.h"
+#include "c_loader.iom"
+#include "c_ioctrl.iom"
+#include "d_loader.h"
+#include "c_loader.h"
+
+static IOMAPLOADER IOMapLoader;
+static VARSLOADER VarsLoader;
+static HEADER **pHeaders;
+
+const HEADER cLoader =
+{
+ 0x00090001L,
+ "Loader",
+ cLoaderInit,
+ cLoaderCtrl,
+ cLoaderExit,
+ (void *)&IOMapLoader,
+ (void *)&VarsLoader,
+ (UWORD)sizeof(IOMapLoader),
+ (UWORD)sizeof(VarsLoader),
+ 0x0000 //Code size - not used so far
+};
+
+UWORD cLoaderFileRq(UBYTE Cmd, UBYTE *pFileName, UBYTE *pBuffer, ULONG *pLength);
+UWORD cLoaderGetIoMapInfo(ULONG ModuleId, UBYTE *pIoMap, UWORD *pIoMapSize);
+UWORD cLoaderFindModule(UBYTE *pBuffer);
+void cLoaderGetModuleName(UBYTE *pDst, UBYTE *pModule);
+
+void cLoaderInit(void* pHeader)
+{
+
+ IOMapLoader.pFunc = &cLoaderFileRq;
+ VarsLoader.IoMapHandle = FALSE;
+ pHeaders = pHeader;
+ dLoaderInit();
+ IOMapLoader.FreeUserFlash = dLoaderReturnFreeUserFlash();
+}
+
+void cLoaderCtrl(void)
+{
+}
+
+
+
+UWORD cLoaderFileRq(UBYTE Cmd, UBYTE *pFileName, UBYTE *pBuffer, ULONG *pLength)
+{
+ UWORD ReturnState;
+
+ ReturnState = SUCCESS;
+
+ switch(Cmd)
+ {
+ case OPENREAD:
+ {
+ ReturnState = dLoaderOpenRead(pFileName, pLength);
+ if (0x8000 <= ReturnState)
+ {
+ dLoaderCloseHandle(ReturnState);
+ }
+ }
+ break;
+ case OPENREADLINEAR:
+ {
+ ReturnState = dLoaderGetFilePtr(pFileName, pBuffer, pLength);
+ if (0x8000 <= ReturnState)
+ {
+ dLoaderCloseHandle(ReturnState);
+ }
+
+ }
+ break;
+ case OPENWRITE:
+ {
+
+ /* This is to create a new file */
+ ReturnState = dLoaderCreateFileHeader(*pLength, pFileName, (UBYTE) NONLINEAR, SYSTEMFILE);
+ if (0x8000 <= ReturnState)
+ {
+ dLoaderCloseHandle(ReturnState);
+ }
+ else
+ {
+ IOMapLoader.FreeUserFlash = dLoaderReturnFreeUserFlash();
+ }
+ }
+ break;
+ case OPENWRITELINEAR:
+ {
+ ReturnState = dLoaderCreateFileHeader(*pLength, pFileName, (UBYTE) LINEAR, SYSTEMFILE);
+ if (0x8000 <= ReturnState)
+ {
+ dLoaderCloseHandle(ReturnState);
+ }
+ else
+ {
+ IOMapLoader.FreeUserFlash = dLoaderReturnFreeUserFlash();
+ }
+ }
+ break;
+ case OPENWRITEDATA:
+ {
+
+ ReturnState = dLoaderCreateFileHeader(*pLength, pFileName, (UBYTE) LINEAR, DATAFILE);
+ if (0x8000 <= ReturnState)
+ {
+ dLoaderCloseHandle(ReturnState);
+ }
+ else
+ {
+ IOMapLoader.FreeUserFlash = dLoaderReturnFreeUserFlash();
+ }
+ }
+ break;
+ case OPENAPPENDDATA:
+ {
+ ReturnState = dLoaderOpenAppend(pFileName, pLength);
+ if (LOADER_ERR(ReturnState) != SUCCESS)
+ {
+ dLoaderCloseHandle(ReturnState);
+ }
+ }
+ break;
+ case CLOSE:
+ {
+ ReturnState = dLoaderCloseHandle(*pFileName);
+ }
+ break;
+ case READ:
+ {
+ ReturnState = dLoaderRead(*pFileName, pBuffer, pLength);
+ }
+ break;
+ case WRITE:
+ {
+ ReturnState = dLoaderWriteData(*pFileName, pBuffer, (UWORD*)pLength);
+ }
+ break;
+ case FINDFIRST:
+ {
+ ULONG DataLength;
+
+ ReturnState = dLoaderFind(pFileName, pBuffer, pLength, &DataLength, (UBYTE) SEARCHING);
+ if (0x8000 <= ReturnState)
+ {
+ dLoaderCloseHandle(ReturnState);
+ }
+ }
+ break;
+ case FINDNEXT:
+ {
+ UWORD Handle;
+ ULONG DataLength;
+
+ Handle = *pFileName;
+ ReturnState = dLoaderFindNext(Handle, pBuffer, pLength, &DataLength);
+ }
+ break;
+ case DELETE:
+ {
+ ReturnState = dLoaderDelete(pFileName);
+ IOMapLoader.FreeUserFlash = dLoaderReturnFreeUserFlash();
+
+ }
+ break;
+ case DELETEUSERFLASH:
+ {
+ dLoaderDeleteAllFiles();
+ IOMapLoader.FreeUserFlash = dLoaderReturnFreeUserFlash();
+
+ }
+ break;
+
+ case FINDFIRSTMODULE:
+ {
+ if (FALSE == VarsLoader.IoMapHandle)
+ {
+ VarsLoader.IoMapHandle = TRUE;
+ VarsLoader.ModSearchIndex = 0;
+ dLoaderInsertSearchStr(VarsLoader.ModSearchStr, pFileName, &(VarsLoader.ModSearchType));
+ ReturnState = cLoaderFindModule(pBuffer);
+ }
+ else
+ {
+ ReturnState = NOMOREHANDLES;
+ }
+ }
+ break;
+
+ case FINDNEXTMODULE:
+ {
+ ReturnState = cLoaderFindModule(pBuffer);
+ }
+ break;
+
+ case CLOSEMODHANDLE:
+ {
+ VarsLoader.IoMapHandle = FALSE;
+ ReturnState = SUCCESS;
+ }
+ break;
+
+ case IOMAPREAD:
+ {
+
+ UBYTE *pIoMap;
+ ULONG Ptr;
+ UWORD IoMapSize;
+ UBYTE Tmp;
+
+ pIoMap = NULL;
+ ReturnState = cLoaderGetIoMapInfo((*(ULONG*)(pFileName)),(UBYTE*)(&pIoMap), &IoMapSize);
+
+ /* Did we have a valid module ID ?*/
+ if (SUCCESS == LOADER_ERR(ReturnState))
+ {
+
+ /* This is the offset */
+ Ptr = pBuffer[0];
+ Ptr |= (UWORD)pBuffer[1] << 8;
+
+ /* is the offset within the limits of the iomap size? */
+ if ((Ptr + *pLength) <= IoMapSize)
+ {
+
+ /* Add the offset to the pointer */
+ pIoMap += Ptr;
+
+ for (Tmp = 0; Tmp < *pLength; Tmp++)
+ {
+ pBuffer[Tmp + 2] = *pIoMap;
+ pIoMap++;
+ }
+ }
+ else
+ {
+
+ /* Error - not within the bounderies */
+ ReturnState = OUTOFBOUNDERY;
+ *pLength = 0;
+ }
+ }
+ else
+ {
+
+ /* Error - not a valid module id */
+ *pLength = 0;
+ }
+ }
+ break;
+
+ case IOMAPWRITE:
+ {
+ UBYTE *pIoMap;
+ ULONG Ptr;
+ UWORD IoMapSize;
+ UWORD Tmp;
+
+
+ pIoMap = NULL;
+ ReturnState = cLoaderGetIoMapInfo(*((ULONG*)pFileName), (UBYTE*)&pIoMap, &IoMapSize);
+
+ if (LOADER_ERR(ReturnState) == SUCCESS)
+ {
+
+ /* This is the offset */
+ Ptr = *pBuffer;
+ pBuffer++;
+ Tmp = *pBuffer;
+ Ptr |= Tmp << 8;
+ pBuffer++;
+
+ if ((Ptr + *pLength) <= IoMapSize)
+ {
+
+ pIoMap += Ptr;
+ for (Tmp = 0; Tmp < *pLength; Tmp++)
+ {
+ *pIoMap = pBuffer[Tmp];
+ pIoMap++;
+ }
+ }
+ else
+ {
+
+ /* Error - not within the bounderies */
+ ReturnState = OUTOFBOUNDERY;
+ *pLength = 0;
+ }
+ }
+ else
+ {
+
+ /* Error - not a valid module id */
+ *pLength = 0;
+ }
+ }
+ break;
+
+ case RENAMEFILE:
+ {
+ UBYTE FoundName[FILENAME_LENGTH + 1];
+
+ /* Check for file exists*/
+ ReturnState = dLoaderFind(pBuffer, FoundName, pLength, pLength, (UBYTE) SEARCHING);
+ dLoaderCloseHandle(LOADER_HANDLE(ReturnState));
+ if (FILENOTFOUND == LOADER_ERR(ReturnState))
+ {
+ ReturnState = dLoaderFind(pFileName, FoundName, pLength, pLength, (UBYTE) SEARCHING);
+ if (ReturnState < 0x8000)
+ {
+ ReturnState = dLoaderCheckFiles((UBYTE) ReturnState);
+ if (ReturnState < 0x8000)
+ {
+ dLoaderRenameFile((UBYTE) ReturnState, pBuffer);
+ }
+ }
+ dLoaderCloseHandle(LOADER_HANDLE(ReturnState));
+ }
+ else
+ {
+ if (SUCCESS == LOADER_ERR(ReturnState))
+ {
+ ReturnState |= FILEEXISTS;
+ }
+ }
+ }
+ break;
+
+ default:
+ {
+ }
+ break;
+ }
+ return (ReturnState);
+}
+
+UWORD cLoaderGetIoMapInfo(ULONG ModuleId, UBYTE *pIoMap, UWORD *pIoMapSize)
+{
+ UBYTE Tmp;
+ UBYTE Exit;
+ UWORD RtnVal;
+
+ RtnVal = SUCCESS;
+ Tmp = 0;
+ Exit = FALSE;
+ while((Tmp < 32) && (Exit == FALSE))
+ {
+ if ((*(pHeaders[Tmp])).ModuleID == ModuleId)
+ {
+ Exit = TRUE;
+ }
+ else
+ {
+ Tmp++;
+ }
+ }
+
+ /* Did we have a valid module ID ?*/
+ if (TRUE == Exit)
+ {
+ /* Get the pointer of the module io map */
+ *((ULONG *)pIoMap) = (ULONG)((*(pHeaders[Tmp])).pIOMap);
+ *pIoMapSize = (*(pHeaders[Tmp])).IOMapSize;
+ }
+ else
+ {
+ RtnVal = MODULENOTFOUND;
+ }
+
+ /* To avoid a warning - this is optimized away */
+ *pIoMap = *pIoMap;
+ return(RtnVal);
+}
+
+UWORD cLoaderFindModule(UBYTE *pBuffer)
+{
+ UBYTE Tmp;
+ UWORD RtnVal;
+ UBYTE ModuleName[FILENAME_SIZE];
+
+ RtnVal = MODULENOTFOUND;
+
+ for (Tmp = VarsLoader.ModSearchIndex; Tmp < 32; Tmp++)
+ {
+ if (pHeaders[Tmp] != 0)
+ {
+
+ cLoaderGetModuleName(ModuleName, ((*(pHeaders[Tmp])).ModuleName));
+ if (SUCCESS == dLoaderCheckName(ModuleName, VarsLoader.ModSearchStr, VarsLoader.ModSearchType))
+ {
+
+ dLoaderCopyFileName(pBuffer, ModuleName);
+
+ pBuffer[FILENAME_SIZE] = (UBYTE) ((*(pHeaders[Tmp])).ModuleID);
+ pBuffer[FILENAME_SIZE + 1] = (UBYTE)(((*(pHeaders[Tmp])).ModuleID) >> 8);
+ pBuffer[FILENAME_SIZE + 2] = (UBYTE)(((*(pHeaders[Tmp])).ModuleID) >> 16);
+ pBuffer[FILENAME_SIZE + 3] = (UBYTE)(((*(pHeaders[Tmp])).ModuleID) >> 24);
+
+ pBuffer[FILENAME_SIZE + 4] = (UBYTE)(((*(pHeaders[Tmp])).ModuleSize));
+ pBuffer[FILENAME_SIZE + 5] = (UBYTE)(((*(pHeaders[Tmp])).ModuleSize) >> 8);
+ pBuffer[FILENAME_SIZE + 6] = (UBYTE)(((*(pHeaders[Tmp])).ModuleSize) >> 16);
+ pBuffer[FILENAME_SIZE + 7] = (UBYTE)(((*(pHeaders[Tmp])).ModuleSize) >> 24);
+
+ pBuffer[FILENAME_SIZE + 8] = (UBYTE) ((*(pHeaders[Tmp])).IOMapSize);
+ pBuffer[FILENAME_SIZE + 9] = (UBYTE)(((*(pHeaders[Tmp])).IOMapSize) >> 8);
+
+ RtnVal = SUCCESS;
+ (VarsLoader.ModSearchIndex) = Tmp + 1;
+ Tmp = 32;
+ }
+ }
+ }
+ return(RtnVal);
+}
+
+void cLoaderGetModuleName(UBYTE *pDst, UBYTE *pModule)
+{
+ UBYTE Tmp;
+
+ for(Tmp = 0; Tmp < FILENAME_SIZE; Tmp++)
+ {
+ if (0 != pModule[Tmp])
+ {
+ pDst[Tmp] = pModule[Tmp];
+ }
+ else
+ {
+ pDst[Tmp++] = '.';
+ pDst[Tmp++] = 'm';
+ pDst[Tmp++] = 'o';
+ pDst[Tmp++] = 'd';
+ pDst[Tmp] = '\0';
+ Tmp = FILENAME_SIZE;
+ }
+ }
+}
+
+void cLoaderExit(void)
+{
+}
+
+
diff --git a/AT91SAM7S256/Source/c_loader.h b/AT91SAM7S256/Source/c_loader.h
new file mode 100644
index 0000000..a720c37
--- /dev/null
+++ b/AT91SAM7S256/Source/c_loader.h
@@ -0,0 +1,44 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 8:27 $
+//
+// Filename $Workfile:: c_loader.h $
+//
+// Version $Revision:: 8 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_loader.h $
+//
+// Platform C
+//
+
+#ifndef C_LOADER
+#define C_LOADER
+
+enum
+{
+ LOADER_BUSY,
+ TOO_MANY_FILES,
+ NO_MORE_FLASH,
+ LOADER_SUCCESS
+};
+
+typedef struct
+{
+ UBYTE ModSearchStr[FILENAME_LENGTH + 1];
+ UBYTE ModSearchIndex;
+ UBYTE ModSearchType;
+ UBYTE UsbStatus;
+ UBYTE IoMapHandle;
+}VARSLOADER;
+
+void cLoaderInit(void* pHeader);
+void cLoaderCtrl(void);
+void cLoaderExit(void);
+
+extern const HEADER cLoader;
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_loader.iom b/AT91SAM7S256/Source/c_loader.iom
new file mode 100644
index 0000000..8a86e2d
--- /dev/null
+++ b/AT91SAM7S256/Source/c_loader.iom
@@ -0,0 +1,83 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 28-03-07 14:54 $
+//
+// Filename $Workfile:: c_loader.iom $
+//
+// Version $Revision:: 45 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_loader.i $
+//
+// Platform C
+//
+
+#ifndef CLOADER_IOM
+#define CLOADER_IOM
+
+#define pMapLoader ((IOMAPLOADER*)(pHeaders[ENTRY_LOADER]->pIOMap))
+
+//Version numbers are two bytes, MAJOR.MINOR (big-endian)
+//For example, version 1.5 would be 0x0105
+//If these switch to little-endian, be sure to update
+//definition and usages of VM_OLDEST_COMPATIBLE_VERSION, too!
+#define FIRMWAREVERSION 0x0105 //1.05
+#define PROTOCOLVERSION 0x017C //1.124
+
+enum
+{
+ OPENREAD = 0x80,
+ OPENWRITE = 0x81,
+ READ = 0x82,
+ WRITE = 0x83,
+ CLOSE = 0x84,
+ DELETE = 0x85,
+ FINDFIRST = 0x86,
+ FINDNEXT = 0x87,
+ VERSIONS = 0x88,
+ OPENWRITELINEAR = 0x89,
+ OPENREADLINEAR = 0x8A,
+ OPENWRITEDATA = 0x8B,
+ OPENAPPENDDATA = 0x8C,
+ FINDFIRSTMODULE = 0x90,
+ FINDNEXTMODULE = 0x91,
+ CLOSEMODHANDLE = 0x92,
+ IOMAPREAD = 0x94,
+ IOMAPWRITE = 0x95,
+ BOOTCMD = 0x97, /* external command only */
+ SETBRICKNAME = 0x98,
+ BTGETADR = 0x9A,
+ DEVICEINFO = 0x9B,
+ DELETEUSERFLASH = 0xA0,
+ POLLCMDLEN = 0xA1,
+ POLLCMD = 0xA2,
+ RENAMEFILE = 0xA3,
+ BTFACTORYRESET = 0xA4
+
+};
+
+typedef UWORD LOADER_STATUS;
+
+//Mask out handle byte of Loader status word for error code checks
+#define LOADER_ERR(StatusWord) ((StatusWord & 0xFF00))
+
+//Byte value of error half of Loader status word
+#define LOADER_ERR_BYTE(StatusWord) ((UBYTE)((StatusWord & 0xFF00) >> 8))
+
+//Value of handle inside Loader status word
+#define LOADER_HANDLE(StatusWord) ((UBYTE)(StatusWord))
+
+//Pointer to lower byte of Loader status word
+#define LOADER_HANDLE_P(StatusWord) ((UBYTE*)(&StatusWord))
+
+typedef struct
+{
+ UWORD (*pFunc)(UBYTE, UBYTE *, UBYTE *, ULONG *);
+ ULONG FreeUserFlash;
+}IOMAPLOADER;
+
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_lowspeed.c b/AT91SAM7S256/Source/c_lowspeed.c
new file mode 100644
index 0000000..a43ba7d
--- /dev/null
+++ b/AT91SAM7S256/Source/c_lowspeed.c
@@ -0,0 +1,236 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: c_lowspeed.c $
+//
+// Version $Revision:: 23 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_lowspeed $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "modules.h"
+#include "c_lowspeed.iom"
+#include "c_input.iom"
+#include "c_lowspeed.h"
+#include "d_lowspeed.h"
+
+static IOMAPLOWSPEED IOMapLowSpeed;
+static VARSLOWSPEED VarsLowSpeed;
+static HEADER **pHeaders;
+
+const UBYTE LOWSPEED_CH_NUMBER[4] = {0x01, 0x02, 0x04, 0x08};
+
+const HEADER cLowSpeed =
+{
+ 0x000B0001L,
+ "Low Speed",
+ cLowSpeedInit,
+ cLowSpeedCtrl,
+ cLowSpeedExit,
+ (void *)&IOMapLowSpeed,
+ (void *)&VarsLowSpeed,
+ (UWORD)sizeof(IOMapLowSpeed),
+ (UWORD)sizeof(VarsLowSpeed),
+ 0x0000 //Code size - not used so far
+};
+
+void cLowSpeedInit(void* pHeader)
+{
+ pHeaders = pHeader;
+
+ dLowSpeedInit();
+ IOMapLowSpeed.State = COM_CHANNEL_NONE_ACTIVE;
+ VarsLowSpeed.TimerState = TIMER_STOPPED;
+}
+
+void cLowSpeedCtrl(void)
+{
+ UBYTE Temp;
+ UBYTE ChannelNumber = 0;
+
+ if (IOMapLowSpeed.State != 0)
+ {
+ for (ChannelNumber = 0; ChannelNumber < NO_OF_LOWSPEED_COM_CHANNEL; ChannelNumber++)
+ {
+ //Lowspeed com is activated
+ switch (IOMapLowSpeed.ChannelState[ChannelNumber])
+ {
+ case LOWSPEED_IDLE:
+ {
+ }
+ break;
+
+ case LOWSPEED_INIT:
+ {
+ if ((pMapInput->Inputs[ChannelNumber].SensorType == LOWSPEED) || (pMapInput->Inputs[ChannelNumber].SensorType == LOWSPEED_9V))
+ {
+ if (VarsLowSpeed.TimerState == TIMER_STOPPED)
+ {
+ dLowSpeedStartTimer();
+ VarsLowSpeed.TimerState = TIMER_RUNNING;
+ }
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_LOAD_BUFFER;
+ IOMapLowSpeed.ErrorType[ChannelNumber] = LOWSPEED_NO_ERROR;
+ VarsLowSpeed.ErrorCount[ChannelNumber] = 0;
+ dLowSpeedInitPins(ChannelNumber);
+ }
+ else
+ {
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_ERROR;
+ IOMapLowSpeed.ErrorType[ChannelNumber] = LOWSPEED_CH_NOT_READY;
+ }
+ }
+ break;
+
+ case LOWSPEED_LOAD_BUFFER:
+ {
+ if ((pMapInput->Inputs[ChannelNumber].SensorType == LOWSPEED) || (pMapInput->Inputs[ChannelNumber].SensorType == LOWSPEED_9V))
+ {
+ VarsLowSpeed.OutputBuf[ChannelNumber].OutPtr = 0;
+ for (VarsLowSpeed.OutputBuf[ChannelNumber].InPtr = 0; VarsLowSpeed.OutputBuf[ChannelNumber].InPtr < IOMapLowSpeed.OutBuf[ChannelNumber].InPtr; VarsLowSpeed.OutputBuf[ChannelNumber].InPtr++)
+ {
+ VarsLowSpeed.OutputBuf[ChannelNumber].Buf[VarsLowSpeed.OutputBuf[ChannelNumber].InPtr] = IOMapLowSpeed.OutBuf[ChannelNumber].Buf[IOMapLowSpeed.OutBuf[ChannelNumber].OutPtr];
+ IOMapLowSpeed.OutBuf[ChannelNumber].OutPtr++;
+ }
+ if (dLowSpeedSendData(ChannelNumber, &VarsLowSpeed.OutputBuf[ChannelNumber].Buf[0], (VarsLowSpeed.OutputBuf[ChannelNumber].InPtr - VarsLowSpeed.OutputBuf[ChannelNumber].OutPtr)))
+ {
+ if (IOMapLowSpeed.InBuf[ChannelNumber].BytesToRx != 0)
+ {
+ dLowSpeedReceiveData(ChannelNumber, &VarsLowSpeed.InputBuf[ChannelNumber].Buf[0], IOMapLowSpeed.InBuf[ChannelNumber].BytesToRx);
+ VarsLowSpeed.RxTimeCnt[ChannelNumber] = 0;
+ }
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_COMMUNICATING;
+ IOMapLowSpeed.Mode[ChannelNumber] = LOWSPEED_TRANSMITTING;
+ }
+ else
+ {
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_ERROR;
+ IOMapLowSpeed.ErrorType[ChannelNumber] = LOWSPEED_CH_NOT_READY;
+ }
+ }
+ else
+ {
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_ERROR;
+ IOMapLowSpeed.ErrorType[ChannelNumber] = LOWSPEED_CH_NOT_READY;
+ }
+ }
+ break;
+
+ case LOWSPEED_COMMUNICATING:
+ {
+ if ((pMapInput->Inputs[ChannelNumber].SensorType == LOWSPEED) || (pMapInput->Inputs[ChannelNumber].SensorType == LOWSPEED_9V))
+ {
+ if (IOMapLowSpeed.Mode[ChannelNumber] == LOWSPEED_TRANSMITTING)
+ {
+ Temp = dLowSpeedComTxStatus(ChannelNumber); // Returns 0x00 if not done, 0x01 if success, 0xFF if error
+
+ if (Temp == LOWSPEED_COMMUNICATION_SUCCESS)
+ {
+ if (IOMapLowSpeed.InBuf[ChannelNumber].BytesToRx != 0)
+ {
+ IOMapLowSpeed.Mode[ChannelNumber] = LOWSPEED_RECEIVING;
+ }
+ else
+ {
+ IOMapLowSpeed.Mode[ChannelNumber] = LOWSPEED_DATA_RECEIVED;
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_DONE;
+ }
+ }
+ if (Temp == LOWSPEED_COMMUNICATION_ERROR)
+ {
+ //ERROR in Communication, No ACK received from SLAVE, retry send data 3 times!
+ VarsLowSpeed.ErrorCount[ChannelNumber]++;
+ if (VarsLowSpeed.ErrorCount[ChannelNumber] > MAX_RETRY_TX_COUNT)
+ {
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_ERROR;
+ IOMapLowSpeed.ErrorType[ChannelNumber] = LOWSPEED_TX_ERROR;
+ }
+ else
+ {
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_LOAD_BUFFER;
+ }
+ }
+ }
+ if (IOMapLowSpeed.Mode[ChannelNumber] == LOWSPEED_RECEIVING)
+ {
+ VarsLowSpeed.RxTimeCnt[ChannelNumber]++;
+ if (VarsLowSpeed.RxTimeCnt[ChannelNumber] > LOWSPEED_RX_TIMEOUT)
+ {
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_ERROR;
+ IOMapLowSpeed.ErrorType[ChannelNumber] = LOWSPEED_RX_ERROR;
+ }
+ Temp = dLowSpeedComRxStatus(ChannelNumber);
+ if (Temp == LOWSPEED_COMMUNICATION_SUCCESS)
+ {
+ for (VarsLowSpeed.InputBuf[ChannelNumber].OutPtr = 0; VarsLowSpeed.InputBuf[ChannelNumber].OutPtr < IOMapLowSpeed.InBuf[ChannelNumber].BytesToRx; VarsLowSpeed.InputBuf[ChannelNumber].OutPtr++)
+ {
+ IOMapLowSpeed.InBuf[ChannelNumber].Buf[IOMapLowSpeed.InBuf[ChannelNumber].InPtr] = VarsLowSpeed.InputBuf[ChannelNumber].Buf[VarsLowSpeed.InputBuf[ChannelNumber].OutPtr];
+ IOMapLowSpeed.InBuf[ChannelNumber].InPtr++;
+ if (IOMapLowSpeed.InBuf[ChannelNumber].InPtr >= SIZE_OF_LSBUF)
+ {
+ IOMapLowSpeed.InBuf[ChannelNumber].InPtr = 0;
+ }
+ VarsLowSpeed.InputBuf[ChannelNumber].Buf[VarsLowSpeed.InputBuf[ChannelNumber].OutPtr] = 0;
+ }
+ IOMapLowSpeed.Mode[ChannelNumber] = LOWSPEED_DATA_RECEIVED;
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_DONE;
+ }
+ if (Temp == LOWSPEED_COMMUNICATION_ERROR)
+ {
+ //There was and error in receiving data from the device
+ for (VarsLowSpeed.InputBuf[ChannelNumber].OutPtr = 0; VarsLowSpeed.InputBuf[ChannelNumber].OutPtr < IOMapLowSpeed.InBuf[ChannelNumber].BytesToRx; VarsLowSpeed.InputBuf[ChannelNumber].OutPtr++)
+ {
+ VarsLowSpeed.InputBuf[ChannelNumber].Buf[VarsLowSpeed.InputBuf[ChannelNumber].OutPtr] = 0;
+ }
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_ERROR;
+ IOMapLowSpeed.ErrorType[ChannelNumber] = LOWSPEED_RX_ERROR;
+ }
+ }
+ }
+ else
+ {
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_ERROR;
+ IOMapLowSpeed.ErrorType[ChannelNumber] = LOWSPEED_CH_NOT_READY;
+ }
+ }
+ break;
+
+ case LOWSPEED_ERROR:
+ {
+ IOMapLowSpeed.State = IOMapLowSpeed.State & ~LOWSPEED_CH_NUMBER[ChannelNumber];
+ if (IOMapLowSpeed.State == 0)
+ {
+ dLowSpeedStopTimer();
+ VarsLowSpeed.TimerState = TIMER_STOPPED;
+ }
+ }
+ break;
+
+ case LOWSPEED_DONE:
+ {
+ IOMapLowSpeed.State = IOMapLowSpeed.State & ~LOWSPEED_CH_NUMBER[ChannelNumber];
+ IOMapLowSpeed.ChannelState[ChannelNumber] = LOWSPEED_IDLE;
+ if (IOMapLowSpeed.State == 0)
+ {
+ dLowSpeedStopTimer();
+ VarsLowSpeed.TimerState = TIMER_STOPPED;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void cLowSpeedExit(void)
+{
+ dLowSpeedExit();
+}
diff --git a/AT91SAM7S256/Source/c_lowspeed.h b/AT91SAM7S256/Source/c_lowspeed.h
new file mode 100644
index 0000000..7930acc
--- /dev/null
+++ b/AT91SAM7S256/Source/c_lowspeed.h
@@ -0,0 +1,61 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: c_lowspeed.h $
+//
+// Version $Revision:: 11 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_lowspeed $
+//
+// Platform C
+//
+
+#ifndef C_LOWSPEED
+#define C_LOWSPEED
+
+#define LOWSPEED_RX_TIMEOUT 100
+#define LOWSPEED_COMMUNICATION_SUCCESS 0x01
+#define LOWSPEED_COMMUNICATION_ERROR 0xFF
+#define SIZE_OF_LSBUFDATA 16
+#define NO_OF_LOWSPEED_COM_CH 4
+
+enum
+{
+ LOWSPEED_CHANNEL1,
+ LOWSPEED_CHANNEL2,
+ LOWSPEED_CHANNEL3,
+ LOWSPEED_CHANNEL4
+};
+
+enum
+{
+ TIMER_STOPPED,
+ TIMER_RUNNING
+};
+
+typedef struct
+{
+ UBYTE Buf[SIZE_OF_LSBUFDATA];
+ UBYTE InPtr;
+ UBYTE OutPtr;
+}LSDATA;
+
+typedef struct
+{
+ LSDATA OutputBuf[NO_OF_LOWSPEED_COM_CH];
+ LSDATA InputBuf[NO_OF_LOWSPEED_COM_CH];
+ UBYTE RxTimeCnt[NO_OF_LOWSPEED_COM_CH];
+ UBYTE ErrorCount[NO_OF_LOWSPEED_COM_CH];
+ UBYTE Tmp;
+ UBYTE TimerState;
+}VARSLOWSPEED;
+
+void cLowSpeedInit(void* pHeader);
+void cLowSpeedCtrl(void);
+void cLowSpeedExit(void);
+
+extern const HEADER cLowSpeed;
+
+#endif
diff --git a/AT91SAM7S256/Source/c_lowspeed.iom b/AT91SAM7S256/Source/c_lowspeed.iom
new file mode 100644
index 0000000..a8e42a4
--- /dev/null
+++ b/AT91SAM7S256/Source/c_lowspeed.iom
@@ -0,0 +1,95 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: c_lowspeed.iom $
+//
+// Version $Revision:: 18 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_lowspeed $
+//
+// Platform C
+//
+
+#ifndef CLOWSPEED_IOM
+#define CLOWSPEED_IOM
+
+#define pMapLowSpeed ((IOMAPLOWSPEED*)(pHeaders[ENTRY_LOWSPEED]->pIOMap))
+
+#define MAX_RETRY_TX_COUNT 3
+#define NO_OF_LOWSPEED_COM_CHANNEL 4
+#define NO_OF_LSBUF NO_OF_LOWSPEED_COM_CHANNEL
+#define SIZE_OF_LSBUF 16
+
+//Constants referring to LowSpeedDeviceType
+enum
+{
+ ULTRA_SONIC = 2,
+ CUSTOM_LS_DEVICE
+};
+
+// Constants reffering to State
+enum
+{
+ COM_CHANNEL_NONE_ACTIVE = 0x00,
+ COM_CHANNEL_ONE_ACTIVE = 0x01,
+ COM_CHANNEL_TWO_ACTIVE = 0x02,
+ COM_CHANNEL_THREE_ACTIVE = 0x04,
+ COM_CHANNEL_FOUR_ACTIVE = 0x08
+};
+
+// Constants reffering to ChannelState
+enum
+{
+ LOWSPEED_IDLE,
+ LOWSPEED_INIT,
+ LOWSPEED_LOAD_BUFFER,
+ LOWSPEED_COMMUNICATING,
+ LOWSPEED_ERROR,
+ LOWSPEED_DONE
+};
+
+// Constants reffering to Mode
+enum
+{
+ LOWSPEED_TRANSMITTING = 1,
+ LOWSPEED_RECEIVING,
+ LOWSPEED_DATA_RECEIVED
+};
+
+// Constants reffering to ErrorType
+enum
+{
+ LOWSPEED_NO_ERROR = 0,
+ LOWSPEED_CH_NOT_READY,
+ LOWSPEED_TX_ERROR,
+ LOWSPEED_RX_ERROR
+};
+
+
+typedef struct
+{
+ UBYTE Buf[SIZE_OF_LSBUF];
+ UBYTE InPtr;
+ UBYTE OutPtr;
+ UBYTE BytesToRx;
+}LSBUF;
+
+typedef struct
+{
+ LSBUF InBuf[NO_OF_LSBUF];
+ LSBUF OutBuf[NO_OF_LSBUF];
+ UBYTE Mode[NO_OF_LSBUF];
+ UBYTE ChannelState[NO_OF_LSBUF];
+ UBYTE ErrorType[NO_OF_LSBUF];
+ UBYTE State;
+ UBYTE Speed;
+ UBYTE Spare1;
+}IOMAPLOWSPEED;
+
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_output.c b/AT91SAM7S256/Source/c_output.c
new file mode 100644
index 0000000..c91eb07
--- /dev/null
+++ b/AT91SAM7S256/Source/c_output.c
@@ -0,0 +1,169 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: c_output.c $
+//
+// Version $Revision:: 45 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_output.c $
+//
+// Platform C
+//
+
+#include <stdio.h>
+#include "stdbool.h"
+#include "stdconst.h"
+#include "modules.h"
+#include "c_output.iom"
+#include "c_output.h"
+#include "d_output.h"
+#include "c_display.iom"
+
+static IOMAPOUTPUT IOMapOutput;
+static VARSOUTPUT VarsOutput;
+
+const HEADER cOutput =
+{
+ 0x00020001L,
+ "Output",
+ cOutputInit,
+ cOutputCtrl,
+ cOutputExit,
+ (void *)&IOMapOutput,
+ (void *)&VarsOutput,
+ (UWORD)sizeof(IOMapOutput),
+ (UWORD)sizeof(VarsOutput),
+ 0x0000 //Code size - not used so far
+};
+
+
+void cOutputInit(void* pHeader)
+{
+ UBYTE Tmp;
+
+ for(Tmp = 0; Tmp < NO_OF_OUTPUTS; Tmp++)
+ {
+ IOMapOutput.Outputs[Tmp].Mode = 0x00;
+ IOMapOutput.Outputs[Tmp].Speed = 0x00;
+ IOMapOutput.Outputs[Tmp].ActualSpeed = 0x00;
+ IOMapOutput.Outputs[Tmp].TachoCnt = 0x00;
+ IOMapOutput.Outputs[Tmp].RunState = 0x00;
+ IOMapOutput.Outputs[Tmp].TachoLimit = 0x00;
+ IOMapOutput.Outputs[Tmp].RegPParameter = DEFAULT_P_GAIN_FACTOR;
+ IOMapOutput.Outputs[Tmp].RegIParameter = DEFAULT_I_GAIN_FACTOR;
+ IOMapOutput.Outputs[Tmp].RegDParameter = DEFAULT_D_GAIN_FACTOR;
+ }
+ VarsOutput.TimeCnt = 0;
+ dOutputInit();
+}
+
+void cOutputCtrl(void)
+{
+ UBYTE Tmp;
+
+ for(Tmp = 0; Tmp < NO_OF_OUTPUTS; Tmp++)
+ {
+ if (IOMapOutput.Outputs[Tmp].Flags != 0)
+ {
+ if (IOMapOutput.Outputs[Tmp].Flags & UPDATE_RESET_ROTATION_COUNT)
+ {
+ IOMapOutput.Outputs[Tmp].Flags &= ~UPDATE_RESET_ROTATION_COUNT;
+ dOutputResetRotationCaptureCount(Tmp);
+ }
+ if (IOMapOutput.Outputs[Tmp].Flags & UPDATE_RESET_COUNT)
+ {
+ IOMapOutput.Outputs[Tmp].Flags &= ~UPDATE_RESET_COUNT;
+ dOutputResetTachoLimit(Tmp);
+ }
+ if (IOMapOutput.Outputs[Tmp].Flags & UPDATE_RESET_BLOCK_COUNT)
+ {
+ IOMapOutput.Outputs[Tmp].Flags &= ~UPDATE_RESET_BLOCK_COUNT;
+ dOutputResetBlockTachoLimit(Tmp);
+ }
+ if (IOMapOutput.Outputs[Tmp].Flags & UPDATE_SPEED)
+ {
+ IOMapOutput.Outputs[Tmp].Flags &= ~UPDATE_SPEED;
+ if (IOMapOutput.Outputs[Tmp].Mode & MOTORON)
+ {
+ dOutputSetSpeed (Tmp, IOMapOutput.Outputs[Tmp].RunState, IOMapOutput.Outputs[Tmp].Speed, IOMapOutput.Outputs[Tmp].SyncTurnParameter);
+ }
+ }
+ if (IOMapOutput.Outputs[Tmp].Flags & UPDATE_TACHO_LIMIT)
+ {
+ IOMapOutput.Outputs[Tmp].Flags &= ~UPDATE_TACHO_LIMIT;
+ dOutputSetTachoLimit(Tmp, IOMapOutput.Outputs[Tmp].TachoLimit);
+ }
+ if (IOMapOutput.Outputs[Tmp].Flags & UPDATE_MODE)
+ {
+ IOMapOutput.Outputs[Tmp].Flags &= ~UPDATE_MODE;
+ if (IOMapOutput.Outputs[Tmp].Mode & BRAKE)
+ {
+ // Motor is Braked
+ dOutputSetMode(Tmp, BRAKE);
+ }
+ else
+ {
+ // Motor is floated
+ dOutputSetMode(Tmp, 0x00);
+ }
+ if (IOMapOutput.Outputs[Tmp].Mode & MOTORON)
+ {
+ if (IOMapOutput.Outputs[Tmp].Mode & REGULATED)
+ {
+ dOutputEnableRegulation(Tmp, IOMapOutput.Outputs[Tmp].RegMode);
+ }
+ else
+ {
+ dOutputDisableRegulation(Tmp);
+ }
+ }
+ else
+ {
+ dOutputSetSpeed(Tmp, 0x00, 0x00, 0x00);
+ dOutputDisableRegulation(Tmp);
+ }
+ }
+ if (IOMapOutput.Outputs[Tmp].Flags & UPDATE_PID_VALUES)
+ {
+ IOMapOutput.Outputs[Tmp].Flags &= ~UPDATE_PID_VALUES;
+ dOutputSetPIDParameters(Tmp, IOMapOutput.Outputs[Tmp].RegPParameter, IOMapOutput.Outputs[Tmp].RegIParameter, IOMapOutput.Outputs[Tmp].RegDParameter);
+ }
+ }
+ }
+ dOutputCtrl();
+ cOutputUpdateIomap();
+}
+
+void cOutputUpdateIomap(void)
+{
+ UBYTE TempCurrentMotorSpeed[NO_OF_OUTPUTS];
+ UBYTE TempRunState[NO_OF_OUTPUTS];
+ UBYTE TempMotorOverloaded[NO_OF_OUTPUTS];
+ SLONG TempTachoCount[NO_OF_OUTPUTS];
+ SLONG TempBlockTachoCount[NO_OF_OUTPUTS];
+ SLONG TempRotationCount[NO_OF_OUTPUTS];
+
+ UBYTE Tmp;
+
+ dOutputGetMotorParameters(TempCurrentMotorSpeed, TempTachoCount, TempBlockTachoCount, TempRunState, TempMotorOverloaded,TempRotationCount);
+
+ for(Tmp = 0; Tmp < NO_OF_OUTPUTS; Tmp++)
+ {
+ IOMapOutput.Outputs[Tmp].ActualSpeed = TempCurrentMotorSpeed[Tmp];
+ IOMapOutput.Outputs[Tmp].TachoCnt = TempTachoCount[Tmp];
+ IOMapOutput.Outputs[Tmp].BlockTachoCount = TempBlockTachoCount[Tmp];
+ IOMapOutput.Outputs[Tmp].RotationCount = TempRotationCount[Tmp];
+ IOMapOutput.Outputs[Tmp].Overloaded = TempMotorOverloaded[Tmp];
+ if (!(IOMapOutput.Outputs[Tmp].Flags & PENDING_UPDATES))
+ {
+ IOMapOutput.Outputs[Tmp].RunState = TempRunState[Tmp];
+ }
+ }
+}
+
+void cOutputExit(void)
+{
+ dOutputExit();
+}
diff --git a/AT91SAM7S256/Source/c_output.h b/AT91SAM7S256/Source/c_output.h
new file mode 100644
index 0000000..e3d7c43
--- /dev/null
+++ b/AT91SAM7S256/Source/c_output.h
@@ -0,0 +1,31 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: c_output.h $
+//
+// Version $Revision:: 6 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_output.h $
+//
+// Platform C
+//
+
+#ifndef C_OUTPUT
+#define C_OUTPUT
+
+typedef struct
+{
+ UBYTE TimeCnt;
+ UBYTE Tmp;
+}VARSOUTPUT;
+
+void cOutputInit(void* pHeader);
+void cOutputCtrl(void);
+void cOutputExit(void);
+void cOutputUpdateIomap(void);
+
+extern const HEADER cOutput;
+
+#endif
diff --git a/AT91SAM7S256/Source/c_output.iom b/AT91SAM7S256/Source/c_output.iom
new file mode 100644
index 0000000..e13f0f8
--- /dev/null
+++ b/AT91SAM7S256/Source/c_output.iom
@@ -0,0 +1,92 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: c_output.iom $
+//
+// Version $Revision:: 25 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_output.i $
+//
+// Platform C
+//
+
+#ifndef COUTPUT_IOM
+#define COUTPUT_IOM
+
+#define NO_OF_OUTPUTS 3
+#define pMapOutPut ((IOMAPOUTPUT*)(pHeaders[ENTRY_OUTPUT]->pIOMap))
+
+// Constants reffering to mode
+enum
+{
+ MOTORON = 0x01,
+ BRAKE = 0x02,
+ REGULATED = 0x04,
+ REG_METHOD = 0xF0 /* Regulation methods - to be designed! */
+};
+
+// Constants related to Flags
+enum
+{
+ UPDATE_MODE = 0x01,
+ UPDATE_SPEED = 0x02,
+ UPDATE_TACHO_LIMIT = 0x04,
+ UPDATE_RESET_COUNT = 0x08,
+ UPDATE_PID_VALUES = 0x10,
+ UPDATE_RESET_BLOCK_COUNT = 0x20,
+ UPDATE_RESET_ROTATION_COUNT = 0x40,
+ PENDING_UPDATES = 0x80
+};
+
+// Constant related to RunState
+#define MOTOR_RUN_STATE_IDLE 0x00
+#define MOTOR_RUN_STATE_RAMPUP 0x10
+#define MOTOR_RUN_STATE_RUNNING 0x20
+#define MOTOR_RUN_STATE_RAMPDOWN 0x40
+
+// Constant related to RegMode
+enum
+{
+ REGULATION_MODE_IDLE,
+ REGULATION_MODE_MOTOR_SPEED,
+ REGULATION_MODE_MOTOR_SYNC
+};
+
+typedef struct
+{
+ SLONG TachoCnt; /* R - Holds current number of counts, since last reset, updated every 1 mS */
+ SLONG BlockTachoCount; /* R - Holds current number of counts for the current output block */
+ SLONG RotationCount; /* R - Holds current number of counts for the rotation counter to the output */
+ ULONG TachoLimit; /* RW - Holds number of counts to travel, 0 => Run forever */
+ SWORD MotorRPM; /* !! Is not updated, will be removed later !! */
+ UBYTE Flags; /* RW - Holds flags for which data should be updated */
+ UBYTE Mode; /* RW - Holds motor mode: Run, Break, regulated, ... */
+ SBYTE Speed; /* RW - Holds the wanted speed */
+ SBYTE ActualSpeed; /* R - Holds the current motor speed */
+ UBYTE RegPParameter; /* RW - Holds the P-constant use din the regulation, Is set to a default value at init => Setting this value is optional for the user */
+ UBYTE RegIParameter; /* RW - Holds the I-constant use din the regulation, Is set to a default value at init => Setting this value is optional for the user */
+ UBYTE RegDParameter; /* RW - Holds the D-constant use din the regulation, Is set to a default value at init => Setting this value is optional for the user */
+ UBYTE RunState; /* RW - Holds the current RunState in the output module */
+ UBYTE RegMode; /* RW - Tells which regulation mode should be used */
+ UBYTE Overloaded; /* R - True if the motor has been overloaded within speed control regulation */
+ SBYTE SyncTurnParameter; /* RW - Holds the turning parameter need within MoveBlock */
+ UBYTE SpareOne;
+ UBYTE SpareTwo;
+ UBYTE SpareThree;
+}OUTPUT;
+
+
+typedef struct
+{
+ OUTPUT Outputs[NO_OF_OUTPUTS];
+ UBYTE PwnFreq;
+}IOMAPOUTPUT;
+
+
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_sound.c b/AT91SAM7S256/Source/c_sound.c
new file mode 100644
index 0000000..8e34d32
--- /dev/null
+++ b/AT91SAM7S256/Source/c_sound.c
@@ -0,0 +1,309 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dkflebun $
+//
+// Revision date $Date:: 5-02-07 13:36 $
+//
+// Filename $Workfile:: c_sound.c $
+//
+// Version $Revision:: 33 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_sound.c $
+//
+// Platform C
+//
+
+#include <stdlib.h>
+#include <string.h>
+#include "stdconst.h"
+#include "modules.h"
+#include "c_sound.iom"
+#include "c_loader.iom"
+#include "c_sound.h"
+#include "d_sound.h"
+
+static IOMAPSOUND IOMapSound;
+static VARSSOUND VarsSound;
+static HEADER **pHeaders;
+
+const HEADER cSound =
+{
+ 0x00080001L,
+ "Sound",
+ cSoundInit,
+ cSoundCtrl,
+ cSoundExit,
+ (void *)&IOMapSound,
+ (void *)&VarsSound,
+ (UWORD)sizeof(IOMapSound),
+ (UWORD)sizeof(VarsSound),
+ 0x0000 //Code size - not used so far
+};
+
+
+UWORD cSoundFile(UBYTE Cmd,UBYTE *pFile,UBYTE *pData,ULONG *pLng)
+{
+ return (pMapLoader->pFunc(Cmd,pFile,pData,pLng));
+}
+
+
+void cSoundInit(void* pHeader)
+{
+ pHeaders = pHeader;
+ IOMapSound.Flags &= ~SOUND_UPDATE;
+ IOMapSound.Flags &= ~SOUND_RUNNING;
+ IOMapSound.State = SOUND_IDLE;
+ IOMapSound.Mode = SOUND_ONCE;
+ IOMapSound.Volume = SOUNDVOLUMESTEPS;
+ IOMapSound.SampleRate = 0;
+ IOMapSound.SoundFilename[0] = 0;
+ VarsSound.BufferIn = 0;
+ VarsSound.BufferOut = 0;
+ dSoundInit();
+}
+
+void cSoundCtrl(void)
+{
+ static UWORD FileFormat;
+ static UBYTE SoundFilename[FILENAME_LENGTH + 1];
+ UWORD Handle;
+ ULONG Length;
+ UBYTE Header[FILEHEADER_LENGTH];
+ UBYTE In,Out,Tmp;
+
+ In = VarsSound.BufferIn;
+ Out = VarsSound.BufferOut;
+
+ if ((IOMapSound.Flags & SOUND_UPDATE))
+ {
+// Check if valid update
+ if (!(SOUND_TONE & IOMapSound.Mode))
+ {
+ Handle = pMapLoader->pFunc(FINDFIRST,IOMapSound.SoundFilename,SoundFilename,&Length);
+ if (!(Handle & 0x8000))
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&Handle,NULL,NULL);
+ }
+ else
+ {
+ IOMapSound.Flags &= ~SOUND_UPDATE;
+ }
+ }
+ if ((IOMapSound.Flags & SOUND_UPDATE))
+ {
+// Check for open file
+ if (!(VarsSound.File & 0x8000))
+ {
+ cSoundFile(CLOSE,(UBYTE*)&VarsSound.File,NULL,NULL);
+ VarsSound.File = 0x8000;
+ }
+
+ IOMapSound.Flags &= ~SOUND_UPDATE;
+
+ if ((SOUND_TONE & IOMapSound.Mode))
+ {
+ dSoundFreq(IOMapSound.Freq,IOMapSound.Duration,IOMapSound.Volume);
+ IOMapSound.State = SOUND_FREQ;
+ }
+ else
+ {
+ if (IOMapSound.Flags & SOUND_RUNNING)
+ {
+ dSoundStop();
+ IOMapSound.Flags &= ~SOUND_RUNNING;
+ }
+ VarsSound.File = pMapLoader->pFunc(OPENREAD,SoundFilename,NULL,&Length);
+ if (!(VarsSound.File & 0x8000))
+ {
+ Length = FILEHEADER_LENGTH;
+ pMapLoader->pFunc(READ,(UBYTE*)&VarsSound.File,Header,&Length);
+ if (Length == FILEHEADER_LENGTH)
+ {
+ FileFormat = ((UWORD)Header[0] << 8) + (UWORD)Header[1];
+
+ if (FILEFORMAT_SOUND == (FileFormat & 0xFF00))
+ {
+ if (IOMapSound.SampleRate)
+ {
+ VarsSound.SampleRate = IOMapSound.SampleRate;
+ IOMapSound.SampleRate = 0;
+ }
+ else
+ {
+ VarsSound.SampleRate = ((UWORD)Header[4] << 8) + (UWORD)Header[5];
+ }
+ dSoundVolume(IOMapSound.Volume);
+ Length = SOUNDBUFFERSIZE;
+ pMapLoader->pFunc(READ,(UBYTE*)&VarsSound.File,VarsSound.Buffer[In],&Length);
+ VarsSound.Length[In] = (UWORD)Length;
+ In++;
+ if (In >= SOUNDBUFFERS)
+ {
+ In = 0;
+ }
+ IOMapSound.State = SOUND_BUSY;
+ }
+ else
+ {
+ if (FILEFORMAT_MELODY == FileFormat)
+ {
+ Length = SOUNDBUFFERSIZE;
+ pMapLoader->pFunc(READ,(UBYTE*)&VarsSound.File,VarsSound.Buffer[In],&Length);
+ VarsSound.Length[In] = (UWORD)Length;
+ In++;
+ if (In >= SOUNDBUFFERS)
+ {
+ In = 0;
+ }
+ IOMapSound.State = SOUND_BUSY;
+ }
+ else
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsSound.File,NULL,NULL);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ switch (IOMapSound.State)
+ {
+ case SOUND_BUSY :
+ {
+ IOMapSound.Flags |= SOUND_RUNNING;
+ if (In != Out)
+ {
+ if ((FILEFORMAT_SOUND == FileFormat) || (FILEFORMAT_SOUND_COMPRESSED == FileFormat))
+ {
+ if (dSoundStart(VarsSound.Buffer[Out],VarsSound.Length[Out],VarsSound.SampleRate,(UBYTE)(FileFormat & 0x00FF)) == TRUE)
+ {
+ Out++;
+ if (Out >= SOUNDBUFFERS)
+ {
+ Out = 0;
+ }
+ }
+ }
+ else
+ {
+ if (dSoundTone(VarsSound.Buffer[Out],VarsSound.Length[Out],IOMapSound.Volume) == TRUE)
+ {
+ Out++;
+ if (Out >= SOUNDBUFFERS)
+ {
+ Out = 0;
+ }
+ }
+ }
+ }
+
+ Tmp = In;
+ Tmp++;
+ if (Tmp >= SOUNDBUFFERS)
+ {
+ Tmp = 0;
+ }
+
+ if (Tmp != Out)
+ {
+ Tmp++;
+ if (Tmp >= SOUNDBUFFERS)
+ {
+ Tmp = 0;
+ }
+ if (Tmp != Out)
+ {
+ Length = SOUNDBUFFERSIZE;
+ Handle = cSoundFile(READ,(UBYTE*)&VarsSound.File,VarsSound.Buffer[In],&Length);
+ if ((Handle & 0x8000))
+ {
+ Length = 0L;
+ }
+ VarsSound.Length[In] = (UWORD)Length;
+ if (VarsSound.Length[In] == 0)
+ {
+ if (SOUND_LOOP == IOMapSound.Mode)
+ {
+ if (!(IOMapSound.Flags & SOUND_UPDATE))
+ {
+ cSoundFile(CLOSE,(UBYTE*)&VarsSound.File,NULL,NULL);
+ VarsSound.File = cSoundFile(OPENREAD,SoundFilename,NULL,&Length);
+ Length = FILEHEADER_LENGTH;
+ cSoundFile(READ,(UBYTE*)&VarsSound.File,Header,&Length);
+ Length = SOUNDBUFFERSIZE;
+ cSoundFile(READ,(UBYTE*)&VarsSound.File,VarsSound.Buffer[In],&Length);
+ VarsSound.Length[In] = (UWORD)Length;
+ }
+ }
+ }
+ if (VarsSound.Length[In] != 0)
+ {
+ In++;
+ if (In >= SOUNDBUFFERS)
+ {
+ In = 0;
+ }
+ }
+ if (VarsSound.Length[Out] == 0)
+ {
+ if (!(VarsSound.File & 0x8000))
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsSound.File,NULL,NULL);
+ VarsSound.File = 0x8000;
+ }
+ IOMapSound.Flags &= ~SOUND_RUNNING;
+ IOMapSound.State = SOUND_IDLE;
+ }
+ }
+ }
+ }
+ break;
+
+ case SOUND_FREQ :
+ {
+ IOMapSound.Flags |= SOUND_RUNNING;
+ if (dSoundReady() == TRUE)
+ {
+ if (SOUND_LOOP & IOMapSound.Mode)
+ {
+ dSoundFreq(IOMapSound.Freq,IOMapSound.Duration,IOMapSound.Volume);
+ }
+ else
+ {
+ IOMapSound.Flags &= ~SOUND_RUNNING;
+ IOMapSound.State = SOUND_IDLE;
+ }
+ }
+ }
+ break;
+
+ case SOUND_STOP :
+ {
+ dSoundStop();
+ if (!(VarsSound.File & 0x8000))
+ {
+ pMapLoader->pFunc(CLOSE,(UBYTE*)&VarsSound.File,NULL,NULL);
+ VarsSound.File = 0x8000;
+ }
+ IOMapSound.Flags &= ~SOUND_RUNNING;
+ IOMapSound.State = SOUND_IDLE;
+ Out = In;
+ }
+ break;
+
+ }
+
+ VarsSound.BufferIn = In;
+ VarsSound.BufferOut = Out;
+}
+
+
+void cSoundExit(void)
+{
+ dSoundExit();
+}
diff --git a/AT91SAM7S256/Source/c_sound.h b/AT91SAM7S256/Source/c_sound.h
new file mode 100644
index 0000000..93e3221
--- /dev/null
+++ b/AT91SAM7S256/Source/c_sound.h
@@ -0,0 +1,44 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 26-08-05 8:37 $
+//
+// Filename $Workfile:: c_sound.h $
+//
+// Version $Revision:: 10 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_sound.h $
+//
+// Platform C
+//
+
+
+#ifndef C_SOUND
+#define C_SOUND
+
+#define SOUNDBUFFERSIZE 64 // Flash Sector size ?
+#define SOUNDBUFFERS 3 // Min 3 - max 255
+
+
+typedef struct
+{
+ UWORD Length[SOUNDBUFFERS];
+ UWORD File;
+ UWORD SampleRate;
+ UBYTE Buffer[SOUNDBUFFERS][SOUNDBUFFERSIZE];
+ UBYTE BufferIn;
+ UBYTE BufferOut;
+ UBYTE BufferTmp;
+}VARSSOUND;
+
+void cSoundInit(void* pHeaders);
+void cSoundCtrl(void);
+void cSoundExit(void);
+
+extern const HEADER cSound;
+
+#endif
diff --git a/AT91SAM7S256/Source/c_sound.iom b/AT91SAM7S256/Source/c_sound.iom
new file mode 100644
index 0000000..8baeb72
--- /dev/null
+++ b/AT91SAM7S256/Source/c_sound.iom
@@ -0,0 +1,109 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 24-01-06 11:47 $
+//
+// Filename $Workfile:: c_sound.iom $
+//
+// Version $Revision:: 18 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_sound.io $
+//
+// Platform C
+//
+
+#ifndef CSOUND_IOM
+#define CSOUND_IOM
+
+#define pMapSound ((IOMAPSOUND*)(pHeaders[ENTRY_SOUND]->pIOMap))
+
+
+/* HOW TO
+
+Start a sound file strcpy((char*)pMapSound->SoundFilename,"xxxxxxx.rso");
+ pMapSound->Volume = IOMapUi.Volume;
+ pMapSound->Mode = SOUND_ONCE;
+ pMapSound->Flags |= SOUND_UPDATE;
+
+
+Start and loop a sound file strcpy((char*)pMapSound->SoundFilename,"xxxxxxx.rso");
+ pMapSound->Volume = IOMapUi.Volume;
+ pMapSound->Mode = SOUND_LOOP;
+ pMapSound->Flags |= SOUND_UPDATE;
+
+
+Start a tone pMapSound->Freq = 440;
+ pMapSound->Duration = 1000;
+ pMapSound->Volume = IOMapUi.Volume;
+ pMapSound->Mode = SOUND_TONE;
+ pMapSound->Flags |= SOUND_UPDATE;
+
+
+Start and loop a tone pMapSound->Freq = 440;
+ pMapSound->Duration = 1000;
+ pMapSound->Volume = IOMapUi.Volume;
+ pMapSound->Mode = SOUND_TONE | SOUND_LOOP;
+ pMapSound->Flags |= SOUND_UPDATE;
+
+
+
+Test for sound finished if (!(pMapSound->Flags & (SOUND_RUNNING | SOUND_UPDATE)))
+ {
+ // FINISHED
+ }
+
+
+Abort sound or tone pMapSound->State = SOUND_STOP;
+
+
+**** Start always abort running sound or tone ****
+
+
+
+*/
+
+// Constants related to Flags
+enum
+{
+ SOUND_UPDATE = 0x01, // W - Make changes take effect
+ SOUND_RUNNING = 0x02 // R - Processing tone or file
+};
+
+// Constants related to State
+enum
+{
+ SOUND_IDLE = 0x00, // R - Idle, ready for start sound (SOUND_UPDATE)
+ SOUND_BUSY = 0x02, // R - Processing file of sound/melody data
+ SOUND_FREQ = 0x03, // R - Processing play tone request
+ SOUND_STOP = 0x04 // W - Stop sound imedately and close hardware
+};
+
+// Constants related to Mode
+enum
+{
+ SOUND_ONCE = 0x00, // W - Only play file once
+ SOUND_LOOP = 0x01, // W - Play file until writing "SOUND_STOP" into "State" or new "update"
+ SOUND_TONE = 0x02 // W - Play tone specified in Freq for Duration ms
+};
+
+typedef struct
+{
+ UWORD Freq; // RW - Tone frequency [Hz]
+ UWORD Duration; // RW - Tone duration [mS]
+ UWORD SampleRate; // RW - Sound file sample rate [2000..16000]
+ UBYTE SoundFilename[FILENAME_LENGTH + 1]; // RW - Sound/melody filename
+ UBYTE Flags; // RW - Play flag - descripted above
+ UBYTE State; // RW - Play state - descriped above
+ UBYTE Mode; // RW - Play mode - descriped above
+ UBYTE Volume; // RW - Sound/melody volume [0..4] 0 = off
+}IOMAPSOUND;
+
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/c_ui.c b/AT91SAM7S256/Source/c_ui.c
new file mode 100644
index 0000000..dd7e351
--- /dev/null
+++ b/AT91SAM7S256/Source/c_ui.c
@@ -0,0 +1,1982 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 2-03-06 13:03 $
+//
+// Filename $Workfile:: c_ui.c $
+//
+// Version $Revision:: 135 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_ui.c $
+//
+// Platform C
+//
+
+#include "stdio.h"
+#include "string.h"
+#include "ctype.h"
+#include "stdconst.h"
+#include "modules.h"
+#include "c_ui.iom"
+#include "c_ui.h"
+#include "m_sched.h"
+#include "c_display.iom"
+#include "c_loader.iom"
+#include "c_button.iom"
+#include "c_sound.iom"
+#include "c_input.iom"
+#include "c_output.iom"
+#include "c_ioctrl.iom"
+#include "c_cmd.iom"
+#include "c_comm.iom"
+#include "c_lowspeed.iom"
+
+static IOMAPUI IOMapUi;
+static VARSUI VarsUi;
+static HEADER **pHeaders;
+
+const HEADER cUi =
+{
+ 0x000C0001L,
+ "Ui",
+ cUiInit,
+ cUiCtrl,
+ cUiExit,
+ (void *)&IOMapUi,
+ (void *)&VarsUi,
+ (UWORD)sizeof(IOMapUi),
+ (UWORD)sizeof(VarsUi),
+ 0x0000 // Code size - not used so far
+};
+
+
+// ****** GENERAL GRAPHIC RESOURCES ******************************************
+
+#include "Display.txt" // Bitmap for frame used in view and datalog
+#include "LowBattery.txt" // Bitmap showed when low battery occures
+#include "Font.txt" // Font used for all text
+#include "Step.txt" // Bitmap used in On Brick Programming
+#include "Cursor.txt" // Bitmap for cursor
+#include "Running.txt" // Icon collection used for "running" symbol
+#include "Port.txt" // Font used for naming sensor ports in datalog/bluetooth
+#include "Ok.txt" // Bitmap for OK buttom in get user string
+#include "Wait.txt" // Bitmap for feedback
+#include "Fail.txt" // Bitmap for feedback
+#include "Info.txt" // Bitmap for feedback
+#include "Icons.txt" // Icon collection used for menues
+
+// ****** INTRO ANIMATION RESOURCES ******************************************
+
+#include "RCXintro_1.txt" // Bitmap for picture 1 in the intro animation
+#include "RCXintro_2.txt" // Bitmap for picture 2 in the intro animation
+#include "RCXintro_3.txt" // Bitmap for picture 3 in the intro animation
+#include "RCXintro_4.txt" // Bitmap for picture 4 in the intro animation
+#include "RCXintro_5.txt" // Bitmap for picture 5 in the intro animation
+#include "RCXintro_6.txt" // Bitmap for picture 6 in the intro animation
+#include "RCXintro_7.txt" // Bitmap for picture 7 in the intro animation
+#include "RCXintro_8.txt" // Bitmap for picture 8 in the intro animation
+#include "RCXintro_9.txt" // Bitmap for picture 9 in the intro animation
+#include "RCXintro_10.txt" // Bitmap for picture 10 in the intro animation
+#include "RCXintro_11.txt" // Bitmap for picture 11 in the intro animation
+#include "RCXintro_12.txt" // Bitmap for picture 12 in the intro animation
+#include "RCXintro_13.txt" // Bitmap for picture 13 in the intro animation
+#include "RCXintro_14.txt" // Bitmap for picture 14 in the intro animation
+#include "RCXintro_15.txt" // Bitmap for picture 15 in the intro animation
+#include "RCXintro_16.txt" // Bitmap for picture 16 in the intro animation
+
+const BMPMAP *Intro[NO_OF_INTROBITMAPS] = // Picture sequence for the intro animation
+{
+ (BMPMAP*)RCXintro_1,
+ (BMPMAP*)RCXintro_2,
+ (BMPMAP*)RCXintro_3,
+ (BMPMAP*)RCXintro_4,
+ (BMPMAP*)RCXintro_5,
+ (BMPMAP*)RCXintro_6,
+ (BMPMAP*)RCXintro_7,
+ (BMPMAP*)RCXintro_8,
+ (BMPMAP*)RCXintro_9,
+ (BMPMAP*)RCXintro_10,
+ (BMPMAP*)RCXintro_11,
+ (BMPMAP*)RCXintro_12,
+ (BMPMAP*)RCXintro_13,
+ (BMPMAP*)RCXintro_14,
+ (BMPMAP*)RCXintro_15,
+ (BMPMAP*)RCXintro_16
+};
+
+// ****** STATUS LINE GRAPHIC RESOURCES **************************************
+
+#include "Status.txt" // Status icon collection file
+
+enum STATUS_NO // Index in status icon collection file
+{
+ STATUS_NO_NOT_USED,
+ STATUS_NO_RUNNING_0,
+ STATUS_NO_RUNNING_1,
+ STATUS_NO_RUNNING_2,
+ STATUS_NO_RUNNING_3,
+ STATUS_NO_RUNNING_4,
+ STATUS_NO_RUNNING_5,
+ STATUS_NO_RUNNING_6,
+ STATUS_NO_RUNNING_7,
+ STATUS_NO_RUNNING_8,
+ STATUS_NO_RUNNING_9,
+ STATUS_NO_RUNNING_10,
+ STATUS_NO_RUNNING_11,
+ STATUS_NO_BATTERY_0,
+ STATUS_NO_BATTERY_1,
+ STATUS_NO_BATTERY_2,
+ STATUS_NO_BATTERY_3,
+ STATUS_NO_BATTERY_4,
+ STATUS_NO_BATTERY_5,
+ STATUS_NO_RECHARGEABLE_0,
+ STATUS_NO_RECHARGEABLE_1,
+ STATUS_NO_RECHARGEABLE_2,
+ STATUS_NO_RECHARGEABLE_3,
+ STATUS_NO_RECHARGEABLE_4,
+ STATUS_NO_RECHARGEABLE_5,
+ STATUS_NO_BLUETOOTH_0,
+ STATUS_NO_BLUETOOTH_1,
+ STATUS_NO_BLUETOOTH_2,
+ STATUS_NO_BLUETOOTH_3,
+ STATUS_NO_BLUETOOTH_4,
+ STATUS_NO_BLUETOOTH_5,
+ STATUS_NO_USB_0,
+ STATUS_NO_USB_1,
+ STATUS_NO_USB_2,
+ STATUS_NO_USB_3,
+ STATUS_NO_USB_4,
+ STATUS_NO_USB_5
+};
+
+// ****** BT DEVICE GRAPHIC RESOURCES ****************************************
+
+#include "Devices.txt" // Icon collection used for Blue tooth devices
+
+enum
+{
+ DEVICETYPE_UNKNOWN,
+ DEVICETYPE_NXT,
+ DEVICETYPE_PHONE,
+ DEVICETYPE_PC
+};
+
+// ****** BT CONNECTIONS GRAPHIC RESOURCES ***********************************
+
+#include "Connections.txt" // Icon collection used for Blue tooth connections
+
+// ****** FREE TEXT GRAPHIC RESOURCES ****************************************
+
+#include "Ui.txt" // Text strings that is'nt defined in menu files
+
+enum // String index in text string file
+{
+ TXT_GENERAL_EMPTY,
+ // BlueTooth connect
+ TXT_FB_BT_CONNECTING_WAIT, // "Connecting"
+ TXT_FB_BT_CONNECT_BUSY_FAIL, // "Line is busy"
+ TXT_FB_BT_CONNECTING_FAIL, // "Failed!"
+
+ // BlueTooth send file
+ TXT_FB_BT_SENDING_NO_CONN_FAIL, // "Connection?"
+ TXT_FB_BT_SENDING_WAIT, // "Sending file"
+ TXT_FB_BT_SENDING_FAIL, // "Failed!"
+
+ // BlueTooth on/off
+ TXT_FB_BT_TURNING_ON_WAIT, // "Turning on"
+ TXT_FB_BT_TURNING_ON_FAIL, // "Failed!"
+ TXT_FB_BT_TURNING_OFF_WAIT, // "Turning off"
+ TXT_FB_BT_TURNING_OFF_FAIL, // "Failed!"
+
+ // BlueTooth seach
+ TXT_FB_BT_SEARCHING_WAIT, // "Searching"
+ TXT_FB_BT_SEARCH_ABORTED_INFO, // "Aborted!"
+ TXT_FB_BT_SEARCHING_FAIL, // "Failed!"
+
+ // BlueTooth device list
+ TXT_FB_BT_REMOVE_FAIL, // "Failed!"
+
+ // BlueTooth connection list
+ TXT_FB_BT_DISCONNECT_FAIL, // "Failed!"
+
+ // On Brick Programming
+ TXT_FB_OBP_MEMORY_FULL_FAIL, // "Memory full!"
+ TXT_FB_OBP_FILE_SAVED_INFO, // "File saved"
+ TXT_FB_OBP_FILE_EXIST_FAIL, // "File exist"
+ TXT_FB_OBP_OVERWRITE_FAIL, // "overwrite!"
+
+ // File delete
+ TXT_FB_FD_FILE_DELETED_INFO, // "File deleted"
+
+ // Files delete
+ TXT_FB_FD_FILES_INFO, // "Files"
+ TXT_FB_FD_DELETED_INFO, // "deleted"
+
+ // File run
+ TXT_FILERUN_RUNNING, // "Running"
+ TXT_FILERUN_ABORTED, // "Aborted!"
+ TXT_FILERUN_ENDED, // "Ended"
+ TXT_FILERUN_FILE_ERROR, // "File error!"
+
+ // Files delete
+ TXT_FILESDELETE_DELETING_ALL, // "Deleting all"
+ TXT_FILESDELETE_S_FILES, // "%s files!"
+
+ // File types
+ TXT_FILETYPE_SOUND, // "Sound"
+ TXT_FILETYPE_LMS, // "Software"
+ TXT_FILETYPE_NXT, // "NXT"
+ TXT_FILETYPE_TRY_ME, // "Try me"
+ TXT_FILETYPE_DATA, // "Datalog"
+
+ // Get user string
+ TXT_GETUSERSTRING_PIN, // "Pin:"
+ TXT_GETUSERSTRING_FILENAME, // "Filename:"
+
+ // On Brick Programming
+ TXT_ONBRICKPROGRAMMING_PLEASE_USE_PORT, // "Please use port:"
+ TXT_ONBRICKPROGRAMMING_1_TOUCH_SENSOR, // "1 - Touch sensor"
+ TXT_ONBRICKPROGRAMMING_2_SOUND_SENSOR, // "2 - Sound sensor"
+ TXT_ONBRICKPROGRAMMING_3_LIGHT_SENSOR, // "3 - Light sensor"
+ TXT_ONBRICKPROGRAMMING_4_ULTRA_SONIC, // "4 - Ultra sonic"
+ TXT_ONBRICKPROGRAMMING_BC_LR_MOTORS, // "B/C - L/R motors"
+
+ // View
+ TXT_VIEW_SELECT, // "Select"
+
+ // BlueTooth device list
+ TXT_BTDEVICELIST_SELECT, // "Select"
+
+ // BlueTooth connection list
+ TXT_BTCONNECTLIST_SELECT, // "Select"
+
+ // Bluetooth list errors
+ TXT_FB_BT_ERROR_LR_COULD_NOT_SAVE_1, // BT save data error!
+ TXT_FB_BT_ERROR_LR_COULD_NOT_SAVE_2, //
+ TXT_FB_BT_ERROR_LR_STORE_IS_FULL_1, // BT store is full error!
+ TXT_FB_BT_ERROR_LR_STORE_IS_FULL_2, //
+ TXT_FB_BT_ERROR_LR_UNKOWN_ADDR_1, // BT unknown addr. error!
+ TXT_FB_BT_ERROR_LR_UNKOWN_ADDR_2, //
+
+ // Power of time
+ TXT_POWEROFFTIME_NEVER // "Never"
+
+};
+
+// ****** FILE TYPE GRAPHIC RESOURCES ****************************************
+
+#define ALLFILES 0x1A // Icon collection offset
+
+enum // File type id's
+{
+ FILETYPE_ALL, // 0 = All
+ FILETYPE_SOUND, // 1 = Sound
+ FILETYPE_LMS, // 2 = LMS
+ FILETYPE_NXT, // 3 = NXT
+ FILETYPE_TRYME, // 4 = Try me
+ FILETYPE_DATALOG, // 5 = Datalog
+ FILETYPES
+};
+
+const UBYTE TXT_FILE_EXT[FILETYPES][4] =
+{
+ "*", // 0 = All
+ TXT_SOUND_EXT, // 1 = Sound
+ TXT_LMS_EXT, // 2 = LMS
+ TXT_NXT_EXT, // 3 = NXT
+ TXT_TRYME_EXT, // 4 = Try me
+ TXT_DATA_EXT // 5 = Datalog
+};
+
+const UBYTE TXT_FILETYPE[FILETYPES] =
+{
+ 0, // NA
+ TXT_FILETYPE_SOUND, // 1 = Sound
+ TXT_FILETYPE_LMS, // 2 = LM
+ TXT_FILETYPE_NXT, // 3 = NXT
+ TXT_FILETYPE_TRY_ME,// 4 = Try me
+ TXT_FILETYPE_DATA // 5 = Datalog
+};
+
+// ****** POWER OFF DEFINITIONS **********************************************
+
+#define POWER_OFF_TIME_STEPS 6
+#define POWER_OFF_TIME_DEFAULT 3
+
+const UBYTE PowerOffTimeSteps[POWER_OFF_TIME_STEPS] = { 0,2,5,10,30,60 }; // [min]
+
+// ****** BATTERY DEFINITIONS ************************************************
+
+#define BATTERYLIMITS 4 // [Cnt]
+#define BATTERYLIMITHYST 100 // [mV]
+#define RECHARGEABLELIMITHYST 50 // [mV]
+
+const UWORD BatteryLimits[BATTERYLIMITS] =
+{
+ 6100,6500,7000,7500 // [mV]
+};
+
+const UWORD RechargeableLimits[BATTERYLIMITS] =
+{
+ 7100,7200,7300,7500 // [mV]
+};
+
+//******* UI MENU FILE HANDLER *************************************************************************
+
+#include "Mainmenu.rms"
+#include "Submenu01.rms"
+#include "Submenu02.rms"
+#include "Submenu04.rms"
+#include "Submenu05.rms"
+#include "Submenu06.rms"
+#include "Submenu07.rms"
+
+
+SWORD cUiMenuFile(UBYTE Cmd,UBYTE *pFile,UBYTE *pData,ULONG *pLng)
+{
+ SWORD Result;
+ UBYTE *pFilePointer;
+
+ Result = -1;
+ switch (Cmd)
+ {
+ case OPENREADLINEAR :
+ {
+ if (strcmp((char*)pFile,"Mainmenu.rms") == 0)
+ {
+ pFilePointer = (UBYTE*)MAINMENU;
+ Result = 0;
+ }
+ if (strcmp((char*)pFile,"Submenu01.rms") == 0)
+ {
+ pFilePointer = (UBYTE*)SUBMENU01;
+ Result = 0;
+ }
+ if (strcmp((char*)pFile,"Submenu02.rms") == 0)
+ {
+ pFilePointer = (UBYTE*)SUBMENU02;
+ Result = 0;
+ }
+ if (strcmp((char*)pFile,"Submenu04.rms") == 0)
+ {
+ pFilePointer = (UBYTE*)SUBMENU04;
+ Result = 0;
+ }
+ if (strcmp((char*)pFile,"Submenu05.rms") == 0)
+ {
+ pFilePointer = (UBYTE*)SUBMENU05;
+ Result = 0;
+ }
+ if (strcmp((char*)pFile,"Submenu06.rms") == 0)
+ {
+ pFilePointer = (UBYTE*)SUBMENU06;
+ Result = 0;
+ }
+ if (strcmp((char*)pFile,"Submenu07.rms") == 0)
+ {
+ pFilePointer = (UBYTE*)SUBMENU07;
+ Result = 0;
+ }
+ if (Result == 0)
+ {
+ *pLng = ((UWORD)pFilePointer[2] << 8) + (UWORD)pFilePointer[3] + FILEHEADER_LENGTH;
+ *((ULONG*)pData) = (ULONG)pFilePointer;
+ }
+ }
+ break;
+
+ }
+
+ return (Result);
+}
+
+//******************************************************************************************************
+
+UBYTE* cUiGetString(UBYTE No) // Get string in text string file
+{
+ UBYTE *Result = NULL;
+ TXT *pUi;
+ UWORD Tmp;
+
+ pUi = (TXT*)Ui;
+ if (No)
+ {
+ if (No <= pUi->ItemsY)
+ {
+ Tmp = No - 1;
+ Tmp *= pUi->ItemCharsX;
+ Result = &(pUi->Data[Tmp]);
+ }
+ }
+
+ return (Result);
+}
+
+
+UBYTE cUiReadButtons(void) // Read buttons
+{
+ UBYTE Result = BUTTON_NONE;
+
+ if (!(IOMapUi.Flags & UI_DISABLE_LEFT_RIGHT_ENTER))
+ {
+ if ((pMapButton->State[BTN3] & PRESSED_STATE))
+ {
+ Result = BUTTON_LEFT;
+ }
+ if ((pMapButton->State[BTN2] & PRESSED_STATE))
+ {
+ Result = BUTTON_RIGHT;
+ }
+ if ((pMapButton->State[BTN4] & PRESSED_STATE))
+ {
+ Result = BUTTON_ENTER;
+ }
+ }
+ if (!(IOMapUi.Flags & UI_DISABLE_EXIT))
+ {
+ if ((pMapButton->State[BTN1] & PRESSED_STATE))
+ {
+ Result = BUTTON_EXIT;
+ }
+ }
+ if (Result == BUTTON_NONE)
+ {
+ // All buttons released
+ VarsUi.ButtonOld = BUTTON_NONE;
+ VarsUi.ButtonTime = BUTTON_DELAY_TIME;
+ }
+ else
+ {
+ // Some button pressed
+ if (VarsUi.ButtonOld == BUTTON_NONE)
+ {
+ // Just pressed
+ VarsUi.ButtonOld = Result;
+ VarsUi.ButtonTimer = 0;
+ }
+ else
+ {
+ // Still pressed
+ Result = BUTTON_NONE;
+
+ if (VarsUi.ButtonTimer >= VarsUi.ButtonTime)
+ {
+ VarsUi.ButtonTimer = 0;
+ VarsUi.ButtonTime = BUTTON_REPEAT_TIME;
+ if ((VarsUi.ButtonOld == BUTTON_LEFT) || (VarsUi.ButtonOld == BUTTON_RIGHT))
+ {
+ // If arrow repeat
+ Result = VarsUi.ButtonOld;
+ }
+ }
+ }
+ }
+ if (VarsUi.ButtonOld == BUTTON_NONE)
+ {
+ // If no key - check interface
+ Result = IOMapUi.Button;
+ IOMapUi.Button = BUTTON_NONE;
+ }
+ if (Result != BUTTON_NONE)
+ {
+ // If key - play key sound file
+ sprintf((char*)pMapSound->SoundFilename,"%s.%s",(char*)UI_KEYCLICK_SOUND,(char*)TXT_SOUND_EXT);
+ pMapSound->Volume = IOMapUi.Volume;
+ pMapSound->Mode = SOUND_ONCE;
+ pMapSound->Flags |= SOUND_UPDATE;
+
+ // Reset power down timer
+ IOMapUi.Flags |= UI_RESET_SLEEP_TIMER;
+ }
+
+ return (Result);
+}
+
+
+void cUiListLeft(UBYTE Limit,UBYTE *Center)
+{
+ UBYTE Tmp;
+
+ Tmp = *Center;
+ if (Tmp > 1)
+ {
+ Tmp--;
+ }
+ else
+ {
+ if (Limit > 2)
+ {
+ Tmp = Limit;
+ }
+ }
+ *Center = Tmp;
+}
+
+
+void cUiListRight(UBYTE Limit,UBYTE *Center)
+{
+ UBYTE Tmp;
+
+ Tmp = *Center;
+ if (Tmp < Limit)
+ {
+ Tmp++;
+ }
+ else
+ {
+ if (Limit > 2)
+ {
+ Tmp = 1;
+ }
+ }
+ *Center = Tmp;
+}
+
+
+void cUiListCalc(UBYTE Limit,UBYTE *Center,UBYTE *Left,UBYTE *Right)
+{
+ switch (Limit)
+ {
+ case 1 :
+ {
+ *Left = 0;
+ *Right = 0;
+ }
+ break;
+
+ case 2 :
+ {
+ if ((*Center) == 1)
+ {
+ *Left = 0;
+ *Right = 2;
+ }
+ else
+ {
+ *Left = 1;
+ *Right = 0;
+ }
+ }
+ break;
+
+ default :
+ {
+ *Left = *Center - 1;
+ if ((*Left) < 1)
+ {
+ *Left = Limit;
+ }
+ *Right = *Center + 1;
+ if ((*Right) > Limit)
+ {
+ *Right = 1;
+ }
+ }
+ break;
+
+ }
+}
+
+
+UBYTE* cUiGetMenuPointer(UBYTE FileNo)
+{
+ ULONG Lng;
+ UWORD Handle;
+ UBYTE TmpBuffer[FILENAME_LENGTH + 1];
+ UBYTE *pPointer;
+
+ if (FileNo)
+ {
+ sprintf((char*)TmpBuffer,"Submenu%02X.rms",(UWORD)FileNo);
+ }
+ else
+ {
+ sprintf((char*)TmpBuffer,"Mainmenu.rms");
+ }
+ Handle = cUiMenuFile(OPENREADLINEAR,TmpBuffer,(UBYTE*)&pPointer,&Lng);
+ if ((Handle & 0x8000))
+ {
+ pPointer = NULL;
+ }
+ else
+ {
+ cUiMenuFile(CLOSE,(UBYTE*)&Handle,NULL,NULL);
+ }
+
+ return (pPointer);
+}
+
+
+ULONG cUiMenuGetId(MENUITEM *pMenuItem)
+{
+ ULONG MenuId;
+
+ MenuId = (ULONG)pMenuItem->ItemId01;
+ MenuId |= (ULONG)pMenuItem->ItemId23 << 8;
+ MenuId |= (ULONG)pMenuItem->ItemId45 << 16;
+ MenuId |= (ULONG)pMenuItem->ItemId67 << 24;
+
+ return (MenuId);
+}
+
+
+ULONG cUiMenuGetSpecialMask(MENUITEM *pMenuItem)
+{
+ ULONG Mask;
+
+ Mask = 0;
+ if (pMenuItem != NULL)
+ {
+ Mask = (ULONG)pMenuItem->SpecialMask0;
+ Mask |= (ULONG)pMenuItem->SpecialMask1 << 8;
+ Mask |= (ULONG)pMenuItem->SpecialMask2 << 16;
+ Mask |= (ULONG)pMenuItem->SpecialMask3 << 24;
+ }
+
+ return (Mask);
+}
+
+
+UBYTE* cUiMenuGetIconImage(UBYTE No)
+{
+ UBYTE *Image;
+
+ Image = NULL;
+ if (No < (Icons->ItemsX * Icons->ItemsY))
+ {
+ Image = (UBYTE*)&Icons->Data[No * Icons->ItemPixelsX * (Icons->ItemPixelsY / 8)];
+ }
+
+ return (Image);
+}
+
+
+ULONG cUiMenuMotherId(ULONG Id,UBYTE Level)
+{
+ ULONG MotherIdMask;
+
+ MotherIdMask = 0xFFFFFFFFL >> ((8 - Level) * 4);
+ MotherIdMask |= 0xFFFFFFFFL << ((Level + 1) * 4);
+
+ return (Id & MotherIdMask);
+}
+
+
+UBYTE cUiMenuIdValid(MENUFILE *pMenuFile,ULONG Id)
+{
+ ULONG SpecialMask;
+ ULONG MotherId;
+ UBYTE Level;
+ UBYTE Result;
+
+ Result = FALSE;
+ Level = pMenuFile->MenuLevel;
+
+ if (Level)
+ {
+ SpecialMask = pMenuFile->MenuLevels[Level - 1].SpecialFlags;
+ MotherId = pMenuFile->MenuLevels[Level - 1].Id;
+ if ((SpecialMask & MENU_SKIP_THIS_MOTHER_ID))
+ {
+ MotherId &= ~(0x0000000F << ((Level - 1) * 4));
+ SpecialMask >>= 28;
+ MotherId |= (SpecialMask << ((Level - 1) * 4));
+ }
+ if (MotherId == cUiMenuMotherId(Id,Level))
+ {
+ Id >>= (Level * 4);
+ if ((Id & 0x0000000F) && (!(Id & 0xFFFFFFF0)))
+ {
+ Result = TRUE;
+ }
+ }
+ }
+ else
+ {
+ Id >>= (Level * 4);
+ if ((Id & 0x0000000F) && (!(Id & 0xFFFFFFF0)))
+ {
+ Result = TRUE;
+ }
+ }
+
+ return (Result);
+}
+
+
+UBYTE cUiMenuGetNoOfMenus(MENU *pMenu,MENUFILE *pMenuFile)
+{
+ ULONG MenuId;
+ UBYTE NoOfMenus;
+ UBYTE Index;
+
+ NoOfMenus = 0;
+ for (Index = 0;Index < pMenu->Items;Index++)
+ {
+ MenuId = cUiMenuGetId(&pMenu->Data[Index]);
+
+ if (cUiMenuIdValid(pMenuFile,MenuId) == TRUE)
+ {
+ if ((cUiMenuGetSpecialMask(&pMenu->Data[Index]) & MENU_ONLY_BT_ON))
+ {
+ // BT module must be on
+ if (!(IOMapUi.BluetoothState & BT_STATE_OFF))
+ {
+ // Yes
+ NoOfMenus++;
+ }
+ }
+ else
+ {
+ if ((cUiMenuGetSpecialMask(&pMenu->Data[Index]) & MENU_ONLY_DATALOG_ENABLED))
+ {
+ // Datalog menu must be enabled
+ if (!(VarsUi.NVData & 0x80))
+ {
+ // Yes
+ NoOfMenus++;
+ }
+ }
+ else
+ {
+ // No restrictions
+ NoOfMenus++;
+ }
+ }
+ }
+ }
+
+ return (NoOfMenus);
+}
+
+
+UBYTE cUiGetMenuItemIndex(MENU *pMenu,MENUFILE *pMenuFile,UBYTE No)
+{
+ ULONG MenuId;
+ UBYTE NoOfMenus;
+ UBYTE Index;
+ UBYTE TmpIndex = 0;
+
+ NoOfMenus = 0;
+ for (Index = 0;(Index < pMenu->Items) && (No != NoOfMenus);Index++)
+ {
+ MenuId = cUiMenuGetId(&pMenu->Data[Index]);
+
+ if (cUiMenuIdValid(pMenuFile,MenuId) == TRUE)
+ {
+ if ((cUiMenuGetSpecialMask(&pMenu->Data[Index]) & MENU_ONLY_BT_ON))
+ {
+ // BT module must be on
+ if (!(IOMapUi.BluetoothState & BT_STATE_OFF))
+ {
+ // Yes
+ TmpIndex = Index;
+ NoOfMenus++;
+ }
+ }
+ else
+ {
+ if ((cUiMenuGetSpecialMask(&pMenu->Data[Index]) & MENU_ONLY_DATALOG_ENABLED))
+ {
+ // Datalog menu must be enabled
+ if (!(VarsUi.NVData & 0x80))
+ {
+ // Yes
+ TmpIndex = Index;
+ NoOfMenus++;
+ }
+ }
+ else
+ {
+ // No restrictions
+ TmpIndex = Index;
+ NoOfMenus++;
+ }
+ }
+ }
+ }
+ if (No != NoOfMenus)
+ {
+ Index = TmpIndex + 1;
+ }
+
+ return (Index);
+}
+
+
+
+UBYTE cUiMenuGetNo(MENU *pMenu,ULONG Id,UBYTE Level)
+{
+ ULONG MenuId;
+ ULONG MotherId;
+ UBYTE Index;
+ UBYTE No;
+ UBYTE NoOfItems;
+
+ No = 0;
+ NoOfItems = 0;
+
+ MotherId = cUiMenuMotherId(Id,Level);
+
+ for (Index = 0;(Index < pMenu->Items) && (No == 0);Index++)
+ {
+ MenuId = cUiMenuGetId(&pMenu->Data[Index]);
+
+ // Scanning all id's until No is found
+ if (!(MenuId >> ((Level + 1) * 4)))
+ {
+ // MenuId is above or on actual level
+ if (((MenuId >> (Level * 4)) & 0x0000000F))
+ {
+ // MenuId is on actual level
+ if (MotherId == cUiMenuMotherId(MenuId,Level))
+ {
+ // Same mother id
+ NoOfItems++;
+ if (MenuId == Id)
+ {
+ No = NoOfItems;
+ }
+ }
+ }
+ }
+ }
+
+ return (No);
+}
+
+void cUiUpdateStatus(void)
+{
+ UWORD Tmp;
+ UWORD Hyst;
+ UWORD *pTmp;
+ UBYTE Pointer;
+
+ if (++VarsUi.UpdateCounter >= RUN_STATUS_CHANGE_TIME)
+ {
+ VarsUi.UpdateCounter = 0;
+
+ // Update running status icon pointer
+ if (++VarsUi.Running >= 12)
+ {
+ VarsUi.Running = 0;
+ }
+
+ // Get battery voltage limits
+ if ((IoFromAvr.Battery & 0x8000))
+ {
+ IOMapUi.Rechargeable = 1;
+ pTmp = (UWORD*)RechargeableLimits;
+ Hyst = RECHARGEABLELIMITHYST;
+ }
+ else
+ {
+ IOMapUi.Rechargeable = 0;
+ pTmp = (UWORD*)BatteryLimits;
+ Hyst = BATTERYLIMITHYST;
+ }
+
+ // Calculate battery voltage
+ Tmp = IoFromAvr.Battery & 0x03FF;
+ Tmp = (UWORD)((float)Tmp * BATTERY_COUNT_TO_MV);
+
+ IOMapUi.BatteryVoltage = Tmp;
+
+ // Find new battery state
+ Pointer = 0;
+ while ((Tmp > pTmp[Pointer]) && (Pointer < BATTERYLIMITS))
+ {
+ Pointer++;
+ }
+
+ // Change battery state
+ if (Pointer != IOMapUi.BatteryState)
+ {
+ if (Pointer > IOMapUi.BatteryState)
+ {
+ if (Tmp > (pTmp[IOMapUi.BatteryState] + Hyst))
+ {
+ IOMapUi.BatteryState = Pointer;
+ }
+ }
+ else
+ {
+ IOMapUi.BatteryState = Pointer;
+ }
+ }
+
+ // Control toggle and bitmap
+ if (IOMapUi.BatteryState)
+ {
+ VarsUi.BatteryToggle = 0;
+ VarsUi.LowBatt = 0;
+ }
+ else
+ {
+ if (VarsUi.LowBatt < 255)
+ {
+ VarsUi.LowBatt++;
+ }
+
+ if (VarsUi.BatteryToggle)
+ {
+ VarsUi.BatteryToggle = 0;
+ }
+ else
+ {
+ VarsUi.BatteryToggle = 1;
+ }
+ }
+
+ // Ensure frequently status updates
+ IOMapUi.Flags |= UI_UPDATE;
+ }
+
+ if ((IOMapUi.Flags & UI_ENABLE_STATUS_UPDATE))
+ {
+ if ((IOMapUi.Flags & UI_UPDATE) || (IOMapUi.Flags & UI_REDRAW_STATUS))
+ {
+ VarsUi.ErrorTimer = 0;
+ pMapDisplay->pStatusText = (UBYTE*)VarsUi.StatusText;
+
+ // Status line update nessesary
+ if (IOMapUi.BatteryState < Status->ItemsX)
+ {
+ // Update battery status icons
+ if (IoFromAvr.Battery & 0x8000)
+ {
+ VarsUi.NewStatusIcons[STATUSICON_BATTERY] = STATUS_NO_RECHARGEABLE_0 + IOMapUi.BatteryState + VarsUi.BatteryToggle;
+ }
+ else
+ {
+ VarsUi.NewStatusIcons[STATUSICON_BATTERY] = STATUS_NO_BATTERY_0 + IOMapUi.BatteryState + VarsUi.BatteryToggle;
+ }
+ }
+
+ // Update bluetooth status icons
+ if ((IOMapUi.BluetoothState & (BT_STATE_VISIBLE | BT_STATE_CONNECTED | BT_STATE_OFF)) < Status->ItemsX)
+ {
+ VarsUi.NewStatusIcons[STATUSICON_BLUETOOTH] = STATUS_NO_BLUETOOTH_0 + (IOMapUi.BluetoothState & (BT_STATE_VISIBLE | BT_STATE_CONNECTED | BT_STATE_OFF));
+ }
+
+ // Update usb status icons
+ if (IOMapUi.UsbState < 6)
+ {
+ VarsUi.NewStatusIcons[STATUSICON_USB] = STATUS_NO_USB_0 + IOMapUi.UsbState;
+ }
+
+ // Update running status icons
+ if (IOMapUi.RunState == FALSE)
+ {
+ VarsUi.Running = 0;
+ }
+ VarsUi.NewStatusIcons[STATUSICON_VM] = STATUS_NO_RUNNING_0 + VarsUi.Running;
+
+ // Update only changed status icons
+ for (Pointer = 0;Pointer < STATUSICONS;Pointer++)
+ {
+ if ((pMapDisplay->StatusIcons[Pointer] != VarsUi.NewStatusIcons[Pointer]))
+ {
+ pMapDisplay->StatusIcons[Pointer] = VarsUi.NewStatusIcons[Pointer];
+ pMapDisplay->UpdateMask |= STATUSICON_BIT(Pointer);
+ }
+ }
+
+ if ((IOMapUi.Flags & UI_REDRAW_STATUS))
+ {
+ // Entire status line needs to be redrawed
+ if (pMapComm->BrickData.Name[0])
+ {
+ for (Pointer = 0;Pointer < STATUSTEXT_SIZE;Pointer++)
+ {
+ VarsUi.StatusText[Pointer] = pMapComm->BrickData.Name[Pointer];
+ }
+ VarsUi.StatusText[Pointer] = 0;
+ }
+ pMapDisplay->EraseMask |= SPECIAL_BIT(STATUSTEXT);
+ pMapDisplay->UpdateMask |= SPECIAL_BIT(STATUSTEXT);
+ pMapDisplay->UpdateMask |= (SPECIAL_BIT(TOPLINE) | STATUSICON_BITS);
+ }
+
+ // Clear update flag
+ IOMapUi.Flags &= ~UI_REDRAW_STATUS;
+ IOMapUi.Flags &= ~UI_UPDATE;
+ }
+ }
+ else
+ {
+ pMapDisplay->UpdateMask &= ~(STATUSICON_BITS | SPECIAL_BIT(TOPLINE) | SPECIAL_BIT(STATUSTEXT));
+ }
+}
+
+
+
+
+void cUiMenuCallFunction(UBYTE Function,UBYTE Parameter)
+{
+ if (Function)
+ {
+ VarsUi.Function = Function;
+ VarsUi.Parameter = Parameter;
+ }
+}
+
+
+void cUiMenuNextFile(void)
+{
+ MENU *pTmpMenu;
+
+ pTmpMenu = (MENU*)cUiGetMenuPointer(VarsUi.pMenuLevel->NextFileNo);
+ if (pTmpMenu != NULL)
+ {
+ if (VarsUi.MenuFileLevel < (MENUFILELEVELS - 1))
+ {
+ VarsUi.MenuFileLevel++;
+ VarsUi.MenuFiles[VarsUi.MenuFileLevel].FileId = VarsUi.pMenuLevel->NextFileNo;
+ VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel = 0;
+ VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevels[VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel].ItemIndex = VarsUi.pMenuLevel->NextMenuNo;
+ IOMapUi.pMenu = pTmpMenu;
+ }
+ }
+}
+
+
+void cUiMenuPrevFile(void)
+{
+ if (VarsUi.MenuFileLevel)
+ {
+ VarsUi.MenuFileLevel--;
+ IOMapUi.pMenu = (MENU*)cUiGetMenuPointer(VarsUi.MenuFiles[VarsUi.MenuFileLevel].FileId);
+ }
+}
+
+
+void cUiMenuNext(void)
+{
+ if (VarsUi.pMenuFile->MenuLevel < (MENULEVELS - 1))
+ {
+ VarsUi.pMenuFile->MenuLevel++;
+ VarsUi.pMenuFile->MenuLevels[VarsUi.pMenuFile->MenuLevel].ItemIndex = VarsUi.pMenuLevel->NextMenuNo;
+ }
+}
+
+
+void cUiMenuPrev(void)
+{
+ if (VarsUi.pMenuFile->MenuLevel)
+ {
+ VarsUi.pMenuFile->MenuLevel--;
+ }
+}
+
+
+void cUiMenuEnter(void)
+{
+ // Call function with parameter (if pressent)
+ if (!(VarsUi.pMenuLevel->SpecialFlags & MENU_INIT_CALLS))
+ {
+ cUiMenuCallFunction(VarsUi.pMenuLevel->FunctionNo,VarsUi.pMenuLevel->Parameter);
+ }
+
+ if (VarsUi.EnterOnlyCalls != TRUE)
+ {
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_ENTER_LEAVES_MENUFILE))
+ {
+ cUiMenuPrevFile();
+ }
+ else
+ {
+ // Load new menu file (if pressent)
+ if (VarsUi.pMenuLevel->NextFileNo)
+ {
+ cUiMenuNextFile();
+ }
+ else
+ {
+ // Activate next menu level (if pressent)
+ if (VarsUi.pMenuLevel->NextMenuNo)
+ {
+ cUiMenuNext();
+ }
+ }
+ }
+ IOMapUi.State = NEXT_MENU;
+ }
+ else
+ {
+ VarsUi.EnterOnlyCalls = FALSE;
+ IOMapUi.State = DRAW_MENU;
+ }
+}
+
+
+void cUiMenuExit(void)
+{
+
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_EXIT_CALLS))
+ {
+ // Call function with parameter (if pressent)
+ if (!(VarsUi.pMenuLevel->SpecialFlags & MENU_INIT_CALLS))
+ {
+ cUiMenuCallFunction(VarsUi.pMenuLevel->FunctionNo,VarsUi.pMenuLevel->Parameter);
+ }
+ }
+
+ // Call function with 0xFF (if ordered)
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_EXIT_CALLS_WITH_FF))
+ {
+ cUiMenuCallFunction(VarsUi.pMenuLevel->FunctionNo,MENU_EXIT);
+ }
+
+ if (VarsUi.ExitOnlyCalls != TRUE)
+ {
+ if ((VarsUi.pMenuFile->MenuLevel) && (!(VarsUi.pMenuLevel->SpecialFlags & MENU_EXIT_LEAVES_MENUFILE)))
+ {
+ if (!(VarsUi.pMenuLevel->SpecialFlags & MENU_EXIT_LOAD_MENU))
+ {
+ cUiMenuPrev();
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_BACK_TWICE))
+ {
+ if (VarsUi.pMenuFile->MenuLevel)
+ {
+ cUiMenuPrev();
+ }
+ VarsUi.SecondTime = FALSE;
+ }
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_BACK_THREE_TIMES))
+ {
+ if (VarsUi.pMenuFile->MenuLevel)
+ {
+ cUiMenuPrev();
+ }
+ if (VarsUi.pMenuFile->MenuLevel)
+ {
+ cUiMenuPrev();
+ }
+ VarsUi.SecondTime = FALSE;
+ }
+ }
+ else
+ {
+ VarsUi.EnterOnlyCalls = FALSE;
+ VarsUi.ExitOnlyCalls = FALSE;
+ if (VarsUi.pMenuLevel->NextFileNo)
+ {
+ cUiMenuNextFile();
+ }
+ else
+ {
+ // Activate next menu level (if pressent)
+ if (VarsUi.pMenuLevel->NextMenuNo)
+ {
+ cUiMenuNext();
+ }
+ }
+ }
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_EXIT_LOAD_POINTER))
+ {
+ VarsUi.pMenuFile->MenuLevels[VarsUi.pMenuFile->MenuLevel].ItemIndex = (UBYTE)((VarsUi.pMenuLevel->SpecialFlags) >> 24) & 0x0F;
+ }
+ }
+ else
+ {
+ if (!(VarsUi.pMenuLevel->SpecialFlags & MENU_EXIT_LOAD_MENU))
+ {
+ cUiMenuPrevFile();
+ }
+ else
+ {
+ VarsUi.EnterOnlyCalls = FALSE;
+ VarsUi.ExitOnlyCalls = FALSE;
+ if (VarsUi.pMenuLevel->NextFileNo)
+ {
+ cUiMenuNextFile();
+ }
+ else
+ {
+ // Activate next menu level (if pressent)
+ if (VarsUi.pMenuLevel->NextMenuNo)
+ {
+ cUiMenuNext();
+ }
+ }
+ }
+ }
+ IOMapUi.State = NEXT_MENU;
+ }
+ else
+ {
+ VarsUi.ExitOnlyCalls = FALSE;
+ IOMapUi.State = DRAW_MENU;
+ }
+}
+
+
+void cUiLoadLevel(UBYTE FileLevel,UBYTE MenuLevel,UBYTE MenuIndex)
+{
+ UBYTE Tmp;
+
+ VarsUi.MenuFileLevel = FileLevel;
+ VarsUi.MenuFiles[FileLevel].MenuLevel = MenuLevel;
+ VarsUi.MenuFiles[FileLevel].MenuLevels[MenuLevel].ItemIndex = MenuIndex;
+ IOMapUi.pMenu = (MENU*)cUiGetMenuPointer(VarsUi.MenuFiles[VarsUi.MenuFileLevel].FileId);
+
+ VarsUi.pMenuFile = &VarsUi.MenuFiles[VarsUi.MenuFileLevel];
+ VarsUi.pMenuLevel = &VarsUi.pMenuFile->MenuLevels[VarsUi.pMenuFile->MenuLevel];
+
+ // Count no of menues on current level
+ VarsUi.pMenuLevel->Items = cUiMenuGetNoOfMenus(IOMapUi.pMenu,VarsUi.pMenuFile);
+
+ if (VarsUi.pMenuLevel->Items)
+ {
+ // if items > 0 -> prepare allways center icon
+ Tmp = cUiGetMenuItemIndex(IOMapUi.pMenu,VarsUi.pMenuFile,VarsUi.pMenuLevel->ItemIndex);
+
+ if (VarsUi.pMenuItem != &IOMapUi.pMenu->Data[Tmp - 1])
+ {
+ VarsUi.pMenuItem = &IOMapUi.pMenu->Data[Tmp - 1];
+ VarsUi.SecondTime = FALSE;
+ }
+
+ // Save center menu item parameters
+ VarsUi.pMenuLevel->Id = cUiMenuGetId(VarsUi.pMenuItem);
+ VarsUi.pMenuLevel->IconImageNo = VarsUi.pMenuItem->IconImageNo;
+ VarsUi.pMenuLevel->IconText = VarsUi.pMenuItem->IconText;
+ VarsUi.pMenuLevel->SpecialFlags = cUiMenuGetSpecialMask(VarsUi.pMenuItem);
+ VarsUi.pMenuLevel->FunctionNo = VarsUi.pMenuItem->FunctionIndex;
+ VarsUi.pMenuLevel->Parameter = VarsUi.pMenuItem->FunctionParameter;
+ VarsUi.pMenuLevel->NextFileNo = VarsUi.pMenuItem->FileLoadNo;
+ VarsUi.pMenuLevel->NextMenuNo = VarsUi.pMenuItem->NextMenu;
+ }
+}
+
+#include "Functions.inl"
+
+
+void cUiInit(void* pHeader)
+{
+ pHeaders = pHeader;
+ VarsUi.Initialized = FALSE;
+ IOMapUi.BluetoothState = BT_STATE_OFF;
+ IOMapUi.UsbState = 0;
+ IOMapUi.State = INIT_DISPLAY;
+}
+
+
+void cUiCtrl(void)
+{
+ UBYTE Tmp;
+
+// Testcode for low battery voltage
+/*
+ if ((pMapInput->Inputs[0].InvalidData != INVALID_DATA) && (pMapInput->Inputs[0].ADRaw < 500))
+ {
+ if (VarsUi.LowBatt < 255)
+ {
+ VarsUi.LowBatt++;
+ }
+ }
+ else
+ {
+ VarsUi.LowBatt = 0;
+ }
+*/
+//
+
+// Testcode for BT connect request
+/*
+ if ((pMapInput->Inputs[0].InvalidData != INVALID_DATA) && (pMapInput->Inputs[0].ADRaw < 500))
+ {
+ IOMapUi.BluetoothState |= BT_CONNECT_REQUEST | BT_PIN_REQUEST;
+ }
+*/
+//
+
+// Testcode for BT error attention
+/*
+ if ((pMapInput->Inputs[0].InvalidData != INVALID_DATA) && (pMapInput->Inputs[0].ADRaw < 500))
+ {
+ IOMapUi.Error = LR_UNKOWN_ADDR;
+ IOMapUi.BluetoothState |= BT_ERROR_ATTENTION;
+ }
+*/
+//
+
+// Testcode for execute program
+/*
+ if ((pMapInput->Inputs[0].InvalidData != INVALID_DATA) && (pMapInput->Inputs[0].ADRaw < 500))
+ {
+ if ((!(IOMapUi.Flags & UI_EXECUTE_LMS_FILE)) && (IOMapUi.State > INIT_MENU))
+ {
+ strcpy((char*)IOMapUi.LMSfilename,"Untitled-1.rxe");
+ IOMapUi.Flags |= UI_EXECUTE_LMS_FILE;
+ }
+ }
+*/
+//
+
+// Testcode for force off
+/*
+ if ((pMapInput->Inputs[0].InvalidData != INVALID_DATA) && (pMapInput->Inputs[0].ADRaw < 500) && (VarsUi.Initialized == TRUE))
+ {
+ IOMapUi.ForceOff = TRUE;
+ }
+*/
+//
+
+
+ VarsUi.CRPasskey++;
+ VarsUi.ButtonTimer++;
+ VarsUi.OBPTimer++;
+ switch (IOMapUi.State)
+ {
+ case INIT_DISPLAY : // Load font and icons
+ {
+ VarsUi.Initialized = FALSE;
+
+ IOMapUi.Flags = UI_BUSY;
+ IOMapUi.RunState = 1;
+ IOMapUi.BatteryState = 0;
+ IOMapUi.Error = 0;
+ IOMapUi.ForceOff = FALSE;
+ VarsUi.LowBatt = 0;
+ VarsUi.LowBattHasOccured = 0;
+
+ pMapDisplay->pFont = (FONT*)Font;
+ pMapDisplay->pStatusIcons = (ICON*)Status;
+ pMapDisplay->pStatusText = (UBYTE*)VarsUi.StatusText;
+ pMapDisplay->pStepIcons = (ICON*)Step;
+
+ VarsUi.State = 0;
+ VarsUi.Pointer = 0;
+ VarsUi.Timer = -INTRO_START_TIME;
+
+ VarsUi.FNOFState = 0;
+ VarsUi.FBState = 0;
+
+ VarsUi.UpdateCounter = 0;
+ VarsUi.Running = 0;
+ VarsUi.BatteryToggle = 0;
+
+ VarsUi.GUSState = 0;
+
+ IOMapUi.pMenu = (MENU*)cUiGetMenuPointer(0);
+ IOMapUi.State = INIT_INTRO;
+
+ pMapDisplay->EraseMask = SCREEN_BIT(SCREEN_BACKGROUND);
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)Intro[VarsUi.Pointer];
+ pMapDisplay->UpdateMask = BITMAP_BIT(BITMAP_1);
+ pMapDisplay->Flags |= DISPLAY_ON;
+
+ cUiNVReadByte();
+ IOMapUi.Volume = cUiNVReadVolumeCount();
+ IOMapUi.SleepTimeout = PowerOffTimeSteps[cUiNVReadPowerOnTimeCount()];
+ }
+ break;
+
+ case INIT_LOW_BATTERY :
+ {
+ if (++VarsUi.Timer >= (INTRO_LOWBATT_TIME))
+ {
+ VarsUi.LowBattHasOccured = 2;
+ pMapDisplay->EraseMask = SCREEN_BIT(SCREEN_BACKGROUND);
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)Intro[VarsUi.Pointer];
+ pMapDisplay->UpdateMask = BITMAP_BIT(BITMAP_1);
+ IOMapUi.Flags &= ~UI_ENABLE_STATUS_UPDATE;
+ VarsUi.State = 0;
+ VarsUi.Pointer = 0;
+ VarsUi.Timer = -INTRO_START_TIME;
+ IOMapUi.State = INIT_INTRO;
+ }
+ }
+ break;
+
+ case INIT_INTRO :
+ {
+ if (VarsUi.LowBattHasOccured == 1)
+ {
+ IOMapUi.Flags |= UI_ENABLE_STATUS_UPDATE;
+ IOMapUi.Flags |= UI_UPDATE;
+ IOMapUi.Flags |= UI_REDRAW_STATUS;
+ VarsUi.Timer = 0;
+ IOMapUi.State = INIT_LOW_BATTERY;
+ }
+ else
+ {
+ if (VarsUi.LowBattHasOccured == 0)
+ {
+ if (VarsUi.LowBatt)
+ {
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)LowBattery;
+ pMapDisplay->UpdateMask = BITMAP_BIT(BITMAP_1);
+ VarsUi.LowBattHasOccured = 1;
+ }
+ }
+ if (++VarsUi.Timer >= (INTRO_SHIFT_TIME))
+ {
+ switch (VarsUi.State)
+ {
+ case 0 :
+ {
+ pMapDisplay->Flags &= ~DISPLAY_REFRESH;
+ VarsUi.State++;
+ }
+ break;
+
+ case 1 :
+ {
+ if ((pMapDisplay->Flags & DISPLAY_REFRESH_DISABLED))
+ {
+ if (VarsUi.Pointer < NO_OF_INTROBITMAPS)
+ {
+ pMapDisplay->EraseMask |= BITMAP_BIT(BITMAP_1);
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)Intro[VarsUi.Pointer];
+ pMapDisplay->UpdateMask = BITMAP_BIT(BITMAP_1);
+ if (VarsUi.Pointer == 11)
+ {
+ sprintf((char*)pMapSound->SoundFilename,"%s.%s",(char*)UI_STARTUP_SOUND,(char*)TXT_SOUND_EXT);
+ pMapSound->Volume = IOMapUi.Volume;
+ pMapSound->Mode = SOUND_ONCE;
+ pMapSound->Flags |= SOUND_UPDATE;
+ }
+ VarsUi.Pointer++;
+ }
+ else
+ {
+ pMapDisplay->Flags |= DISPLAY_REFRESH;
+ IOMapUi.State = INIT_WAIT;
+ }
+ VarsUi.State++;
+ }
+ }
+ break;
+
+ default :
+ {
+ if (!(pMapDisplay->UpdateMask & BITMAP_BIT(BITMAP_1)))
+ {
+ pMapDisplay->Flags |= DISPLAY_REFRESH;
+ VarsUi.Timer = 0;
+ VarsUi.State = 0;
+ }
+ }
+ break;
+
+ }
+ }
+ }
+ }
+ break;
+
+ case INIT_WAIT :
+ {
+ if (++VarsUi.Timer >= INTRO_STOP_TIME)
+ {
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ IOMapUi.State = INIT_MENU;
+ }
+ }
+ break;
+
+ case INIT_MENU :
+ {
+ // Restart menu system
+ VarsUi.Function = 0;
+ VarsUi.MenuFileLevel = 0;
+
+ cUiLoadLevel(0,0,1);
+ cUiLoadLevel(0,1,1);
+
+ VarsUi.EnterOnlyCalls = FALSE;
+ VarsUi.ExitOnlyCalls = FALSE;
+
+ IOMapUi.State = NEXT_MENU;
+ }
+ break;
+
+ case NEXT_MENU : // prepare icons
+ {
+ // Init various variables
+ VarsUi.State = 0;
+
+ // Init icon pointers
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = NULL;
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = NULL;
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = NULL;
+
+ cUiLoadLevel(VarsUi.MenuFileLevel,VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel,VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevels[VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel].ItemIndex);
+
+ // Find menu icons
+ if (VarsUi.pMenuLevel->Items)
+ {
+ // Prepare center icon
+ pMapDisplay->pMenuIcons[MENUICON_CENTER] = cUiMenuGetIconImage(VarsUi.pMenuLevel->IconImageNo);
+ pMapDisplay->pMenuText = VarsUi.pMenuLevel->IconText;
+
+ if (VarsUi.pMenuLevel->Items == 2)
+ {
+ // if 2 menues -> prepare left or right icon
+ if (VarsUi.pMenuLevel->ItemIndex == 1)
+ {
+ Tmp = cUiGetMenuItemIndex(IOMapUi.pMenu,VarsUi.pMenuFile,2);
+ if (Tmp)
+ {
+ Tmp--;
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = cUiMenuGetIconImage(IOMapUi.pMenu->Data[Tmp].IconImageNo);
+ }
+ }
+ else
+ {
+ Tmp = cUiGetMenuItemIndex(IOMapUi.pMenu,VarsUi.pMenuFile,1);
+ if (Tmp)
+ {
+ Tmp--;
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = cUiMenuGetIconImage(IOMapUi.pMenu->Data[Tmp].IconImageNo);
+ }
+ }
+ }
+
+ if (VarsUi.pMenuLevel->Items > 2)
+ {
+ // if more menues -> prepare left and right icon
+ if (VarsUi.pMenuLevel->ItemIndex > 1)
+ {
+ Tmp = VarsUi.pMenuLevel->ItemIndex -1;
+ }
+ else
+ {
+ Tmp = VarsUi.pMenuLevel->Items;
+ }
+ Tmp = cUiGetMenuItemIndex(IOMapUi.pMenu,VarsUi.pMenuFile,Tmp);
+ if (Tmp)
+ {
+ Tmp--;
+ pMapDisplay->pMenuIcons[MENUICON_LEFT] = cUiMenuGetIconImage(IOMapUi.pMenu->Data[Tmp].IconImageNo);
+
+ }
+ if (VarsUi.pMenuLevel->ItemIndex < VarsUi.pMenuLevel->Items)
+ {
+ Tmp = VarsUi.pMenuLevel->ItemIndex + 1;
+ }
+ else
+ {
+ Tmp = 1;
+ }
+ Tmp = cUiGetMenuItemIndex(IOMapUi.pMenu,VarsUi.pMenuFile,Tmp);
+ if (Tmp)
+ {
+ Tmp--;
+ pMapDisplay->pMenuIcons[MENUICON_RIGHT] = cUiMenuGetIconImage(IOMapUi.pMenu->Data[Tmp].IconImageNo);
+ }
+ }
+ }
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_ENTER_ONLY_CALLS))
+ {
+ VarsUi.EnterOnlyCalls = TRUE;
+ }
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_EXIT_ONLY_CALLS))
+ {
+ VarsUi.ExitOnlyCalls = TRUE;
+ }
+
+ IOMapUi.State = DRAW_MENU;
+ }
+ break;
+
+ case DRAW_MENU : // If no function active -> erase screen, draw statusline and menu icons
+ {
+ if (VarsUi.Function)
+ {
+ // Function active
+ if (VarsUi.Function < FUNC_NO_MAX)
+ {
+ if (Functions[VarsUi.Function](VarsUi.Parameter) == 0)
+ {
+ VarsUi.Function = 0;
+ }
+ }
+ else
+ {
+ VarsUi.Function = 0;
+ }
+ }
+ else
+ {
+ // function inactive - erase screen
+ if (!(VarsUi.pMenuLevel->SpecialFlags & MENU_LEAVE_BACKGROUND))
+ {
+ pMapDisplay->EraseMask |= SCREEN_BIT(SCREEN_LARGE);
+
+ // Draw only icons, frame and icon text
+ pMapDisplay->UpdateMask = (MENUICON_BITS | SPECIAL_BIT(FRAME_SELECT) | SPECIAL_BIT(MENUTEXT));
+ pMapDisplay->TextLinesCenterFlags = 0;
+ }
+ else
+ {
+ pMapDisplay->EraseMask |= (SPECIAL_BIT(MENUTEXT) | MENUICON_BITS);
+
+ // Draw icons, frame and icon text
+ pMapDisplay->UpdateMask |= (MENUICON_BITS | SPECIAL_BIT(FRAME_SELECT) | SPECIAL_BIT(MENUTEXT));
+ }
+
+ // Draw status
+ IOMapUi.Flags |= (UI_ENABLE_STATUS_UPDATE | UI_UPDATE | UI_REDRAW_STATUS);
+
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_INIT_CALLS_WITH_0) && (VarsUi.SecondTime == FALSE))
+ {
+ VarsUi.SecondTime = TRUE;
+ cUiMenuCallFunction(VarsUi.pMenuLevel->FunctionNo,MENU_INIT);
+ }
+ else
+ {
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_INIT_CALLS_WITH_1) && (VarsUi.SecondTime == FALSE))
+ {
+ VarsUi.SecondTime = TRUE;
+ cUiMenuCallFunction(VarsUi.pMenuLevel->FunctionNo,MENU_INIT_ALTERNATIVE);
+ }
+ else
+ {
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_INIT_CALLS) && (VarsUi.SecondTime == FALSE))
+ {
+ VarsUi.SecondTime = TRUE;
+ cUiMenuCallFunction(VarsUi.pMenuLevel->FunctionNo,VarsUi.pMenuLevel->Parameter);
+ }
+ else
+ {
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_AUTO_PRESS_ENTER))
+ {
+ IOMapUi.State = ENTER_PRESSED;
+ }
+ else
+ {
+ IOMapUi.State = TEST_BUTTONS;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case TEST_BUTTONS : // Test buttons to execute new functions and new menus
+ {
+ if (VarsUi.Initialized == FALSE)
+ {
+ VarsUi.Initialized = TRUE;
+ IOMapUi.Flags &= ~UI_BUSY;
+ }
+
+ switch (cUiReadButtons())
+ {
+ case BUTTON_LEFT :
+ {
+ IOMapUi.State = LEFT_PRESSED;
+ }
+ break;
+
+ case BUTTON_RIGHT :
+ {
+ IOMapUi.State = RIGHT_PRESSED;
+ }
+ break;
+
+ case BUTTON_ENTER :
+ {
+ IOMapUi.State = ENTER_PRESSED;
+ }
+ break;
+
+ case BUTTON_EXIT :
+ {
+ if (!(VarsUi.pMenuLevel->SpecialFlags & MENU_EXIT_DISABLE))
+ {
+ IOMapUi.State = EXIT_PRESSED;
+ }
+ }
+ break;
+
+ }
+
+ }
+ break;
+
+ case LEFT_PRESSED :
+ {
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_LEFT_RIGHT_AS_CALL))
+ {
+ cUiMenuCallFunction(VarsUi.pMenuLevel->FunctionNo,MENU_LEFT);
+ }
+ else
+ {
+ VarsUi.SecondTime = FALSE;
+ VarsUi.EnterOnlyCalls = FALSE;
+ VarsUi.ExitOnlyCalls = FALSE;
+
+ if (VarsUi.pMenuLevel->ItemIndex > 1)
+ {
+ VarsUi.pMenuLevel->ItemIndex--;
+ }
+ else
+ {
+ if (VarsUi.pMenuLevel->Items > 2)
+ {
+ VarsUi.pMenuLevel->ItemIndex = VarsUi.pMenuLevel->Items;
+ }
+ }
+ }
+ IOMapUi.State = NEXT_MENU;
+ }
+ break;
+
+ case RIGHT_PRESSED :
+ {
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_LEFT_RIGHT_AS_CALL))
+ {
+ cUiMenuCallFunction(VarsUi.pMenuLevel->FunctionNo,MENU_RIGHT);
+ }
+ else
+ {
+ VarsUi.SecondTime = FALSE;
+ VarsUi.EnterOnlyCalls = FALSE;
+ VarsUi.ExitOnlyCalls = FALSE;
+
+ if (VarsUi.pMenuLevel->ItemIndex < VarsUi.pMenuLevel->Items)
+ {
+ VarsUi.pMenuLevel->ItemIndex++;
+ }
+ else
+ {
+ if (VarsUi.pMenuLevel->Items > 2)
+ {
+ VarsUi.pMenuLevel->ItemIndex = 1;
+ }
+ }
+ }
+ IOMapUi.State = NEXT_MENU;
+ }
+ break;
+
+ case ENTER_PRESSED :
+ {
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_ENTER_ACT_AS_EXIT))
+ {
+ cUiMenuExit();
+ }
+ else
+ {
+ cUiMenuEnter();
+ }
+ }
+ break;
+
+ case EXIT_PRESSED :
+ {
+ if ((VarsUi.pMenuLevel->SpecialFlags & MENU_EXIT_ACT_AS_ENTER))
+ {
+ cUiMenuEnter();
+ }
+ else
+ {
+ cUiMenuExit();
+ }
+ }
+ break;
+
+ case CONNECT_REQUEST :
+ {
+ if (cUiBTConnectRequest(MENU_INIT) == 0)
+ {
+ IOMapUi.BluetoothState &= ~BT_CONNECT_REQUEST;
+ cUiLoadLevel(0,1,1);
+ IOMapUi.State = NEXT_MENU;
+ IOMapUi.Flags &= ~UI_BUSY;
+ }
+ }
+ break;
+
+ case EXECUTE_FILE :
+ {
+ cUiLoadLevel(0,1,1);
+ cUiMenuEnter();
+ cUiLoadLevel(VarsUi.MenuFileLevel,VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel,VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevels[VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel].ItemIndex);
+ cUiMenuEnter();
+ cUiLoadLevel(VarsUi.MenuFileLevel,VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel,VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevels[VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel].ItemIndex);
+ cUiMenuEnter();
+ cUiLoadLevel(VarsUi.MenuFileLevel,VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel,VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevels[VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel].ItemIndex);
+
+ VarsUi.Function = 0;
+ VarsUi.State = 0;
+ VarsUi.Pointer = 0;
+ VarsUi.FNOFState = 0;
+ VarsUi.FBState = 0;
+ VarsUi.GUSState = 0;
+
+ strcpy((char*)VarsUi.SelectedFilename,(char*)IOMapUi.LMSfilename);
+ IOMapUi.State = EXECUTING_FILE;
+ VarsUi.FileType = FILETYPE_LMS;
+ cUiFileRun(MENU_INIT);
+ }
+ break;
+
+ case EXECUTING_FILE :
+ {
+ if (cUiFileRun(MENU_RUN) == 0)
+ {
+ IOMapUi.Flags &= ~UI_EXECUTE_LMS_FILE;
+ IOMapUi.State = NEXT_MENU;
+ }
+ }
+ break;
+
+ case LOW_BATTERY :
+ {
+ if (DISPLAY_IDLE)
+ {
+ if (cUiReadButtons() != BUTTON_NONE)
+ {
+ pMapDisplay->Flags &= ~DISPLAY_POPUP;
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)VarsUi.LowBattSavedBitmap;
+ IOMapUi.State = VarsUi.LowBattSavedState;
+ IOMapUi.Flags &= ~UI_BUSY;
+ }
+ }
+ }
+ break;
+
+ case BT_ERROR :
+ {
+ switch (IOMapUi.Error)
+ {
+ case LR_COULD_NOT_SAVE :
+ {
+ Tmp = TXT_FB_BT_ERROR_LR_COULD_NOT_SAVE_1;
+ }
+ break;
+
+ case LR_STORE_IS_FULL :
+ {
+ Tmp = TXT_FB_BT_ERROR_LR_STORE_IS_FULL_1;
+ }
+ break;
+
+ default :
+ {
+ Tmp = TXT_FB_BT_ERROR_LR_UNKOWN_ADDR_1;
+ }
+ break;
+
+ }
+
+ if (!cUiFeedback((BMPMAP*)Fail,Tmp,Tmp + 1,DISPLAY_SHOW_ERROR_TIME))
+ {
+ IOMapUi.BluetoothState &= ~BT_ERROR_ATTENTION;
+ cUiLoadLevel(0,1,1);
+ IOMapUi.State = NEXT_MENU;
+ IOMapUi.Flags &= ~UI_BUSY;
+ }
+ }
+ break;
+
+ }
+
+ // Check for low battery voltage
+ if (VarsUi.LowBatt >= LOW_BATT_THRESHOLD)
+ {
+ if (!VarsUi.LowBattHasOccured)
+ {
+ if (DISPLAY_IDLE)
+ {
+ if (!(IOMapUi.Flags & UI_BUSY))
+ {
+ pMapDisplay->Flags |= DISPLAY_POPUP;
+ VarsUi.LowBattHasOccured = 1;
+ VarsUi.LowBattSavedState = IOMapUi.State;
+ VarsUi.LowBattSavedBitmap = (UBYTE*)pMapDisplay->pBitmaps[BITMAP_1];
+ pMapDisplay->pBitmaps[BITMAP_1] = (BMPMAP*)LowBattery;
+ pMapDisplay->UpdateMask = BITMAP_BIT(BITMAP_1);
+ IOMapUi.Flags |= UI_REDRAW_STATUS;
+ IOMapUi.Flags |= UI_BUSY;
+ IOMapUi.State = LOW_BATTERY;
+ }
+ }
+ }
+ }
+
+ // Check for incomming BT connection requests
+ if ((IOMapUi.BluetoothState & BT_CONNECT_REQUEST) && (!(IOMapUi.Flags & UI_BUSY)))
+ {
+ IOMapUi.Flags |= UI_BUSY;
+ IOMapUi.State = CONNECT_REQUEST;
+ }
+
+ // Check for BT errors
+ if ((IOMapUi.BluetoothState & BT_ERROR_ATTENTION) && (!(IOMapUi.Flags & UI_BUSY)))
+ {
+ IOMapUi.Flags |= UI_BUSY;
+ IOMapUi.State = BT_ERROR;
+ }
+
+ // Check for incomming execute program
+ if ((IOMapUi.Flags & UI_EXECUTE_LMS_FILE) && (!(IOMapUi.Flags & UI_BUSY)))
+ {
+ // Reset power down timer
+ IOMapUi.Flags |= UI_RESET_SLEEP_TIMER;
+
+ // Set state and busy
+ IOMapUi.Flags |= UI_BUSY;
+ IOMapUi.State = EXECUTE_FILE;
+ }
+
+ // Check for power timeout
+ if ((IOMapUi.Flags & UI_RESET_SLEEP_TIMER))
+ {
+ IOMapUi.Flags &= ~UI_RESET_SLEEP_TIMER;
+ IOMapUi.SleepTimer = 0;
+ VarsUi.SleepTimer = 0;
+ }
+ if (IOMapUi.SleepTimeout)
+ {
+ if (++VarsUi.SleepTimer >= 60000)
+ {
+ VarsUi.SleepTimer = 0;
+ if (++IOMapUi.SleepTimer >= IOMapUi.SleepTimeout)
+ {
+ IOMapUi.ForceOff = TRUE;
+ }
+ }
+ }
+ else
+ {
+ IOMapUi.Flags |= UI_RESET_SLEEP_TIMER;
+ }
+
+ // Check for "long prees on exit" power off
+ if ((pMapButton->State[BTN1] & LONG_PRESSED_EV) && (pMapCmd->ProgStatus != PROG_RUNNING) && (VarsUi.Initialized == TRUE) && (VarsUi.State == 0))
+ {
+ IOMapUi.ForceOff = TRUE;
+ }
+
+ // Check for "force" off
+ if (IOMapUi.ForceOff != FALSE)
+ {
+ IOMapUi.ForceOff = FALSE;
+ VarsUi.Function = FUNC_NO_OFF;
+ VarsUi.Parameter = MENU_INIT;
+ VarsUi.State = 0;
+ IOMapUi.State = DRAW_MENU;
+ }
+
+ // Update status line
+ cUiUpdateStatus();
+}
+
+
+void cUiExit(void)
+{
+ VarsUi.Initialized = FALSE;
+ IOMapUi.State = INIT_DISPLAY;
+}
diff --git a/AT91SAM7S256/Source/c_ui.h b/AT91SAM7S256/Source/c_ui.h
new file mode 100644
index 0000000..07a4237
--- /dev/null
+++ b/AT91SAM7S256/Source/c_ui.h
@@ -0,0 +1,352 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 3-02-06 12:50 $
+//
+// Filename $Workfile:: c_ui.h $
+//
+// Version $Revision:: 75 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_ui.h $
+//
+// Platform C
+//
+
+#ifndef C_UI
+#define C_UI
+
+#define NO_OF_FEEDBACK_CHARS 12 // Chars left when bitmap also showed
+#define SIZE_OF_CURSOR 16 // Bitmap size of cursor (header + 8x8 pixels)
+#define SIZE_OF_PORTBITMAP 11 // Bitmap size of port no (header + 3x8 pixels)
+#define NO_OF_STATUSICONS 4 // Status icons
+
+#define NO_OF_INTROBITMAPS 16 // Intro bitmaps
+#define INTRO_START_TIME 1000 // Intro startup time [mS]
+#define INTRO_SHIFT_TIME 100 // Intro inter bitmap time [mS]
+#define INTRO_STOP_TIME 1000 // Intro stop time [mS]
+#define INTRO_LOWBATT_TIME 2000 // Low battery show time at power up [mS]
+
+#define MAX_VOLUME 4 // Max volume in UI [cnt]
+
+#define BATTERY_COUNT_TO_MV 13.848 // Battery count to mV factor [mV/cnt]
+#define LOW_BATT_THRESHOLD 6 // Low batt conunts before warning
+
+#define BUTTON_DELAY_TIME 800 // Delay before first repeat [mS]
+#define BUTTON_REPEAT_TIME 200 // Repeat time [mS]
+
+#define RUN_BITMAP_CHANGE_TIME 125 // Running bimap update time [mS]
+#define RUN_STATUS_CHANGE_TIME 167 // Running status update time [mS]
+
+#define DISPLAY_SHOW_ERROR_TIME 2500 // Error string show time [mS]
+#define DISPLAY_SHOW_TIME 1500 // Min. response display time [mS]
+#define DISPLAY_VIEW_UPDATE 250 // Display update time [mS]
+#define MIN_DISPLAY_UPDATE_TIME 50 // OBP min graphics update time [mS]
+#define MIN_SENSOR_READ_TIME 25 // Time between sensor reads [mS]
+
+#define ARM_WAIT_FOR_POWER_OFF 250 // Time for off command to execute [mS]
+
+// Menu special flags
+
+#define MENU_SKIP_THIS_MOTHER_ID 0x00000001L // Used to seek next common menu (i0000000)
+ // Free
+#define MENU_ENTER_ACT_AS_EXIT 0x00000004L // Enter button acts as exit button
+#define MENU_BACK_TWICE 0x00000008L // Exit twice on exit button
+#define MENU_EXIT_ACT_AS_ENTER 0x00000010L // Exit button acts as enter button
+#define MENU_LEAVE_BACKGROUND 0x00000020L // Don't erase background at next menu
+#define MENU_EXIT_CALLS_WITH_FF 0x00000040L // Exit button calls function with MENU_EXIT
+#define MENU_EXIT_LEAVES_MENUFILE 0x00000080L // Exit leaves menu file
+#define MENU_INIT_CALLS_WITH_0 0x00000100L // Menu init calls with MENU_INIT
+#define MENU_LEFT_RIGHT_AS_CALL 0x00000200L // Left calls with MENU_LEFT and right with MENU_RIGHT
+#define MENU_ENTER_ONLY_CALLS 0x00000400L // Enter calls only it does not change menues
+#define MENU_EXIT_ONLY_CALLS 0x00000800L // Exit calls only it does not change menues
+#define MENU_AUTO_PRESS_ENTER 0x00001000L // Enter button is pressed automaticly
+#define MENU_ENTER_LEAVES_MENUFILE 0x00002000L // Enter leaves menufile
+#define MENU_INIT_CALLS 0x00004000L // Init calls instead of enter
+#define MENU_ACCEPT_INCOMMING_REQUEST 0x00008000L // Accept incomming BT connection request
+#define MENU_BACK_THREE_TIMES 0x00010000L // Exit three times on exit button
+#define MENU_EXIT_DISABLE 0x00020000L // Disable exit button
+#define MENU_EXIT_LOAD_POINTER 0x00040000L // Load item index on exit (0i000000)
+#define MENU_EXIT_CALLS 0x00080000L // Exit calls as enter
+#define MENU_INIT_CALLS_WITH_1 0x00100000L // Menu init calls with MENU_INIT
+#define MENU_EXIT_LOAD_MENU 0x00200000L // Exit loads next menu
+#define MENU_ONLY_BT_ON 0x00400000L // Only valid when bluecore is on
+#define MENU_ONLY_DATALOG_ENABLED 0x00800000L // Only valid when datalog is enabled
+
+// Menu function call parameter
+
+#define MENU_SENSOR_EMPTY 0x01 // Empty
+#define MENU_SENSOR_SOUND_DB 0x02 // Sound sensor dB
+#define MENU_SENSOR_SOUND_DBA 0x03 // Sound sensor dBA
+#define MENU_SENSOR_LIGHT 0x04 // Light sensor with flood light
+#define MENU_SENSOR_LIGHT_AMB 0x05 // Light sensor without flood light
+#define MENU_SENSOR_LIGHT_OLD 0x06 // Light sensor old with flood light
+#define MENU_SENSOR_TOUCH 0x07 // Touch sensor
+#define MENU_SENSOR_MOTOR_DEG 0x08 // Motor sensor degrees
+#define MENU_SENSOR_MOTOR_ROT 0x09 // Motor sensor rotations
+#define MENU_SENSOR_ROTATION 0x0A // Rotation sensor ticks
+#define MENU_SENSOR_ULTRASONIC_IN 0x0B // Ultrasonic sensor inch
+#define MENU_SENSOR_ULTRASONIC_CM 0x0C // Ultrasonic sensor cm
+#define MENU_SENSOR_TEMP_C 0x0D // Temp sensor celcius
+#define MENU_SENSOR_TEMP_F 0x0E // Temp sensor fahrenheit
+#define MENU_SENSOR_INVALID 0x0F // Invalid
+
+#define MENU_PORT_EMPTY 0x11 // NA
+#define MENU_PORT_1 0x12 // Port 1
+#define MENU_PORT_2 0x13 // Port 2
+#define MENU_PORT_3 0x14 // Port 3
+#define MENU_PORT_4 0x15 // Port 4
+#define MENU_PORT_A 0x16 // Port A
+#define MENU_PORT_B 0x17 // Port B
+#define MENU_PORT_C 0x18 // Port C
+#define MENU_PORT_INVALID 0x19 // Invalid
+
+#define MENU_ACTION_EMPTY 0x21 // Empty
+#define MENU_ACTION_FORWARD_1 0x22 // Forward until
+#define MENU_ACTION_FORWARD_2 0x23 // Forward 5
+#define MENU_ACTION_BACK_LEFT_2 0x24 // Back left 2
+#define MENU_ACTION_TURN_LEFT_1 0x25 // Turn left until
+#define MENU_ACTION_TURN_LEFT_2 0x26 // Turn left 2
+#define MENU_ACTION_BACK_RIGHT_1 0x27 // Back right until
+#define MENU_ACTION_TURN_RIGHT_1 0x28 // Turn right until
+#define MENU_ACTION_TURN_RIGHT_2 0x29 // Turn right 2
+#define MENU_ACTION_BACK_LEFT_1 0x2A // Back left until
+#define MENU_ACTION_TONE_1 0x2B // Tone 1
+#define MENU_ACTION_TONE_2 0x2C // Tone 2
+#define MENU_ACTION_BACKWARD_1 0x2D // Backward until
+#define MENU_ACTION_BACKWARD_2 0x2E // Backward 5
+#define MENU_ACTION_BACK_RIGHT_2 0x2F // Back right 2
+#define MENU_ACTION_INVALID 0x30 // Invalid
+
+#define MENU_WAIT_EMPTY 0x41 // Empty
+#define MENU_WAIT_LIGHT 0x42 // Light
+#define MENU_WAIT_SEEK_OBJ 0x43 // Seek obj.
+#define MENU_WAIT_SOUND 0x44 // Sound
+#define MENU_WAIT_TOUCH 0x45 // Touch
+#define MENU_WAIT_1 0x46 // Wait 2
+#define MENU_WAIT_2 0x47 // Wait 5
+#define MENU_WAIT_3 0x48 // Wait 10
+#define MENU_WAIT_DARK 0x49 // Dark
+#define MENU_WAIT_INVALID 0x4A // Invalid
+
+#define MENU_INIT 0x00 // Init
+#define MENU_INIT_ALTERNATIVE 0x01 // Init alternative
+#define MENU_DRAW 0xE9 // Draw
+#define MENU_OFF 0xEA // Off
+#define MENU_ON 0xEB // On
+#define MENU_OPEN_STREAM 0xEC // Open stream
+#define MENU_OVERWRITE 0xED // Overwrite file
+#define MENU_CALCULATE 0xEE // Calculate
+#define MENU_ENTER 0xEF // Enter
+#define MENU_DISCONNECT 0xF0 // Disconnect BT
+#define MENU_DELETE 0xF1 // Delete
+#define MENU_SELECT 0xF2 // Select
+#define MENU_RUN_SILENT 0xF3 // Run without graphics
+#define MENU_TOGGLE 0xF4 // Toggle
+#define MENU_CONNECT 0xF5 // Connect BT
+#define MENU_UPDATE 0xF6 // Update
+#define MENU_TEXT 0xF7 // Text
+#define MENU_RUN 0xF8 // Run
+#define MENU_SEND 0xF9 // Send
+#define MENU_SAVE 0xFA // Save
+#define MENU_STOP 0xFB // Stop
+#define MENU_LOOP 0xFC // Loop
+#define MENU_LEFT 0xFD // Left
+#define MENU_RIGHT 0xFE // Right
+#define MENU_EXIT 0xFF // Exit
+
+#define MENULEVELS 10 // Max no of levels in one file (8 + 2 virtual)
+#define MENUFILELEVELS 3 // Max deept in menu file pool
+
+typedef struct // VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevels[VarsUi.MenuLevel].
+{
+ ULONG Id; // Menu item id
+ UBYTE *IconText; // Menu item icon text pointer
+ ULONG SpecialFlags; // Menu item special behaivor
+ UBYTE IconImageNo; // Menu item icon image no
+ UBYTE FunctionNo; // Menu item function call no (0 = none)
+ UBYTE Parameter; // Menu item function call parameter
+ UBYTE NextFileNo; // Menu item next menu file no (0 = none)
+ UBYTE NextMenuNo; // Menu item next menu no (0 = none)
+
+ UBYTE ItemIndex; // Menu item index on level
+ UBYTE Items; // Menu items on level
+}
+MENULEVEL;
+
+typedef struct
+{
+ MENULEVEL MenuLevels[MENULEVELS]; // See above
+ UBYTE FileId; // VarsUi.MenuFiles[VarsUi.MenuFileLevel].FileId
+ UBYTE MenuLevel; // VarsUi.MenuFiles[VarsUi.MenuFileLevel].MenuLevel
+}
+MENUFILE;
+
+typedef struct
+{
+ UBYTE StatusText[STATUSTEXT_SIZE + 1]; // RCX name
+ UBYTE Initialized; // Ui init done
+ UWORD SleepTimer; // Sleep timer
+
+ // Menu system
+ MENUFILE MenuFiles[MENUFILELEVELS]; // Menu file array
+ MENUFILE *pMenuFile; // Actual menu file pointer
+ MENULEVEL *pMenuLevel; // Actual menu item on level, pointer
+ MENUITEM *pMenuItem; // Actual menu item in menu flash file
+ UBYTE MenuFileLevel; // Actual menu file level
+ UBYTE Function; // Running function (0 = none)
+ UBYTE Parameter; // Parameter for running function
+ UBYTE SecondTime; // Second time flag
+ UBYTE EnterOnlyCalls; // Enter button only calls
+ UBYTE ExitOnlyCalls; // Exit button only calls
+ UWORD ButtonTimer; // Button repeat timer
+ UWORD ButtonTime; // Button repeat time
+ UBYTE ButtonOld; // Button old state
+
+ // Update status
+ UWORD UpdateCounter; // Update counter
+ UBYTE Running; // Running pointer
+ UBYTE BatteryToggle; // Battery flash toggle flag
+ UBYTE NewStatusIcons[NO_OF_STATUSICONS]; // New status icons (used to detect changes)
+
+ // Low battery voltage
+ UBYTE *LowBattSavedBitmap; // Low battery overwritten bitmap placeholder
+ UBYTE LowBatt; // Low battery volatge flag
+ UBYTE LowBattHasOccured; // Low battery voltage has occured
+ UBYTE LowBattSavedState; // Low battery current state placeholder
+
+ // General used variables
+ UBYTE *MenuIconTextSave; // Menu icon text save
+
+ UBYTE *pTmp; // General UBYTE pointer
+ ULONG TmpLength; // General filelength (used in filelist)
+ SWORD TmpHandle; // General filehandle (used in filelist)
+
+ SWORD Timer; // General tmp purpose timer
+ SWORD ReadoutTimer; // General read out timer
+ UBYTE Tmp; // General UBYTE
+ UBYTE FileType; // General file type
+ UBYTE State; // General tmp purpose state
+ UBYTE Pointer; // General tmp purpose pointer
+ UBYTE Counter; // General tmp purpose counter
+ UBYTE Cursor; // General cursor
+ UBYTE SelectedSensor; // General used for selected sensor
+ UBYTE SelectedPort; // General used for selected port
+ UBYTE NextState;
+
+ UBYTE SelectedFilename[FILENAME_LENGTH + 1]; // Selected file name
+ UBYTE FilenameBuffer[FILENAME_LENGTH + 1]; // General filename buffer
+ UBYTE SearchFilenameBuffer[FILENAME_LENGTH + 1];// General filename buffer
+ UBYTE DisplayBuffer[DISPLAYLINE_LENGTH + 1]; // General purpose display buffer
+
+ UBYTE PortBitmapLeft[SIZE_OF_PORTBITMAP]; // Port no bitmap for left icon
+ UBYTE PortBitmapCenter[SIZE_OF_PORTBITMAP]; // Port no bitmap for center icon
+ UBYTE PortBitmapRight[SIZE_OF_PORTBITMAP]; // Port no bitmap for right icon
+
+ // Find no of files and find name for file no
+ ULONG FNOFLength; // Length
+ SWORD FNOFHandle; // Handle
+ UBYTE FNOFState; // State
+ UBYTE FNOFSearchBuffer[FILENAME_LENGTH + 1]; // Search buffer
+ UBYTE FNOFNameBuffer[FILENAME_LENGTH + 1]; // File name buffer
+ UBYTE FNOFFileNo; // File no
+
+ // File list
+ UBYTE FileCenter; // File center
+ UBYTE FileLeft; // File left
+ UBYTE FileRight; // File right
+ UBYTE NoOfFiles; // No of files
+
+ // On brick programming menu
+ UBYTE ProgramSteps[ON_BRICK_PROGRAMSTEPS]; // On brick programming steps
+ UBYTE ProgramStepPointer; // On brick programming step pointer
+ UBYTE CursorTmp[SIZE_OF_CURSOR]; // On brick programming cursor
+ UBYTE FileHeader[FILEHEADER_LENGTH]; // File header for programs
+ UBYTE *FeedBackText; // Program end text
+ UWORD OBPTimer; // Graphic update timer
+
+ // BT search menu
+ UBYTE NoOfDevices; // BT search no of devices found
+ UBYTE NoOfNames; // BT search no of names found
+ UBYTE SelectedDevice; // BT selected device
+ UBYTE SelectedSlot; // BT selected slot
+
+ // BT device list menu
+ UBYTE DevicesKnown; // BT device known flag
+ UBYTE Devices; // BT devices
+ UBYTE DeviceLeft; // BT device left
+ UBYTE DeviceCenter; // BT device center
+ UBYTE DeviceRight; // BT device right
+ UBYTE DeviceType; // BT device type
+
+ // BT connect Menu
+ UBYTE Slots; // BT connect no of slots
+ UBYTE SlotLeft; // BT connect
+ UBYTE SlotCenter; // BT connect
+ UBYTE SlotRight; // BT connect
+
+ // Get user string
+ UBYTE GUSTmp; // Seperat tmp for "Get user string"
+ UBYTE GUSState; // Seperat state for "Get user string"
+ UBYTE GUSNoname; // No user entry
+ UBYTE UserString[DISPLAYLINE_LENGTH + 1]; // User string
+ UBYTE DisplayText[DISPLAYLINE_LENGTH + 1]; // Display buffer
+ SBYTE FigurePointer; // Figure cursor
+ UBYTE GUSCursor; // User string cursor
+
+ // Connect request
+ ULONG CRPasskey; // Passkey to fake wrong pin code
+ UBYTE CRState; // Seperate state for "Connect request"
+ UBYTE CRTmp; // Seperate tmp for "Connect request"
+
+ // Run files
+ UBYTE *RunIconSave; // Menu center icon save
+ UWORD RunTimer; // Bitmap change timer
+ UBYTE RunBitmapPointer; // Bitmap pointer
+
+ // Delete files
+ UBYTE SelectedType; // Type of selected files for delete
+
+ // View
+ SLONG ViewSampleValue; // Latch for sensor values
+ UBYTE ViewSampleValid; // Latch for sensor valid
+
+ // NV storage
+ ULONG NVTmpLength; // Non volatile filelength
+ SWORD NVTmpHandle; // Non volatile filehandle
+ UBYTE NVFilename[FILENAME_LENGTH + 1]; // Non volatile file name
+ UBYTE NVData; // Non volatile data
+
+ // Feedback
+ UBYTE *FBText; // Seperate text pointer for feedback
+ UWORD FBTimer; // Seperate timer for feedback
+ UBYTE FBState; // Seperate state for feedback
+ UBYTE FBPointer; // Seperate pointer for feedback
+
+ // BT command
+ UBYTE BTIndex; // List index
+ UBYTE BTTmpIndex; // Tmp list index
+ UBYTE BTCommand; // Last lached BT command
+ UBYTE BTPar1; // Last lached BT command parameter 1
+ UBYTE BTPar2; // Last lached BT command parameter 2
+ UWORD BTResult; // Last lached BT command result
+
+ // Error display
+ UBYTE ErrorTimer; // Error show timer
+ UBYTE ErrorFunction; // Error latched function
+ UBYTE ErrorParameter; // Error latched parameter
+ UBYTE ErrorState; // Error latched state
+ UBYTE ErrorString[DISPLAYLINE_LENGTH + 1]; // Error string
+}VARSUI;
+
+
+void cUiInit(void* pHeader); // Init controller
+void cUiCtrl(void); // Run controller
+void cUiExit(void); // Exit controller
+
+extern const HEADER cUi;
+
+#endif
diff --git a/AT91SAM7S256/Source/c_ui.iom b/AT91SAM7S256/Source/c_ui.iom
new file mode 100644
index 0000000..6159a4f
--- /dev/null
+++ b/AT91SAM7S256/Source/c_ui.iom
@@ -0,0 +1,116 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 28-02-06 14:07 $
+//
+// Filename $Workfile:: c_ui.iom $
+//
+// Version $Revision:: 45 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_ui.iom $
+//
+// Platform C
+//
+
+#ifndef CUI_IOM
+#define CUI_IOM
+
+#define pMapUi ((IOMAPUI*)(pHeaders[ENTRY_UI]->pIOMap))
+
+// Various filenames without extension
+#define UI_NONVOLATILE "NVConfig" // Ui non volatile config filename
+#define UI_PROGRAM_DEFAULT "Untitled" // On brick programming default filename
+#define UI_PROGRAM_TEMP "Program" // On brick programming tmp filename
+#define UI_PROGRAM_READER "RPGReader" // On brick programming script reader filename
+#define UI_STARTUP_SOUND "! Startup" // Sound file activated when the menu system starts up
+#define UI_KEYCLICK_SOUND "! Click" // Sound file activated when key pressed in the menu system
+#define UI_ATTENTION_SOUND "! Attention" // Sound file activated when incomming BT requests attention
+
+// Various text strings
+#define UI_NAME_DEFAULT "NXT" // Default blue tooth name
+#define UI_PINCODE_DEFAULT "1234" // Default blue tooth pin code
+#define UI_PINCODE_NONE_OUT "????" // Fake pin code to deney outgoing request
+#define UI_PINCODE_NONE_IN "????" // Fake pin code to deney incomming request
+
+// Constants related to Flags
+enum
+{
+ UI_UPDATE = 0x01, // W - Make changes take effect
+ UI_DISABLE_LEFT_RIGHT_ENTER = 0x02, // RW - Disable left, right and enter button
+ UI_DISABLE_EXIT = 0x04, // RW - Disable exit button
+ UI_REDRAW_STATUS = 0x08, // W - Redraw entire status line
+ UI_RESET_SLEEP_TIMER = 0x10, // W - Reset sleep timeout timer
+ UI_EXECUTE_LMS_FILE = 0x20, // W - Execute LMS file in "LMSfilename" (Try It)
+ UI_BUSY = 0x40, // R - UI busy running or datalogging (popup disabled)
+ UI_ENABLE_STATUS_UPDATE = 0x80 // W - Enable status line to be updated
+};
+
+// Constants related to State
+enum
+{
+ INIT_DISPLAY, // RW - Init display and load font, menu etc.
+ INIT_LOW_BATTERY, // R - Low battery voltage at power on
+ INIT_INTRO, // R - Display intro
+ INIT_WAIT, // RW - Wait for initialization end
+ INIT_MENU, // RW - Init menu system
+ NEXT_MENU, // RW - Next menu icons ready for drawing
+ DRAW_MENU, // RW - Execute function and draw menu icons
+ TEST_BUTTONS, // RW - Wait for buttons to be pressed
+ LEFT_PRESSED, // RW - Load selected function and next menu id
+ RIGHT_PRESSED, // RW - Load selected function and next menu id
+ ENTER_PRESSED, // RW - Load selected function and next menu id
+ EXIT_PRESSED, // RW - Load selected function and next menu id
+ CONNECT_REQUEST, // RW - Request for connection accept
+ EXECUTE_FILE, // RW - Execute file in "LMSfilename"
+ EXECUTING_FILE, // R - Executing file in "LMSfilename"
+ LOW_BATTERY, // R - Low battery at runtime
+ BT_ERROR // R - BT error
+};
+
+// Constants related to Button
+enum
+{
+ BUTTON_NONE, // R - Button inserted are executed
+ BUTTON_LEFT, // W - Insert left arrow button
+ BUTTON_ENTER, // W - Insert enter button
+ BUTTON_RIGHT, // W - Insert right arrow button
+ BUTTON_EXIT // W - Insert exit button
+};
+
+// Constants related to BlueToothState
+enum
+{
+ BT_STATE_VISIBLE = 0x01, // RW - BT visible
+ BT_STATE_CONNECTED = 0x02, // RW - BT connected to something
+ BT_STATE_OFF = 0x04, // RW - BT power off
+ BT_ERROR_ATTENTION = 0x08, // W - BT error attention
+ BT_CONNECT_REQUEST = 0x40, // RW - BT get connect accept in progress
+ BT_PIN_REQUEST = 0x80 // RW - BT get pin code
+};
+
+typedef struct
+{
+ MENU *pMenu; // W - Pointer to menu file
+ UWORD BatteryVoltage; // R - Battery voltage in millivolts
+ UBYTE LMSfilename[FILENAME_LENGTH + 1]; // W - LMS filename to execute (Try It)
+ UBYTE Flags; // RW - Update command flags (flags enumerated above)
+ UBYTE State; // RW - UI state (states enumerated above)
+ UBYTE Button; // RW - Insert button (buttons enumerated above)
+ UBYTE RunState; // W - VM Run state (0 = stopped, 1 = running)
+ UBYTE BatteryState; // W - Battery state (0..4 capacity)
+ UBYTE BluetoothState; // W - Bluetooth state (0=on, 1=visible, 2=conn, 3=conn.visible, 4=off, 5=dfu)
+ UBYTE UsbState; // W - Usb state (0=disconnected, 1=connected, 2=working)
+ UBYTE SleepTimeout; // RW - Sleep timeout time (min)
+ UBYTE SleepTimer; // RW - Sleep timer (min)
+ UBYTE Rechargeable; // R - Rechargeable battery (0 = no, 1 = yes)
+ UBYTE Volume; // RW - Volume used in UI (0 - 4)
+ UBYTE Error; // W - Error code
+ UBYTE OBPPointer; // W - Actual OBP step (0 - 4)
+ UBYTE ForceOff; // W - Force off (> 0 = off)
+}IOMAPUI;
+
+#endif
diff --git a/AT91SAM7S256/Source/d_bt.c b/AT91SAM7S256/Source/d_bt.c
new file mode 100644
index 0000000..55b81f7
--- /dev/null
+++ b/AT91SAM7S256/Source/d_bt.c
@@ -0,0 +1,453 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:42 $
+//
+// Filename $Workfile:: d_bt.c $
+//
+// Version $Revision:: 21 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_bt.c $
+//
+// Platform C
+//
+
+
+#include "stdconst.h"
+#include "modules.h"
+#include "m_sched.h"
+#include "d_bt.h"
+#include "d_bt.r"
+#include <string.h>
+
+enum
+{
+ BT_FAST_TIMEOUT = 500,
+ BT_CMD_TIMEOUT_2S = 2000,
+ BT_TIMEOUT_30S = 30000
+};
+
+#define SETTimeout(TOut) CmdTOut = 0;\
+ CmdTOutLimit = TOut
+#define RESETTimeout CmdTOut = 0
+
+static UWORD CmdTOut;
+static UWORD CmdTOutLimit;
+
+void dBtInit(void)
+{
+ SETTimeout(0);
+ BTInit;
+ BTInitPIOPins;
+ BTInitADC;
+}
+
+void dBtSetBcResetPinLow(void)
+{
+ BTSetResetLow; /* Set Reset pin to Bluecore chip low */
+}
+
+void dBtSetBcResetPinHigh(void)
+{
+ BTSetResetHigh; /* Set Reset pin to Bluecore chip high */
+}
+
+void dBtStartADConverter(void)
+{
+ BTStartADConverter;
+}
+
+void dBtInitReceive(UBYTE *InputBuffer, UBYTE Mode)
+{
+ BTInitReceiver(InputBuffer, Mode);
+}
+
+void dBtSetArm7CmdSignal(void)
+{
+ BT_SetArm7CmdPin;
+}
+
+void dBtClearArm7CmdSignal(void)
+{
+ BT_ClearArm7CmdPin;
+}
+
+UBYTE dBtGetBc4CmdSignal(void)
+{
+ UWORD ADValue;
+
+ BTReadADCValue(ADValue);
+
+ if (ADValue > 0x200)
+ {
+ ADValue = 1;
+ }
+ else
+ {
+ ADValue = 0;
+ }
+ return(ADValue);
+}
+
+
+UWORD dBtTxEnd(void)
+{
+ UWORD TxEnd;
+
+ REQTxEnd(TxEnd);
+
+ return(TxEnd);
+
+}
+
+UWORD dBtCheckForTxBuf(void)
+{
+ UWORD AvailBytes;
+
+ AVAILOutBuf(AvailBytes);
+
+ return(AvailBytes);
+}
+
+void dBtSendMsg(UBYTE *OutputBuffer, UBYTE BytesToSend, UWORD MsgSize)
+{
+
+ /* Used for sending a complete message that can be placed in the buffer - */
+ /* or to send the first part of a message that cannot be placed in the buffer */
+ /* once (bigger than the buffer) */
+ BTSendMsg(OutputBuffer,BytesToSend, MsgSize);
+}
+
+void dBtSend(UBYTE *OutputBuffer, UBYTE BytesToSend)
+{
+
+ /* Used for continous stream of data to be send */
+ BTSend(OutputBuffer, BytesToSend);
+}
+
+UWORD dBtReceivedData(UWORD *pLength, UWORD *pBytesToGo)
+{
+ UWORD RtnVal;
+
+ RtnVal = TRUE;
+ BTReceivedData(pLength, pBytesToGo);
+ if (*pLength)
+ {
+ SETTimeout(0);
+ }
+ else
+ {
+ if (CmdTOut < CmdTOutLimit)
+ {
+ CmdTOut++;
+ if (CmdTOut >= CmdTOutLimit)
+ {
+ SETTimeout(0);
+ RtnVal = FALSE;
+ }
+ }
+ }
+ return(RtnVal);
+}
+
+void dBtResetTimeOut(void)
+{
+ RESETTimeout;
+}
+
+void dBtClearTimeOut(void)
+{
+ SETTimeout(0);
+}
+
+void dBtSendBtCmd(UBYTE Cmd, UBYTE Param1, UBYTE Param2, UBYTE *pBdAddr, UBYTE *pName, UBYTE *pCod, UBYTE *pPin)
+{
+ UBYTE Tmp;
+ UBYTE SendData;
+ UWORD CheckSumTmp;
+ UBYTE BtOutBuf[128];
+ UBYTE BtOutCnt;
+
+ SendData = 0;
+ BtOutCnt = 0;
+ switch (Cmd)
+ {
+ case MSG_BEGIN_INQUIRY:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_BEGIN_INQUIRY;
+ BtOutBuf[BtOutCnt++] = Param1;
+ BtOutBuf[BtOutCnt++] = 0x00;
+ BtOutBuf[BtOutCnt++] = Param2;
+ BtOutBuf[BtOutCnt++] = 0x00;
+ BtOutBuf[BtOutCnt++] = 0x00;
+ BtOutBuf[BtOutCnt++] = 0x00;
+ BtOutBuf[BtOutCnt++] = 0x00;
+
+ SendData = 1;
+ SETTimeout(BT_TIMEOUT_30S);
+ }
+ break;
+
+ case MSG_CANCEL_INQUIRY:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_CANCEL_INQUIRY;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_CONNECT:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_CONNECT;
+ memcpy(&(BtOutBuf[BtOutCnt]), pBdAddr, SIZE_OF_BDADDR);
+ BtOutCnt += SIZE_OF_BDADDR;
+
+ SendData = 1;
+ SETTimeout(BT_TIMEOUT_30S);
+ }
+ break;
+
+ case MSG_OPEN_PORT:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_OPEN_PORT;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_LOOKUP_NAME:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_LOOKUP_NAME;
+ memcpy(&(BtOutBuf[BtOutCnt]), pBdAddr, SIZE_OF_BDADDR);
+ BtOutCnt += SIZE_OF_BDADDR;
+
+ SendData = 1;
+ SETTimeout(BT_TIMEOUT_30S);
+ }
+ break;
+
+ case MSG_ADD_DEVICE:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_ADD_DEVICE;
+ memcpy(&(BtOutBuf[BtOutCnt]), pBdAddr, SIZE_OF_BDADDR);
+ BtOutCnt += SIZE_OF_BDADDR;
+ memcpy(&(BtOutBuf[BtOutCnt]), pName, SIZE_OF_BT_NAME);
+ BtOutCnt += SIZE_OF_BT_NAME;
+ memcpy(&(BtOutBuf[BtOutCnt]), pCod, SIZE_OF_CLASS_OF_DEVICE);
+ BtOutCnt += SIZE_OF_CLASS_OF_DEVICE;
+
+ SendData = 1;
+ SETTimeout(BT_TIMEOUT_30S);
+ }
+ break;
+
+ case MSG_REMOVE_DEVICE:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_REMOVE_DEVICE;
+ memcpy(&(BtOutBuf[BtOutCnt]), pBdAddr, SIZE_OF_BDADDR);
+ BtOutCnt += SIZE_OF_BDADDR;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_DUMP_LIST:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_DUMP_LIST;
+
+ SendData = 1;
+ SETTimeout(BT_TIMEOUT_30S);
+ }
+ break;
+
+ case MSG_CLOSE_CONNECTION:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_CLOSE_CONNECTION;
+ BtOutBuf[BtOutCnt++] = Param1;
+
+ SendData = 1;
+ SETTimeout(BT_TIMEOUT_30S);
+ }
+ break;
+
+ case MSG_ACCEPT_CONNECTION:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_ACCEPT_CONNECTION;
+ BtOutBuf[BtOutCnt++] = Param1;
+
+ SendData = 1;
+ SETTimeout(BT_TIMEOUT_30S);
+ }
+ break;
+
+ case MSG_PIN_CODE:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_PIN_CODE;
+ memcpy(&(BtOutBuf[BtOutCnt]), pBdAddr, SIZE_OF_BDADDR);
+ BtOutCnt += SIZE_OF_BDADDR;
+ memcpy(&(BtOutBuf[BtOutCnt]), pPin, SIZE_OF_BT_PINCODE);
+ BtOutCnt += SIZE_OF_BT_PINCODE;
+
+ SendData = 1;
+ SETTimeout(BT_TIMEOUT_30S);
+ }
+ break;
+
+ case MSG_OPEN_STREAM:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_OPEN_STREAM;
+ BtOutBuf[BtOutCnt++] = Param1;
+
+ SendData = 1;
+ SETTimeout(BT_TIMEOUT_30S);
+ }
+ break;
+
+ case MSG_START_HEART:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_START_HEART;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_SET_DISCOVERABLE:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_SET_DISCOVERABLE;
+ BtOutBuf[BtOutCnt++] = Param1;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_CLOSE_PORT:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_CLOSE_PORT;
+ BtOutBuf[BtOutCnt++] = 0x03;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_SET_FRIENDLY_NAME:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_SET_FRIENDLY_NAME;
+ memcpy(&(BtOutBuf[BtOutCnt]), pName, SIZE_OF_BT_NAME);
+ BtOutCnt += SIZE_OF_BT_NAME;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_GET_LINK_QUALITY:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_GET_LINK_QUALITY;
+ BtOutBuf[BtOutCnt++] = Param1;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_SET_FACTORY_SETTINGS:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_SET_FACTORY_SETTINGS;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_GET_LOCAL_ADDR:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_GET_LOCAL_ADDR;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_GET_FRIENDLY_NAME:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_GET_FRIENDLY_NAME;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_GET_DISCOVERABLE:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_GET_DISCOVERABLE;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_GET_PORT_OPEN:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_GET_PORT_OPEN;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_GET_VERSION:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_GET_VERSION;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_GET_BRICK_STATUSBYTE:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_GET_BRICK_STATUSBYTE;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+
+ case MSG_SET_BRICK_STATUSBYTE:
+ {
+ BtOutBuf[BtOutCnt++] = MSG_SET_BRICK_STATUSBYTE;
+ BtOutBuf[BtOutCnt++] = Param1;
+ BtOutBuf[BtOutCnt++] = Param2;
+
+ SendData = 1;
+ SETTimeout(BT_FAST_TIMEOUT);
+ }
+ break;
+ }
+
+ if (SendData == 1)
+ {
+ CheckSumTmp = 0;
+ for(Tmp = 0; Tmp < BtOutCnt; Tmp++)
+ {
+ CheckSumTmp += BtOutBuf[Tmp];
+ }
+ CheckSumTmp = (UWORD) (1 + (0xFFFF - CheckSumTmp));
+ BtOutBuf[BtOutCnt++] = (UBYTE)((CheckSumTmp & 0xFF00)>>8);
+ BtOutBuf[BtOutCnt++] = (UBYTE)(CheckSumTmp & 0x00FF);
+ BTSendMsg(BtOutBuf, BtOutCnt, (UWORD)BtOutCnt);
+ }
+}
+
+
+
+void dBtExit(void)
+{
+ BTExit;
+}
diff --git a/AT91SAM7S256/Source/d_bt.h b/AT91SAM7S256/Source/d_bt.h
new file mode 100644
index 0000000..2e41ded
--- /dev/null
+++ b/AT91SAM7S256/Source/d_bt.h
@@ -0,0 +1,39 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:41 $
+//
+// Filename $Workfile:: d_bt.h $
+//
+// Version $Revision:: 16 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_bt.h $
+//
+// Platform C
+//
+
+#ifndef D_BT
+#define D_BT
+
+#define STREAM_MODE 1
+#define CMD_MODE 2
+
+void dBtInit(void);
+void dBtExit(void);
+void dBtStartADConverter(void);
+void dBtSetArm7CmdSignal(void);
+void dBtClearArm7CmdSignal(void);
+void dBtInitReceive(UBYTE *InputBuffer, UBYTE Mode);
+void dBtSetBcResetPinLow(void);
+void dBtSetBcResetPinHigh(void);
+void dBtSendBtCmd(UBYTE Cmd, UBYTE Param1, UBYTE Param2, UBYTE *pBdAddr, UBYTE *pName, UBYTE *pCod, UBYTE *pPin);
+void dBtSendMsg(UBYTE *pData, UBYTE Length, UWORD MsgSize);
+void dBtSend(UBYTE *pData, UBYTE Length);
+void dBtResetTimeOut(void);
+void dBtClearTimeOut(void);
+UBYTE dBtGetBc4CmdSignal(void);
+UWORD dBtTxEnd(void);
+UWORD dBtReceivedData(UWORD *pLength, UWORD *pBytesToGo);
+UWORD dBtCheckForTxBuf(void);
+
+#endif
diff --git a/AT91SAM7S256/Source/d_bt.r b/AT91SAM7S256/Source/d_bt.r
new file mode 100644
index 0000000..f5c6a7d
--- /dev/null
+++ b/AT91SAM7S256/Source/d_bt.r
@@ -0,0 +1,350 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:42 $
+//
+// Filename $Workfile:: d_bt.r $
+//
+// Version $Revision:: 28 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_bt.r $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+#if defined (PROTOTYPE_PCB_3) || (PROTOTYPE_PCB_4)
+
+#define BT_RX_PIN AT91C_PIO_PA21
+#define BT_TX_PIN AT91C_PIO_PA22
+#define BT_SCK_PIN AT91C_PIO_PA23
+#define BT_RTS_PIN AT91C_PIO_PA24
+#define BT_CTS_PIN AT91C_PIO_PA25
+
+#define BT_CS_PIN AT91C_PIO_PA31
+#define BT_RST_PIN AT91C_PIO_PA11
+
+#define BT_ARM7_CMD_PIN AT91C_PIO_PA27
+
+#else
+
+#endif
+
+#define BAUD_RATE 460800L
+
+#define SIZE_OF_INBUF 128
+#define NO_OF_INBUFFERS 2
+#define NO_OF_DMA_OUTBUFFERS 2
+#define SIZE_OF_OUTBUF 256
+
+#define PER_ID7_UART_1 0x80
+#define UART1_INQ 0x80
+#define EXT_LEN_MSG_BIT 0x80
+
+static UBYTE InBuf[NO_OF_INBUFFERS][SIZE_OF_INBUF];
+static ULONG InBufPtrs[NO_OF_INBUFFERS];
+static UBYTE InBufInPtr;
+static UBYTE LengthSize;
+
+static UBYTE OutDma[NO_OF_DMA_OUTBUFFERS][SIZE_OF_OUTBUF];
+static UBYTE DmaBufPtr;
+static UBYTE *pBuffer;
+
+static UBYTE MsgIn;
+static UBYTE InBufOutCnt;
+static UWORD FullRxLength;
+static UWORD RemainingLength;
+
+
+#define ENABLEDebugOutput {\
+ *AT91C_PIOA_PER = 0x20000000; /* Enable PIO on PA029 */\
+ *AT91C_PIOA_OER = 0x20000000; /* PA029 set to Output */\
+ }
+
+#define SETDebugOutputHigh *AT91C_PIOA_SODR = 0x20000000
+
+#define SETDebugOutputLow *AT91C_PIOA_CODR = 0x20000000
+
+#define BTInit {\
+ UBYTE Tmp;\
+ LengthSize = 1;\
+ InBufInPtr = 0;\
+ for(Tmp = 0; Tmp < NO_OF_INBUFFERS; Tmp++)\
+ {\
+ InBufPtrs[Tmp] = (ULONG)&(InBuf[Tmp][0]);\
+ }\
+ *AT91C_PMC_PCER = PER_ID7_UART_1; /* Enable PMC clock for UART 1 */\
+ *AT91C_PIOA_PDR = BT_RX_PIN | BT_TX_PIN | BT_SCK_PIN | BT_RTS_PIN | BT_CTS_PIN; /* Disable Per. A on PA21, PA22, PA23, PA24 & PA25 */\
+ *AT91C_PIOA_ASR = BT_RX_PIN | BT_TX_PIN | BT_SCK_PIN | BT_RTS_PIN | BT_CTS_PIN; /* Enable Per. A on PA21, PA22, PA23, PA24 & PA25 */\
+ *AT91C_US1_CR = AT91C_US_RSTSTA; /* Resets pins on UART1 */\
+ *AT91C_US1_CR = AT91C_US_STTTO; /* Start timeout functionality after 1 byte */\
+ *AT91C_US1_RTOR = 10000; /* Approxitely 20 mS,x times bit time with 115200 bit pr s */\
+ *AT91C_US1_IDR = AT91C_US_TIMEOUT; /* Disable interrupt on timeout */\
+ *AT91C_AIC_IDCR = UART1_INQ; /* Disable UART1 interrupt */\
+ *AT91C_AIC_ICCR = UART1_INQ; /* Clear interrupt register */\
+ *AT91C_US1_MR = AT91C_US_USMODE_HWHSH; /* Set UART with HW handshake */\
+ *AT91C_US1_MR &= ~AT91C_US_SYNC; /* Set UART in asynchronous mode */\
+ *AT91C_US1_MR |= AT91C_US_CLKS_CLOCK; /* Clock setup MCK*/\
+ *AT91C_US1_MR |= AT91C_US_CHRL_8_BITS; /* UART using 8-bit */\
+ *AT91C_US1_MR |= AT91C_US_PAR_NONE; /* UART using none parity bit */\
+ *AT91C_US1_MR |= AT91C_US_NBSTOP_1_BIT; /* UART using 1 stop bit */\
+ *AT91C_US1_MR |= AT91C_US_OVER; /* UART is using 8-bit sampling */\
+ *AT91C_US1_BRGR = ((OSC/8/BAUD_RATE) | (((OSC/8) - ((OSC/8/BAUD_RATE) * BAUD_RATE)) / ((BAUD_RATE + 4)/8)) << 16);\
+ *AT91C_US1_PTCR = (AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS); /* Disable of TX & RX with DMA */\
+ *AT91C_US1_RCR = 0; /* Receive Counter Register */\
+ *AT91C_US1_TCR = 0; /* Transmit Counter Register */\
+ *AT91C_US1_RNPR = 0;\
+ *AT91C_US1_TNPR = 0;\
+ Tmp = *AT91C_US1_RHR;\
+ Tmp = *AT91C_US1_CSR;\
+ *AT91C_US1_RPR = (unsigned int)&(InBuf[InBufInPtr][0]); /* Initialise receiver buffer using DMA */\
+ *AT91C_US1_RCR = SIZE_OF_INBUF;\
+ *AT91C_US1_RNPR = (unsigned int)&(InBuf[(InBufInPtr + 1)%NO_OF_INBUFFERS][0]);\
+ *AT91C_US1_RNCR = SIZE_OF_INBUF;\
+ MsgIn = 0;\
+ InBufOutCnt = 0;\
+ FullRxLength = 0;\
+ RemainingLength = 0;\
+ *AT91C_US1_CR = AT91C_US_RXEN | AT91C_US_TXEN; /* Enable Tx & Rx on UART 1*/\
+ *AT91C_US1_PTCR = (AT91C_PDC_RXTEN | AT91C_PDC_TXTEN); /* Enable of TX & RX with DMA */\
+ }
+
+
+#define BTInitPIOPins {\
+ *AT91C_PIOA_PER = BT_CS_PIN | BT_RST_PIN; /* Enable PIO on PA11 & PA31 */\
+ *AT91C_PIOA_OER = BT_CS_PIN | BT_RST_PIN; /* PA11 & PA31 set to output */\
+ *AT91C_PIOA_SODR = BT_CS_PIN | BT_RST_PIN; /* PA31 & PA11 set output high */\
+ *AT91C_PIOA_PPUDR = BT_ARM7_CMD_PIN; /* Disable PULL-UP resistor on PA27 */\
+ *AT91C_PIOA_PER = BT_ARM7_CMD_PIN; /* Enable PIO on PA27 */\
+ *AT91C_PIOA_CODR = BT_ARM7_CMD_PIN; /* PA27 set output low */\
+ *AT91C_PIOA_OER = BT_ARM7_CMD_PIN; /* PA27 set to output */\
+ }
+
+#define BTInitADC {\
+ *AT91C_ADC_MR = 0; /* Reset register plus setting only software trigger */\
+ *AT91C_ADC_MR |= 0x00003F00; /* ADC-clock set to approximatly 375 kHz */\
+ *AT91C_ADC_MR |= 0x00020000; /* Startup set to approximatly 84uS */\
+ *AT91C_ADC_MR |= 0x09000000; /* Sample & Hold set to approximatly 20uS */\
+ *AT91C_ADC_CHER = AT91C_ADC_CH6 | AT91C_ADC_CH4; /* Enable channel 6 and 4*/\
+ }
+
+#define BTStartADConverter *AT91C_ADC_CR = AT91C_ADC_START; /* Start the ADC converter */\
+
+#define BTReadADCValue(ADValue) ADValue = *AT91C_ADC_CDR6;
+
+#define BTSetResetHigh {\
+ *AT91C_PIOA_SODR = BT_RST_PIN; /* PA11 set output high */\
+ }
+
+#define BTSetResetLow {\
+ *AT91C_PIOA_CODR = BT_RST_PIN; /* PA11 set output low */\
+ }
+
+#define BTInitReceiver(InputBuffer, Mode)\
+ {\
+ pBuffer = InputBuffer;\
+ MsgIn = 0;\
+ FullRxLength = 0;\
+ if (STREAM_MODE == Mode)\
+ {\
+ LengthSize = 2;\
+ }\
+ else\
+ {\
+ LengthSize = 1;\
+ }\
+ }
+
+#define BT_SetArm7CmdPin *AT91C_PIOA_SODR = BT_ARM7_CMD_PIN
+
+#define BT_ClearArm7CmdPin *AT91C_PIOA_CODR = BT_ARM7_CMD_PIN
+
+#define BT_GetBc4CmdPin *AT91C_PIOA_PDSR & BT_BC4_CMD_PIN
+
+#define REQTxEnd(TxEnd) TxEnd = FALSE;\
+ if ((!(*AT91C_US1_TNCR)) && (!(*AT91C_US1_TCR)))\
+ {\
+ TxEnd = TRUE;\
+ }
+
+#define AVAILOutBuf(Avail) if (!(*AT91C_US1_TNCR))\
+ {\
+ Avail = SIZE_OF_OUTBUF;\
+ }\
+ else\
+ {\
+ Avail = 0;\
+ }
+
+
+#define BTSend(OutputBuffer, BytesToSend)\
+ {\
+ UWORD Avail;\
+ AVAILOutBuf(Avail);\
+ if (BytesToSend < (Avail - 1))\
+ {\
+ memcpy(&(OutDma[DmaBufPtr][0]), OutputBuffer, BytesToSend);\
+ *AT91C_US1_TNPR = (unsigned int)&(OutDma[DmaBufPtr][0]);\
+ *AT91C_US1_TNCR = BytesToSend;\
+ DmaBufPtr = (DmaBufPtr + 1) % NO_OF_DMA_OUTBUFFERS;\
+ }\
+ }
+
+
+#define BTSendMsg(OutputBuffer, BytesToSend, MsgSize)\
+ {\
+ UWORD Avail;\
+ AVAILOutBuf(Avail);\
+ if (BytesToSend < (Avail - 1))\
+ {\
+ if (2 == LengthSize)\
+ {\
+ OutDma[DmaBufPtr][0] = (UBYTE)MsgSize;\
+ OutDma[DmaBufPtr][1] = (UBYTE)(MsgSize>>8);\
+ }\
+ else\
+ {\
+ OutDma[DmaBufPtr][0] = (UBYTE)MsgSize;\
+ }\
+ memcpy(&(OutDma[DmaBufPtr][LengthSize]), OutputBuffer, BytesToSend);\
+ *AT91C_US1_TNPR = (unsigned int)&(OutDma[DmaBufPtr][0]);\
+ *AT91C_US1_TNCR = BytesToSend + LengthSize;\
+ DmaBufPtr = (DmaBufPtr + 1) % NO_OF_DMA_OUTBUFFERS;\
+ }\
+ }
+
+
+#define BTReceivedData(pByteCnt, pToGo)\
+ {\
+ UWORD InCnt, Cnt;\
+ *pByteCnt = 0;\
+ *pToGo = 0;\
+ InCnt = (SIZE_OF_INBUF - *AT91C_US1_RCR);\
+ if (*AT91C_US1_RNCR == 0)\
+ {\
+ InCnt = SIZE_OF_INBUF;\
+ }\
+ InCnt -= InBufOutCnt; /* Remove already read bytes */\
+ if (InCnt)\
+ {\
+ if (0 == FullRxLength) /* FullRxLength still to be calculated */\
+ {\
+ while((MsgIn < LengthSize) && (InCnt > 0))\
+ {\
+ pBuffer[MsgIn] = InBuf[InBufInPtr][InBufOutCnt];\
+ MsgIn++;\
+ InBufOutCnt++;\
+ InCnt--;\
+ }\
+ if (LengthSize == MsgIn)\
+ {\
+ if (2 == LengthSize)\
+ {\
+ FullRxLength = pBuffer[1];\
+ FullRxLength <<= 8;\
+ FullRxLength |= pBuffer[0];\
+ /* Remove Length when in strean mode */\
+ MsgIn = 0;\
+ }\
+ else\
+ {\
+ FullRxLength = pBuffer[0];\
+ }\
+ RemainingLength = FullRxLength;\
+ }\
+ else\
+ {\
+ /* Length still not received */\
+ FullRxLength = 0;\
+ }\
+ }\
+ if (FullRxLength)\
+ {\
+ /* Incomming msg in progress */\
+ /* room for bytes? */\
+ if (InCnt >= RemainingLength)\
+ {\
+ /* Remaining msg bytes are in the buffer */\
+ /* Can remaining byte be stored in buffer? */\
+ if ((MsgIn + RemainingLength) <= SIZE_OF_INBUF)\
+ {\
+ /* All bytes can be stored */\
+ for (Cnt = 0; Cnt < RemainingLength; Cnt++)\
+ {\
+ pBuffer[MsgIn] = InBuf[InBufInPtr][InBufOutCnt];\
+ MsgIn++;\
+ InBufOutCnt++;\
+ }\
+ *pByteCnt = MsgIn;\
+ *pToGo = 0;\
+ FullRxLength = 0;\
+ RemainingLength = 0;\
+ MsgIn = 0;\
+ }\
+ else\
+ {\
+ for (Cnt = 0; MsgIn < SIZE_OF_INBUF; Cnt++)\
+ {\
+ pBuffer[MsgIn] = InBuf[InBufInPtr][InBufOutCnt];\
+ MsgIn++;\
+ InBufOutCnt++;\
+ }\
+ *pByteCnt = SIZE_OF_INBUF;\
+ RemainingLength -= Cnt;\
+ *pToGo = RemainingLength;\
+ MsgIn = 0;\
+ }\
+ }\
+ else\
+ {\
+ if ((InCnt + MsgIn) < SIZE_OF_INBUF)\
+ {\
+ /* Received bytes do not fill up the buffer */\
+ for (Cnt = 0; Cnt < InCnt; Cnt++)\
+ {\
+ pBuffer[MsgIn] = InBuf[InBufInPtr][InBufOutCnt];\
+ MsgIn++;\
+ InBufOutCnt++;\
+ }\
+ RemainingLength -= InCnt;\
+ }\
+ else\
+ {\
+ /* Received bytes fill up the buffer */\
+ for (Cnt = 0; MsgIn < SIZE_OF_INBUF; Cnt++)\
+ {\
+ pBuffer[MsgIn] = InBuf[InBufInPtr][InBufOutCnt];\
+ MsgIn++;\
+ InBufOutCnt++;\
+ }\
+ *pByteCnt = SIZE_OF_INBUF;\
+ RemainingLength -= Cnt; /* Only substract no removed */\
+ *pToGo = RemainingLength;\
+ MsgIn = 0;\
+ }\
+ }\
+ }\
+ }\
+ if ((*AT91C_US1_RNCR == 0) && (SIZE_OF_INBUF == InBufOutCnt))\
+ {\
+ InBufOutCnt = 0;\
+ *AT91C_US1_RNPR = (unsigned int)InBufPtrs[InBufInPtr];\
+ *AT91C_US1_RNCR = SIZE_OF_INBUF;\
+ InBufInPtr = (InBufInPtr + 1) % NO_OF_INBUFFERS;\
+ }\
+ }
+
+#define BTExit {\
+ *AT91C_PMC_PCDR = PER_ID7_UART_1; /* Disable PMC clock for UART 1*/\
+ *AT91C_US1_IDR = AT91C_US_TIMEOUT; /* Disable interrupt on timeout */\
+ *AT91C_AIC_IDCR = UART1_INQ; /* Disable PIO interrupt */\
+ *AT91C_AIC_ICCR = UART1_INQ; /* Clear interrupt register */\
+ }
+
+
+#endif
+
+#ifdef PCWIN
+
+#endif
diff --git a/AT91SAM7S256/Source/d_button.c b/AT91SAM7S256/Source/d_button.c
new file mode 100644
index 0000000..a74c166
--- /dev/null
+++ b/AT91SAM7S256/Source/d_button.c
@@ -0,0 +1,36 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:58 $
+//
+// Filename $Workfile:: d_button.c $
+//
+// Version $Revision:: 4 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_button.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "m_sched.h"
+#include "d_button.h"
+#include "d_button.r"
+
+static UBYTE TimeTick;
+
+void dButtonInit(UBYTE Prescaler)
+{
+ TimeTick = Prescaler;
+ BUTTONInit;
+}
+
+void dButtonRead(UBYTE *pButton)
+{
+ BUTTONRead(pButton);
+}
+
+void dButtonExit(void)
+{
+ BUTTONExit;
+}
diff --git a/AT91SAM7S256/Source/d_button.h b/AT91SAM7S256/Source/d_button.h
new file mode 100644
index 0000000..2826c3f
--- /dev/null
+++ b/AT91SAM7S256/Source/d_button.h
@@ -0,0 +1,24 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:58 $
+//
+// Filename $Workfile:: d_button.h $
+//
+// Version $Revision:: 4 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_button.h $
+//
+// Platform C
+//
+
+#ifndef D_BUTTON
+#define D_BUTTON
+
+void dButtonInit(UBYTE Prescaler);
+void dButtonExit(void);
+
+void dButtonRead(UBYTE *pButton);
+
+
+#endif
diff --git a/AT91SAM7S256/Source/d_button.r b/AT91SAM7S256/Source/d_button.r
new file mode 100644
index 0000000..3e5e359
--- /dev/null
+++ b/AT91SAM7S256/Source/d_button.r
@@ -0,0 +1,189 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:58 $
+//
+// Filename $Workfile:: d_button.r $
+//
+// Version $Revision:: 14 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_button.r $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+static UBYTE PrellCnt[NOS_OF_AVR_BTNS];
+static UWORD OldVal;
+static UBYTE OldState;
+static UBYTE RisingTime;
+
+#define PRELL_TIME (60/TimeTick)
+#define RISING_THRESHOLD (10/TimeTick)
+
+#define BUTTONInit {\
+ UBYTE Tmp;\
+ for (Tmp = 0; Tmp < NOS_OF_AVR_BTNS; Tmp++)\
+ {\
+ PrellCnt[Tmp] = 0;\
+ }\
+ IoFromAvr.Buttons = 0;\
+ OldVal = 0;\
+ OldState = 0;\
+ RisingTime = 0;\
+ }
+
+#if defined (PROTOTYPE_PCB_3) || (PROTOTYPE_PCB_4)
+
+/* Buttons read here are free of prell or jitter */
+/* And because it's an AD value returned from the AVR */
+/* then a peak detector is needed */
+#define BUTTONRead(pB) {\
+ UBYTE Tmp, BtnPtr;\
+ UWORD TmpBtn;\
+ *pB = OldState;\
+ BtnPtr = 0x01;\
+ if (OldVal < IoFromAvr.Buttons)\
+ {\
+ OldVal = IoFromAvr.Buttons;\
+ RisingTime = 0;\
+ }\
+ else\
+ {\
+ if (OldVal > (IoFromAvr.Buttons + 20))\
+ {\
+ OldVal = IoFromAvr.Buttons;\
+ RisingTime = 0;\
+ }\
+ else\
+ {\
+ if (RisingTime > RISING_THRESHOLD)\
+ {\
+ TmpBtn = IoFromAvr.Buttons;\
+ if (0x40 > TmpBtn)\
+ {\
+ TmpBtn = 0x00;\
+ }\
+ else if (0x100 > TmpBtn)\
+ {\
+ TmpBtn = 0x04;\
+ }\
+ else if (0x1FF > TmpBtn)\
+ {\
+ TmpBtn = 0x02;\
+ }\
+ else if (0x5FF > TmpBtn)\
+ {\
+ TmpBtn = 0x01;\
+ }\
+ else\
+ {\
+ TmpBtn = 0x08;\
+ }\
+ for (Tmp = 0; Tmp < NOS_OF_AVR_BTNS; Tmp++)\
+ {\
+ if ((TmpBtn) & BtnPtr)\
+ {\
+ *pB |= BtnPtr;\
+ PrellCnt[Tmp] = PRELL_TIME;\
+ }\
+ else\
+ {\
+ /* btn not pressed */\
+ if (0 != PrellCnt[Tmp])\
+ {\
+ PrellCnt[Tmp]--;\
+ }\
+ else\
+ {\
+ *pB &= ~BtnPtr;\
+ }\
+ }\
+ BtnPtr <<= 1;\
+ }\
+ OldState = *pB;\
+ }\
+ else\
+ {\
+ RisingTime++;\
+ }\
+ }\
+ }\
+ }
+
+#else
+
+// Buttons read here are free of prell or jitter
+#define BUTTONRead(pB) {\
+ UBYTE Tmp, BtnPtr;\
+ UWORD TmpBtn;\
+ *pB = OldState;\
+ BtnPtr = 0x01;\
+ if ((OldVal) < IoFromAvr.Buttons)\
+ {\
+ OldVal = IoFromAvr.Buttons;\
+ }\
+ else\
+ {\
+ if ((OldVal) > IoFromAvr.Buttons)\
+ {\
+ OldVal = IoFromAvr.Buttons;\
+ }\
+ else\
+ {\
+ TmpBtn = IoFromAvr.Buttons;\
+ if (100 > TmpBtn)\
+ {\
+ TmpBtn = 0x00;\
+ }\
+ else if (170 > TmpBtn)\
+ {\
+ TmpBtn = 0x01;\
+ }\
+ else if (255 > TmpBtn)\
+ {\
+ TmpBtn = 0x02;\
+ }\
+ else if (1000 > TmpBtn)\
+ {\
+ TmpBtn = 0x04;\
+ }\
+ else if (1024 > TmpBtn)\
+ {\
+ TmpBtn = 0x08;\
+ }\
+ for (Tmp = 0; Tmp < NOS_OF_AVR_BTNS; Tmp++)\
+ {\
+ if ((TmpBtn) & BtnPtr)\
+ {\
+ *pB |= BtnPtr;\
+ PrellCnt[Tmp] = PRELL_TIME;\
+ }\
+ else\
+ {\
+ /* btn not pressed */\
+ if (0 != PrellCnt[Tmp])\
+ {\
+ PrellCnt[Tmp]--;\
+ }\
+ else\
+ {\
+ *pB &= ~BtnPtr;\
+ }\
+ }\
+ BtnPtr <<= 1;\
+ }\
+ OldState = *pB;\
+ }\
+ }\
+ }
+#endif
+
+#define BUTTONExit
+
+#endif
+
+#ifdef PCWIN
+
+#endif
diff --git a/AT91SAM7S256/Source/d_display.c b/AT91SAM7S256/Source/d_display.c
new file mode 100644
index 0000000..7181913
--- /dev/null
+++ b/AT91SAM7S256/Source/d_display.c
@@ -0,0 +1,53 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 29-08-05 11:26 $
+//
+// Filename $Workfile:: d_display.c $
+//
+// Version $Revision:: 4 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_display. $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "m_sched.h"
+#include "d_display.h"
+#include "d_display.r"
+
+
+void dDisplayInit(void)
+{
+ DISPLAYInit;
+}
+
+
+void dDisplayOn(UBYTE On)
+{
+ if (On)
+ {
+ DISPLAYOn;
+ }
+ else
+ {
+ DISPLAYOff;
+ }
+}
+
+
+UBYTE dDisplayUpdate(UWORD Height,UWORD Width,UBYTE *pImage)
+{
+ return (DISPLAYUpdate(Height,Width,pImage));
+}
+
+
+void dDisplayExit(void)
+{
+ DISPLAYExit;
+}
diff --git a/AT91SAM7S256/Source/d_display.h b/AT91SAM7S256/Source/d_display.h
new file mode 100644
index 0000000..c205619
--- /dev/null
+++ b/AT91SAM7S256/Source/d_display.h
@@ -0,0 +1,39 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 29-08-05 11:26 $
+//
+// Filename $Workfile:: d_display.h $
+//
+// Version $Revision:: 5 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_display. $
+//
+// Platform C
+//
+
+#ifndef D_DISPLAY
+#define D_DISPLAY
+
+void dDisplayInit(void);
+void dDisplayOn(UBYTE On);
+UBYTE dDisplayUpdate(UWORD Height,UWORD Width,UBYTE *pImage);
+void dDisplayExit(void);
+
+
+
+typedef struct
+{
+ UBYTE StartX;
+ UBYTE StartY;
+ UBYTE PixelsX;
+ UBYTE PixelsY;
+}
+SCREEN_CORDINATE;
+
+
+#endif
diff --git a/AT91SAM7S256/Source/d_display.r b/AT91SAM7S256/Source/d_display.r
new file mode 100644
index 0000000..d4328b7
--- /dev/null
+++ b/AT91SAM7S256/Source/d_display.r
@@ -0,0 +1,374 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dktochpe $
+//
+// Revision date $Date:: 20-12-05 12:28 $
+//
+// Filename $Workfile:: d_display.r $
+//
+// Version $Revision:: 18 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_display. $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+// Display 128 x 64
+// 1/65 duty, 1/9 bias
+// VLCD 12.0V
+
+// SPI interface
+//
+// PCB LCD ARM PIO
+// ------ ----- ---- -----
+// CS_DIS -CS1 PA10 NPCS2 (PB)
+// DIS_A0 A0 PA12 PA12
+// DIS_SCL SCL PA14 SPCK (PA)
+// DIS_SDA SI PA13 MOSI (PA)
+
+
+// CPOL = 0, NCPHA=0,
+
+#define BT_RESET_OUT AT91C_PIO_PA11
+#define BT_RESET_IN AT91C_PIO_PA29
+#define BT_MOSI_OUT AT91C_PIO_PA13
+#define BT_MOSI_IN AT91C_PIO_PA20
+#define BT_CLK_OUT AT91C_PIO_PA14
+#define BT_CLK_IN AT91C_PIO_PA28
+#define BT_CE_OUT AT91C_PIO_PA31
+#define BT_CE_IN AT91C_PIO_PA19
+#define BT_REA_OUT AT91C_PIO_PA7
+#define BT_MISO_OUT AT91C_PIO_PA6
+#define BT_MISO_IN AT91C_PIO_PA12
+
+#pragma optimize=s 9
+
+__ramfunc void SpiBtIo(void)
+{
+ register ULONG Port;
+
+ *AT91C_AIC_IDCR = 0xFFFFFFFF; /* Disable all interrupts */
+
+ *AT91C_PIOA_PER = BT_RESET_OUT; /* Enable pin RESET out */
+ *AT91C_PIOA_OER = BT_RESET_OUT; /* Set output */
+ *AT91C_PIOA_SODR = BT_RESET_OUT; /* Set high */
+
+ *AT91C_PIOA_PER = BT_MOSI_OUT; /* Enable pin MOSI out */
+ *AT91C_PIOA_OER = BT_MOSI_OUT; /* Set output */
+
+ *AT91C_PIOA_PER = BT_CLK_OUT; /* Enable pin CLK out */
+ *AT91C_PIOA_OER = BT_CLK_OUT; /* Set output */
+
+ *AT91C_PIOA_PER = BT_CE_OUT; /* Enable pin CE out */
+ *AT91C_PIOA_OER = BT_CE_OUT; /* Set output */
+
+ *AT91C_PIOA_PER = BT_REA_OUT; /* Enable pin REA out */
+ *AT91C_PIOA_OER = BT_REA_OUT; /* Set output */
+ *AT91C_PIOA_SODR = BT_REA_OUT; /* Set high */
+
+ *AT91C_PIOA_PER = BT_MISO_OUT; /* Enable pin MISO out */
+ *AT91C_PIOA_OER = BT_MISO_OUT; /* Set output */
+
+ *AT91C_PIOA_PER = BT_RESET_IN; /* Enable pin RESET in */
+ *AT91C_PIOA_ODR = BT_RESET_IN; /* Set input */
+ *AT91C_PIOA_IFDR = BT_RESET_IN; /* Disable filter */
+ *AT91C_PIOA_IDR = BT_RESET_IN; /* Disable interrupt */
+ *AT91C_PIOA_MDDR = BT_RESET_IN; /* Disable multidriver */
+ *AT91C_PIOA_PPUDR = BT_RESET_IN; /* Disable pullup */
+
+ *AT91C_PIOA_PER = BT_MOSI_IN; /* Enable pin MOSI in */
+ *AT91C_PIOA_ODR = BT_MOSI_IN; /* Set input */
+ *AT91C_PIOA_IFDR = BT_MOSI_IN; /* Disable filter */
+ *AT91C_PIOA_IDR = BT_MOSI_IN; /* Disable interrupt */
+ *AT91C_PIOA_MDDR = BT_MOSI_IN; /* Disable multidriver */
+ *AT91C_PIOA_PPUDR = BT_MOSI_IN; /* Disable pullup */
+
+ *AT91C_PIOA_PER = BT_CLK_IN; /* Enable pin CLK in */
+ *AT91C_PIOA_ODR = BT_CLK_IN; /* Set input */
+ *AT91C_PIOA_IFDR = BT_CLK_IN; /* Disable filter */
+ *AT91C_PIOA_IDR = BT_CLK_IN; /* Disable interrupt */
+ *AT91C_PIOA_MDDR = BT_CLK_IN; /* Disable multidriver */
+ *AT91C_PIOA_PPUDR = BT_CLK_IN; /* Disable pullup */
+
+ *AT91C_PIOA_PER = BT_CE_IN; /* Enable pin CE in */
+ *AT91C_PIOA_ODR = BT_CE_IN; /* Set input */
+ *AT91C_PIOA_IFDR = BT_CE_IN; /* Disable filter */
+ *AT91C_PIOA_IDR = BT_CE_IN; /* Disable interrupt */
+ *AT91C_PIOA_MDDR = BT_CE_IN; /* Disable multidriver */
+ *AT91C_PIOA_PPUDR = BT_CE_IN; /* Disable pullup */
+
+ *AT91C_PIOA_PER = BT_MISO_IN; /* Enable pin MISO in */
+ *AT91C_PIOA_ODR = BT_MISO_IN; /* Set input */
+ *AT91C_PIOA_IFDR = BT_MISO_IN; /* Disable filter */
+ *AT91C_PIOA_IDR = BT_MISO_IN; /* Disable interrupt */
+ *AT91C_PIOA_MDDR = BT_MISO_IN; /* Disable multidriver */
+ *AT91C_PIOA_PPUDR = BT_MISO_IN; /* Disable pullup */
+
+ while (1)
+ {
+ Port = *AT91C_PIOA_PDSR;
+ if ((Port & BT_MISO_IN))
+ {
+ *AT91C_PIOA_SODR = BT_MISO_OUT;
+ }
+ else
+ {
+ *AT91C_PIOA_CODR = BT_MISO_OUT;
+ }
+ if ((Port & BT_MOSI_IN))
+ {
+ *AT91C_PIOA_SODR = BT_MOSI_OUT;
+ }
+ else
+ {
+ *AT91C_PIOA_CODR = BT_MOSI_OUT;
+ }
+ if ((Port & BT_CLK_IN))
+ {
+ *AT91C_PIOA_SODR = BT_CLK_OUT;
+ }
+ else
+ {
+ *AT91C_PIOA_CODR = BT_CLK_OUT;
+ }
+ if ((Port & BT_CE_IN))
+ {
+ *AT91C_PIOA_SODR = BT_CE_OUT;
+ }
+ else
+ {
+ *AT91C_PIOA_CODR = BT_CE_OUT;
+ }
+ }
+
+}
+
+
+void BtIo(void)
+{
+ SpiBtIo();
+}
+
+
+
+#define SPI_BITRATE 2000000
+
+#define SPIA0High {\
+ *AT91C_PIOA_SODR = AT91C_PIO_PA12;\
+ }
+
+
+#define SPIA0Low {\
+ *AT91C_PIOA_CODR = AT91C_PIO_PA12;\
+ }
+
+
+#define SPIInit {\
+ *AT91C_PMC_PCER = (1L << AT91C_ID_SPI); /* Enable MCK clock */\
+ *AT91C_PIOA_PER = AT91C_PIO_PA12; /* Enable A0 on PA12 */\
+ *AT91C_PIOA_OER = AT91C_PIO_PA12;\
+ *AT91C_PIOA_CODR = AT91C_PIO_PA12;\
+ *AT91C_PIOA_PDR = AT91C_PA14_SPCK; /* Enable SPCK on PA14 */\
+ *AT91C_PIOA_ASR = AT91C_PA14_SPCK;\
+ *AT91C_PIOA_ODR = AT91C_PA14_SPCK;\
+ *AT91C_PIOA_OWER = AT91C_PA14_SPCK;\
+ *AT91C_PIOA_MDDR = AT91C_PA14_SPCK;\
+ *AT91C_PIOA_PPUDR = AT91C_PA14_SPCK;\
+ *AT91C_PIOA_IFDR = AT91C_PA14_SPCK;\
+ *AT91C_PIOA_CODR = AT91C_PA14_SPCK;\
+ *AT91C_PIOA_IDR = AT91C_PA14_SPCK;\
+ *AT91C_PIOA_PDR = AT91C_PA13_MOSI; /* Enable mosi on PA13 */\
+ *AT91C_PIOA_ASR = AT91C_PA13_MOSI;\
+ *AT91C_PIOA_ODR = AT91C_PA13_MOSI;\
+ *AT91C_PIOA_OWER = AT91C_PA13_MOSI;\
+ *AT91C_PIOA_MDDR = AT91C_PA13_MOSI;\
+ *AT91C_PIOA_PPUDR = AT91C_PA13_MOSI;\
+ *AT91C_PIOA_IFDR = AT91C_PA13_MOSI;\
+ *AT91C_PIOA_CODR = AT91C_PA13_MOSI;\
+ *AT91C_PIOA_IDR = AT91C_PA13_MOSI;\
+ *AT91C_PIOA_PDR = AT91C_PA10_NPCS2; /* Enable npcs0 on PA11 */\
+ *AT91C_PIOA_BSR = AT91C_PA10_NPCS2;\
+ *AT91C_PIOA_ODR = AT91C_PA10_NPCS2;\
+ *AT91C_PIOA_OWER = AT91C_PA10_NPCS2;\
+ *AT91C_PIOA_MDDR = AT91C_PA10_NPCS2;\
+ *AT91C_PIOA_PPUDR = AT91C_PA10_NPCS2;\
+ *AT91C_PIOA_IFDR = AT91C_PA10_NPCS2;\
+ *AT91C_PIOA_CODR = AT91C_PA10_NPCS2;\
+ *AT91C_PIOA_IDR = AT91C_PA10_NPCS2;\
+ *AT91C_SPI_CR = AT91C_SPI_SWRST; /* Soft reset */\
+ *AT91C_SPI_CR = AT91C_SPI_SPIEN; /* Enable spi */\
+ *AT91C_SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | (0xB << 16);\
+ AT91C_SPI_CSR[2] = ((OSC / SPI_BITRATE) << 8) | AT91C_SPI_CPOL;\
+ }
+
+
+#define SPIWrite(pString,Length) {\
+ *AT91C_SPI_TPR = (unsigned int)pString;\
+ *AT91C_SPI_TCR = (unsigned int)Length;\
+ *AT91C_SPI_PTCR = AT91C_PDC_TXTEN;\
+ }
+
+
+
+#define CMD 0
+#define DAT 1
+#define DISP_LINES 8
+
+#if defined (PROTOTYPE_PCB_3) || (PROTOTYPE_PCB_4)
+
+#define ACTUAL_WIDTH 100
+
+UBYTE DisplayInitString[] =
+{
+ 0xEB, // LCD bias setting = 1/9 0xEB
+ 0x2F, // Power control = internal 0x2F
+ 0xA4, // All points not on 0xA4
+ 0xA6, // Not inverse 0xA6
+ 0x40, // Start line = 0 0x40
+ 0x81, // Electronic volume 0x81
+ 0x5A, // -"- 0x5F
+ 0xC4, // LCD mapping 0xC4
+ 0x27, // Set temp comp. 0x27-
+ 0x29, // Panel loading 0x28 0-1
+ 0xA0, // Framerate 0xA0-
+ 0x88, // CA++ 0x88-
+ 0x23, // Multiplex 1:65 0x23
+ 0xAF // Display on 0xAF
+};
+
+#else
+
+#define ACTUAL_WIDTH 128
+
+UBYTE DisplayInitString[] =
+{
+ 0xA2, // LCD bias setting = 1/9
+ 0x2F, // Power control = internal
+ 0xA4, // All points not on
+ 0xA6, // Not inverse
+ 0x40, // Start line = 0
+ 0x81, // Electronic volume
+ 0x3F, // -"-
+ 0xA0, // LCD mapping
+ 0x27, // Resistor ratio
+ 0xC8, // Common output state selection
+ 0xF8, // Booster ratio
+ 0x00, // -"-
+ 0xE3, // nop
+ 0xAF // Display on
+};
+
+#endif
+
+UBYTE DisplayLineString[DISP_LINES][3] =
+{
+ { 0xB0,0x10,0x00 },
+ { 0xB1,0x10,0x00 },
+ { 0xB2,0x10,0x00 },
+ { 0xB3,0x10,0x00 },
+ { 0xB4,0x10,0x00 },
+ { 0xB5,0x10,0x00 },
+ { 0xB6,0x10,0x00 },
+ { 0xB7,0x10,0x00 }
+};
+
+UBYTE DisplayWrite(UBYTE Type,UBYTE *pData,UWORD Length)
+{
+ UBYTE Result = FALSE;
+
+ if ((*AT91C_SPI_SR & AT91C_SPI_TXEMPTY))
+ {
+ if (Type)
+ {
+ SPIA0High;
+ }
+ else
+ {
+ SPIA0Low;
+ }
+ SPIWrite(pData,Length);
+ Result = TRUE;
+ }
+
+ return (Result);
+}
+
+UBYTE DisplayUpdate(UWORD Height,UWORD Width,UBYTE *pImage)
+{
+ static UWORD State = 0;
+ static UWORD Line;
+
+ if (State == 0)
+ {
+ if (DisplayWrite(CMD,(UBYTE*)DisplayInitString,sizeof(DisplayInitString)) == TRUE)
+ {
+ Line = 0;
+ State++;
+ }
+ }
+ else
+ {
+ if ((State & 1))
+ {
+ if (DisplayWrite(CMD,(UBYTE*)DisplayLineString[Line],3) == TRUE)
+ {
+ State++;
+ }
+ }
+ else
+ {
+ if (DisplayWrite(DAT,(UBYTE*)&pImage[Line * Width],ACTUAL_WIDTH) == TRUE)
+ {
+ State++;
+ if (++Line >= (Height / 8))
+ {
+ State = 0;
+ }
+ }
+ }
+ }
+
+ return (State);
+}
+
+
+#if defined (PROTOTYPE_PCB_3)
+
+#define DISPLAYInit {\
+ TSTInit;\
+ TSTOn;\
+ SPIInit;\
+ }
+
+#else
+
+#define DISPLAYInit {\
+ SPIInit;\
+ }
+
+#endif
+
+#define DISPLAYOn {\
+ DisplayInitString[6] = 0x5A;\
+ DisplayInitString[13] = 0xAF;\
+ }
+
+#define DISPLAYOff {\
+ DisplayInitString[6] = 0x00;\
+ DisplayInitString[13] = 0xAE;\
+ }
+
+#define DISPLAYUpdate(H,W,I) DisplayUpdate(H,W,I)
+
+#define DISPLAYExit
+
+#endif
+
+#ifdef PCWIN
+
+#endif
diff --git a/AT91SAM7S256/Source/d_hispeed.c b/AT91SAM7S256/Source/d_hispeed.c
new file mode 100644
index 0000000..cdb79b7
--- /dev/null
+++ b/AT91SAM7S256/Source/d_hispeed.c
@@ -0,0 +1,48 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: d_hispeed.c $
+//
+// Version $Revision:: 8 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_hispeed. $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "m_sched.h"
+#include "d_hispeed.h"
+#include "d_hispeed.r"
+
+void dHiSpeedInit(void)
+{
+ HIGHSPEEDInit;
+}
+
+void dHiSpeedSendData(UBYTE *OutputBuffer, UBYTE BytesToSend)
+{
+ HIGHSPEEDSendDmaData(OutputBuffer,BytesToSend);
+}
+
+void dHiSpeedSetupUart(void)
+{
+ HIGHSPEEDSetupUart;
+}
+
+void dHiSpeedInitReceive(UBYTE *InputBuffer)
+{
+ HIGHSPEEDInitReceiver(InputBuffer);
+}
+
+void dHiSpeedReceivedData(UWORD *ByteCnt)
+{
+ HIGHSPEEDReceivedData(ByteCnt);
+}
+
+void dHiSpeedExit(void)
+{
+ HIGHSPEEDExit;
+}
diff --git a/AT91SAM7S256/Source/d_hispeed.h b/AT91SAM7S256/Source/d_hispeed.h
new file mode 100644
index 0000000..2ebda66
--- /dev/null
+++ b/AT91SAM7S256/Source/d_hispeed.h
@@ -0,0 +1,25 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: d_hispeed.h $
+//
+// Version $Revision:: 5 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_hispeed. $
+//
+// Platform C
+//
+
+#ifndef D_HISPEED
+#define D_HISPEED
+
+void dHiSpeedInit(void);
+void dHiSpeedSendData(UBYTE *OutputBuffer, UBYTE BytesToSend);
+void dHiSpeedSetupUart(void);
+void dHiSpeedInitReceive(UBYTE *InputBuffer);
+void dHiSpeedReceivedData(UWORD *ByteCnt);
+void dHiSpeedExit(void);
+
+#endif
diff --git a/AT91SAM7S256/Source/d_hispeed.r b/AT91SAM7S256/Source/d_hispeed.r
new file mode 100644
index 0000000..0f4a455
--- /dev/null
+++ b/AT91SAM7S256/Source/d_hispeed.r
@@ -0,0 +1,190 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: d_hispeed.r $
+//
+// Version $Revision:: 11 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_hispeed. $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+#if defined (PROTOTYPE_PCB_3) || (PROTOTYPE_PCB_4)
+
+#define HIGHSPEED_RX_PIN AT91C_PIO_PA5
+#define HIGHSPEED_TX_PIN AT91C_PIO_PA6
+#define HIGHSPEED_RTS_PIN AT91C_PIO_PA7
+
+#else
+
+
+#endif
+
+#define PER_ID6_UART_0 0x40
+#define UART0_INQ 0x40
+#define BAUD_RATE 921600L
+
+#define SIZE_OF_INBUF 128
+#define NO_OF_INBUFFERS 2
+#define SIZE_OF_OUTBUF 128
+#define NO_OF_DMA_OUTBUFFERS 1
+
+static UBYTE InBuf[NO_OF_INBUFFERS][SIZE_OF_INBUF];
+static ULONG InBufPtrs[NO_OF_INBUFFERS];
+static UBYTE InBufInPtr;
+
+static UBYTE OutDma[NO_OF_DMA_OUTBUFFERS][SIZE_OF_OUTBUF];
+static UBYTE DmaBufPtr;
+static UBYTE *pBuffer;
+
+static UBYTE MsgIn;
+static UBYTE InBufOutCnt;
+
+#define HIGHSPEEDInit {\
+ *AT91C_PIOA_PER = HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN | HIGHSPEED_RX_PIN; /* Enable PIO on PA07, PA06 & PA05 */\
+ *AT91C_PIOA_PPUDR = HIGHSPEED_RX_PIN | HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN; /* Disable Pull-up resistor */\
+ *AT91C_PIOA_OER = HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN | HIGHSPEED_RX_PIN; /* PA07 & PA06 set to Output */\
+ *AT91C_PIOA_CODR = HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN | HIGHSPEED_RX_PIN; /* Set output low */\
+ }
+
+
+#define HIGHSPEEDSetupUart {\
+ UBYTE Tmp;\
+ InBufInPtr = 0;\
+ for(Tmp = 0; Tmp < NO_OF_INBUFFERS; Tmp++)\
+ {\
+ InBufPtrs[Tmp] = (ULONG)&(InBuf[Tmp][0]);\
+ }\
+ *AT91C_PMC_PCER = PER_ID6_UART_0; /* Enable PMC clock for UART 0 */\
+ *AT91C_PIOA_PPUDR = HIGHSPEED_RX_PIN | HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN; /* Disable Pull-up resistor */\
+ *AT91C_PIOA_PDR = HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN | HIGHSPEED_RX_PIN; /* Disable Per. A on PA5, PA6 & PA7 */\
+ *AT91C_PIOA_ASR = HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN | HIGHSPEED_RX_PIN;; /* Enable Per. A on PA5, PA6 & PA7 */\
+ *AT91C_US0_CR = AT91C_US_RSTSTA; /* Resets pins on UART0 */\
+ *AT91C_US0_CR = AT91C_US_STTTO; /* Start timeout functionality after 1 byte */\
+ *AT91C_US0_RTOR = 2400; /* Approxitely 20 mS,x times bit time with 115200 bit pr s */\
+ *AT91C_US0_IDR = AT91C_US_TIMEOUT; /* Disable interrupt on timeout */\
+ *AT91C_AIC_IDCR = UART0_INQ; /* Disable UART0 interrupt */\
+ *AT91C_AIC_ICCR = UART0_INQ; /* Clear interrupt register */\
+ *AT91C_US0_MR = AT91C_US_USMODE_RS485; /* Set UART to RUN RS485 Mode*/\
+ *AT91C_US0_MR &= ~AT91C_US_SYNC; /* Set UART in asynchronous mode */\
+ *AT91C_US0_MR |= AT91C_US_CLKS_CLOCK; /* Clock setup MCK*/\
+ *AT91C_US0_MR |= AT91C_US_CHRL_8_BITS; /* UART using 8-bit */\
+ *AT91C_US0_MR |= AT91C_US_PAR_NONE; /* UART using none parity bit */\
+ *AT91C_US0_MR |= AT91C_US_NBSTOP_1_BIT; /* UART using 1 stop bit */\
+ *AT91C_US0_MR |= AT91C_US_OVER; /* UART is using 8-bit sampling */\
+ *AT91C_US0_BRGR = ((OSC/8/BAUD_RATE) | (((OSC/8) - ((OSC/8/BAUD_RATE) * BAUD_RATE)) / ((BAUD_RATE + 4)/8)) << 16);\
+ *AT91C_US0_PTCR = (AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS); /* Disable of TX & RX with DMA */\
+ *AT91C_US0_RCR = 0; /* Receive Counter Register */\
+ *AT91C_US0_TCR = 0; /* Transmit Counter Register */\
+ *AT91C_US0_RNPR = 0;\
+ *AT91C_US0_TNPR = 0;\
+ Tmp = *AT91C_US0_RHR;\
+ Tmp = *AT91C_US0_CSR;\
+ *AT91C_US0_RPR = (unsigned int)&(InBuf[InBufInPtr][0]); /* Initialise receiver buffer using DMA */\
+ *AT91C_US0_RCR = SIZE_OF_INBUF;\
+ *AT91C_US0_RNPR = (unsigned int)&(InBuf[(InBufInPtr + 1)%NO_OF_INBUFFERS][0]);\
+ *AT91C_US0_RNCR = SIZE_OF_INBUF;\
+ MsgIn = 0;\
+ InBufOutCnt = 0;\
+ *AT91C_US0_CR = AT91C_US_RXEN | AT91C_US_TXEN; /* Enable Tx & Rx on UART 0*/\
+ *AT91C_US0_PTCR = (AT91C_PDC_RXTEN | AT91C_PDC_TXTEN); /* Enable of TX & RX with DMA */\
+ }
+
+#define HIGHSPEEDInitReceiver(InputBuffer)\
+ {\
+ UBYTE Tmp;\
+ pBuffer = InputBuffer;\
+ *AT91C_US0_PTCR = (AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS); /* Disable of TX & RX with DMA */\
+ *AT91C_US0_RCR = 0; /* Receive Counter Register */\
+ *AT91C_US0_TCR = 0; /* Transmit Counter Register */\
+ *AT91C_US0_RNPR = 0;\
+ *AT91C_US0_TNPR = 0;\
+ Tmp = *AT91C_US0_RHR;\
+ Tmp = *AT91C_US0_CSR;\
+ Tmp = Tmp;\
+ *AT91C_US0_RPR = (unsigned int)&(InBuf[InBufInPtr][0]); /* Initialise receiver buffer using DMA */\
+ *AT91C_US0_RCR = SIZE_OF_INBUF;\
+ *AT91C_US0_RNPR = (unsigned int)&(InBuf[(InBufInPtr + 1)%NO_OF_INBUFFERS][0]);\
+ *AT91C_US0_RNCR = SIZE_OF_INBUF;\
+ MsgIn = 0;\
+ InBufOutCnt = 0;\
+ *AT91C_US0_CR = AT91C_US_RXEN | AT91C_US_TXEN; /* Enable Tx & Rx on UART 0*/\
+ *AT91C_US0_PTCR = (AT91C_PDC_RXTEN | AT91C_PDC_TXTEN); /* Enable of TX & RX with DMA */\
+ }
+
+
+#define HIGHSPEEDReceivedData(pByteCnt)\
+ {\
+ UWORD InCnt;\
+ *pByteCnt = 0;\
+ InCnt = (SIZE_OF_INBUF - *AT91C_US0_RCR);\
+ if (*AT91C_US0_RNCR == 0)\
+ {\
+ InCnt = SIZE_OF_INBUF;\
+ }\
+ InCnt -= InBufOutCnt; /* Remove already read bytes */\
+ if(InCnt)\
+ {\
+ while(InCnt > 0)\
+ {\
+ pBuffer[MsgIn] = InBuf[InBufInPtr][InBufOutCnt];\
+ MsgIn++;\
+ InBufOutCnt++;\
+ InCnt--;\
+ }\
+ *pByteCnt = MsgIn;\
+ MsgIn = 0;\
+ }\
+ if ((*AT91C_US0_RNCR == 0) && (SIZE_OF_INBUF == InBufOutCnt))\
+ {\
+ InBufOutCnt = 0;\
+ *AT91C_US0_RNPR = (unsigned int)InBufPtrs[InBufInPtr];\
+ *AT91C_US0_RNCR = SIZE_OF_INBUF;\
+ InBufInPtr = (InBufInPtr + 1) % NO_OF_INBUFFERS;\
+ }\
+ }
+
+#define AVAILOutBuf(Avail) if (!(*AT91C_US0_TNCR))\
+ {\
+ Avail = SIZE_OF_OUTBUF;\
+ }\
+ else\
+ {\
+ Avail = 0;\
+ }
+
+#define HIGHSPEEDSendDmaData(OutputBuffer, BytesToSend)\
+ {\
+ UWORD Avail, Cnt;\
+ AVAILOutBuf(Avail);\
+ if (BytesToSend < (Avail - 1))\
+ {\
+ for (Cnt = 0; Cnt < BytesToSend; Cnt++)\
+ {\
+ OutDma[DmaBufPtr][Cnt] = OutputBuffer[Cnt];\
+ }\
+ *AT91C_US0_TNPR = (unsigned int)&(OutDma[DmaBufPtr][0]);\
+ *AT91C_US0_TNCR = BytesToSend;\
+ DmaBufPtr = (DmaBufPtr + 1) % NO_OF_DMA_OUTBUFFERS;\
+ }\
+ }
+
+#define HIGHSPEEDExit {\
+ *AT91C_PMC_PCDR = PER_ID6_UART_0; /* Disable PMC clock for UART 0*/\
+ *AT91C_PIOA_PER = HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN | HIGHSPEED_RX_PIN; /* Enable PIO on PA07, PA06 & PA05 */\
+ *AT91C_PIOA_PPUDR = HIGHSPEED_RX_PIN | HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN; /* Disable Pull-up resistor */\
+ *AT91C_PIOA_OER = HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN | HIGHSPEED_RX_PIN; /* PA07 & PA06 set to Output */\
+ *AT91C_PIOA_CODR = HIGHSPEED_TX_PIN | HIGHSPEED_RTS_PIN | HIGHSPEED_RX_PIN; /* Set output low */\
+ }
+
+
+#endif
+
+#ifdef PCWIN
+
+#endif
diff --git a/AT91SAM7S256/Source/d_input.c b/AT91SAM7S256/Source/d_input.c
new file mode 100644
index 0000000..272f35e
--- /dev/null
+++ b/AT91SAM7S256/Source/d_input.c
@@ -0,0 +1,104 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:06 $
+//
+// Filename $Workfile:: d_input.c $
+//
+// Version $Revision:: 14 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_input.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "m_sched.h"
+#include "c_input.h"
+#include "d_input.h"
+#include "d_input.r"
+
+
+void dInputInit(void)
+{
+ INPUTInit;
+}
+
+
+void dInputGetRawAd(UWORD *pValues, UBYTE No)
+{
+ INPUTGetVal(pValues, No);
+}
+
+
+void dInputSetDirOutDigi0(UBYTE Port)
+{
+ INPUTSetOutDigi0(Port);
+}
+
+void dInputSetDirOutDigi1(UBYTE Port)
+{
+ INPUTSetOutDigi1(Port);
+}
+
+void dInputSetDirInDigi0(UBYTE Port)
+{
+ INPUTSetInDigi0(Port);
+}
+
+void dInputSetDirInDigi1(UBYTE Port)
+{
+ INPUTSetInDigi1(Port);
+}
+
+void dInputClearDigi0(UBYTE Port)
+{
+ INPUTClearDigi0(Port);
+}
+
+void dInputClearDigi1(UBYTE Port)
+{
+ INPUTClearDigi1(Port);
+}
+
+void dInputSetDigi0(UBYTE Port)
+{
+ INPUTSetDigi0(Port);
+}
+
+void dInputSetDigi1(UBYTE Port)
+{
+ INPUTSetDigi1(Port);
+}
+
+void dInputRead0(UBYTE Port, UBYTE *pData)
+{
+ INPUTReadDigi0(Port, pData);
+}
+
+void dInputRead1(UBYTE Port, UBYTE * pData)
+{
+ INPUTReadDigi1(Port, pData);
+}
+
+void dInputSetActive(UBYTE Port)
+{
+ INPUTSetActive(Port);
+}
+
+void dInputSet9v(UBYTE Port)
+{
+ INPUTSet9v(Port);
+}
+
+void dInputSetInactive(UBYTE Port)
+{
+ INPUTSetInactive(Port);
+}
+
+
+void dInputExit(void)
+{
+ INPUTExit;
+}
+
diff --git a/AT91SAM7S256/Source/d_input.h b/AT91SAM7S256/Source/d_input.h
new file mode 100644
index 0000000..8a7d4ef
--- /dev/null
+++ b/AT91SAM7S256/Source/d_input.h
@@ -0,0 +1,37 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:06 $
+//
+// Filename $Workfile:: d_input.h $
+//
+// Version $Revision:: 6 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_input.h $
+//
+// Platform C
+//
+
+#ifndef D_INPUT
+#define D_INPUT
+
+void dInputInit(void);
+void dInputExit(void);
+
+void dInputGetRawAd(UWORD *pValues, UBYTE No);
+void dInputSetActive(UBYTE Port);
+void dInputSet9v(UBYTE Port);
+void dInputSetInactive(UBYTE Port);
+
+void dInputSetDirOutDigi0(UBYTE Port);
+void dInputSetDirOutDigi1(UBYTE Port);
+void dInputSetDirInDigi0(UBYTE Port);
+void dInputSetDirInDigi1(UBYTE Port);
+void dInputClearDigi0(UBYTE Port);
+void dInputClearDigi1(UBYTE Port);
+void dInputSetDigi0(UBYTE Port);
+void dInputSetDigi1(UBYTE Port);
+void dInputRead0(UBYTE Port, UBYTE *pData);
+void dInputRead1(UBYTE Port, UBYTE *pData);
+
+#endif
diff --git a/AT91SAM7S256/Source/d_input.r b/AT91SAM7S256/Source/d_input.r
new file mode 100644
index 0000000..6e3d989
--- /dev/null
+++ b/AT91SAM7S256/Source/d_input.r
@@ -0,0 +1,99 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:06 $
+//
+// Filename $Workfile:: d_input.r $
+//
+// Version $Revision:: 10 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_input.r $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+#define MAX_AD_VALUE 0x3FF
+
+#define INPUTInit {\
+ UBYTE Tmp;\
+ for (Tmp = 0; Tmp < NOS_OF_AVR_INPUTS; Tmp++)\
+ {\
+ IoFromAvr.AdValue[Tmp] = MAX_AD_VALUE;\
+ }\
+ IoToAvr.InputPower = 0;\
+ for (Tmp = 0; Tmp < NO_OF_INPUTS; Tmp++)\
+ {\
+ *AT91C_PIOA_PPUDR = Digi0Alloc[Tmp];\
+ *AT91C_PIOA_PPUDR = Digi1Alloc[Tmp];\
+ INPUTSetInDigi0(Tmp);\
+ INPUTSetInDigi1(Tmp);\
+ }\
+ }
+
+#define INPUTGetVal(pValues, No) *pValues = (UWORD)IoFromAvr.AdValue[No];\
+ *pValues &= 0x03FF
+
+#define INPUTSetActive(Input) IoToAvr.InputPower |= (0x01 << Input);\
+ IoToAvr.InputPower &= ~(0x10 << Input)
+#define INPUTSet9v(Input) IoToAvr.InputPower |= (0x10 << Input);\
+ IoToAvr.InputPower &= ~(0x01 << Input)
+#define INPUTSetInactive(Input) IoToAvr.InputPower &= ~(0x11 << Input)
+
+const ULONG Digi0Alloc[] = {AT91C_PIO_PA23, AT91C_PIO_PA28, AT91C_PIO_PA29, AT91C_PIO_PA30};
+const ULONG Digi1Alloc[] = {AT91C_PIO_PA18, AT91C_PIO_PA19, AT91C_PIO_PA20, AT91C_PIO_PA2};
+
+#define INPUTSetOutDigi0(Input) *AT91C_PIOA_PER = Digi0Alloc[Input];\
+ *AT91C_PIOA_OER = Digi0Alloc[Input]
+
+#define INPUTSetOutDigi1(Input) *AT91C_PIOA_PER = Digi1Alloc[Input];\
+ *AT91C_PIOA_OER = Digi1Alloc[Input]
+
+
+#define INPUTSetInDigi0(Input) *AT91C_PIOA_PER = Digi0Alloc[Input];\
+ *AT91C_PIOA_ODR = Digi0Alloc[Input]
+
+#define INPUTSetInDigi1(Input) *AT91C_PIOA_PER = Digi1Alloc[Input];\
+ *AT91C_PIOA_ODR = Digi1Alloc[Input]
+
+#define INPUTSetDigi0(Input) *AT91C_PIOA_SODR = Digi0Alloc[Input]
+
+#define INPUTSetDigi1(Input) *AT91C_PIOA_SODR = Digi1Alloc[Input]
+
+#define INPUTClearDigi0(Input) *AT91C_PIOA_CODR = Digi0Alloc[Input]
+
+#define INPUTClearDigi1(Input) *AT91C_PIOA_CODR = Digi1Alloc[Input]
+
+#define INPUTReadDigi0(Input, Data) if ((*AT91C_PIOA_PDSR) & Digi0Alloc[Input])\
+ {\
+ *Data |= 0x00000001;\
+ }\
+ else\
+ {\
+ *Data &= ~0x00000001;\
+ }
+#define INPUTReadDigi1(Input, Data) if ((*AT91C_PIOA_PDSR) & Digi1Alloc[Input])\
+ {\
+ *Data |= 0x00000002;\
+ }\
+ else\
+ {\
+ *Data &= ~0x00000002;\
+ }
+
+#define INPUTExit {\
+ UBYTE Tmp;\
+ for (Tmp = 0; Tmp < NO_OF_INPUTS; Tmp++)\
+ {\
+ INPUTSetInDigi0(Tmp);\
+ INPUTSetInDigi1(Tmp);\
+ }\
+ }
+
+
+#endif
+
+#ifdef PCWIN
+
+#endif
diff --git a/AT91SAM7S256/Source/d_ioctrl.c b/AT91SAM7S256/Source/d_ioctrl.c
new file mode 100644
index 0000000..7c414f6
--- /dev/null
+++ b/AT91SAM7S256/Source/d_ioctrl.c
@@ -0,0 +1,102 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:50 $
+//
+// Filename $Workfile:: d_ioctrl.c $
+//
+// Version $Revision:: 11 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_ioctrl.c $
+//
+// Platform C
+//
+
+
+#include <string.h>
+#include "stdconst.h"
+#include "m_sched.h"
+#include "d_ioctrl.h"
+#include "d_ioctrl.r"
+
+/* Enum related to State */
+enum
+{
+ RX_I2C = 1,
+ TX_I2C = 2,
+ UNLOCK_I2C = 3,
+ WAIT_I2C = 4
+};
+
+
+static UBYTE volatile State;
+
+void dIOCtrlInit(void)
+{
+ IOCTRLInit;
+ State = UNLOCK_I2C;
+}
+
+void dIOCtrlSetPower(UBYTE Power)
+{
+ INSERTPower(Power);
+}
+
+void dIOCtrlSetPwm(UBYTE Pwm)
+{
+ INSERTPwm(Pwm);
+}
+
+void dIOCtrlTransfer(void)
+{
+ UBYTE B;
+
+ CHECKTime(B);
+ if (B)
+ {
+ switch(State)
+ {
+ case TX_I2C:
+ {
+ FULLDataTx;
+ State = RX_I2C;
+ }
+ break;
+ case RX_I2C:
+ {
+ FULLDataRx;
+ State = TX_I2C;
+ }
+ break;
+ case UNLOCK_I2C:
+ {
+ UNLOCKTx;
+ State = WAIT_I2C;
+ }
+ break;
+ case WAIT_I2C:
+ {
+
+ /* Intermediate state as unlock string is 47 */
+ /* characters which is a little more than 1mS */
+ State = TX_I2C;
+ }
+ break;
+ default:
+ {
+ UNLOCKTx;
+ State = WAIT_I2C;
+ }
+ break;
+ }
+ SETTime;
+ }
+}
+
+
+
+void dIOCtrlExit(void)
+{
+ IOCTRLExit;
+}
+
diff --git a/AT91SAM7S256/Source/d_ioctrl.h b/AT91SAM7S256/Source/d_ioctrl.h
new file mode 100644
index 0000000..4ebedd3
--- /dev/null
+++ b/AT91SAM7S256/Source/d_ioctrl.h
@@ -0,0 +1,25 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:50 $
+//
+// Filename $Workfile:: d_ioctrl.h $
+//
+// Version $Revision:: 7 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_ioctrl.h $
+//
+// Platform C
+//
+
+#ifndef D_AVRCOMM
+#define D_AVRCOMM
+
+void dIOCtrlInit(void);
+void dIOCtrlExit(void);
+
+void dIOCtrlSetPower(UBYTE Power);
+void dIOCtrlSetPwm(UBYTE Pwm);
+void dIOCtrlTransfer(void);
+
+#endif
diff --git a/AT91SAM7S256/Source/d_ioctrl.r b/AT91SAM7S256/Source/d_ioctrl.r
new file mode 100644
index 0000000..71bf0f4
--- /dev/null
+++ b/AT91SAM7S256/Source/d_ioctrl.r
@@ -0,0 +1,310 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 9:50 $
+//
+// Filename $Workfile:: d_ioctrl.r $
+//
+// Version $Revision:: 21 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_ioctrl.r $
+//
+// Platform C
+//
+
+
+#ifdef SAM7S256
+
+#define NO_TO_TX BYTES_TO_TX + 1
+#define NO_TO_RX BYTES_TO_RX + 1
+#define TIMEOUT 2100
+
+
+
+extern void I2cHandler(void);
+
+static UBYTE *pIrq;
+static UBYTE Cnt;
+static UBYTE NoToTx;
+static UBYTE I2cStatus;
+static UBYTE I2cInBuffer[NO_TO_RX];
+static UBYTE I2cOutBuffer[NO_TO_TX];
+static UBYTE RxSum;
+
+#define I2C_IDLE 1
+#define I2C_ERROR 2
+#define I2C_TX 3
+#define I2C_RX 4
+
+#define I2CClk 400000L
+#define TIME400KHz (((OSC/16L)/(I2CClk * 2)) + 1)
+#define CLDIV (((OSC/I2CClk)/2)-3)
+
+#define DEVICE_ADR 0x01
+#define DISABLEI2cIrqs *AT91C_TWI_IDR = 0x000001C7
+#define ISSUEStopCond *AT91C_TWI_CR = AT91C_TWI_STOP
+
+
+#define WAITClk {\
+ ULONG PitTmr;\
+ PitTmr = (*AT91C_PITC_PIIR & AT91C_PITC_CPIV) + TIME400KHz;\
+ if (PitTmr >= (*AT91C_PITC_PIMR & AT91C_PITC_CPIV))\
+ {\
+ PitTmr -= (*AT91C_PITC_PIMR & AT91C_PITC_CPIV);\
+ }\
+ while ((*AT91C_PITC_PIIR & AT91C_PITC_CPIV) < PitTmr);\
+ }
+
+
+
+#define RESETI2c {\
+ UBYTE Tmp;\
+ *AT91C_PMC_PCER = (1L<<AT91C_ID_TWI);/* Enable TWI Clock */\
+ *AT91C_PIOA_MDER = AT91C_PA4_TWCK; /* enable open drain on SCL*/\
+ *AT91C_PIOA_SODR = AT91C_PA4_TWCK; /* SCL is high */\
+ *AT91C_PIOA_OER = AT91C_PA4_TWCK; /* SCL is output */\
+ *AT91C_PIOA_ODR = AT91C_PA3_TWD; /* SDA is input */\
+ *AT91C_PIOA_PER = (AT91C_PA4_TWCK | AT91C_PA3_TWD); /* Disable peripheal */\
+ Tmp = 0;\
+ /* Clock minimum 9 times and both SCK and SDA should be high */\
+ while(((!(*AT91C_PIOA_PDSR & AT91C_PA3_TWD)) || (!(*AT91C_PIOA_PDSR & AT91C_PA4_TWCK))) || (Tmp <= 9))\
+ {\
+ *AT91C_PIOA_CODR = AT91C_PA4_TWCK; /* SCL is low */\
+ WAITClk;\
+ *AT91C_PIOA_SODR = AT91C_PA4_TWCK; /* SCL is high */\
+ WAITClk;\
+ Tmp++;\
+ }\
+ *AT91C_TWI_CR = AT91C_TWI_SWRST;\
+ I2cStatus = I2C_IDLE;\
+ }
+
+#define IOCTRLInit {\
+ memset(I2cInBuffer, 0x00, sizeof(I2cInBuffer));\
+ *AT91C_AIC_IDCR = (1L<<AT91C_ID_TWI); /* Disable AIC irq */\
+ DISABLEI2cIrqs; /* Disable TWI irq */\
+ RESETI2c;\
+ IoToAvr.Power = 0;\
+ *AT91C_AIC_ICCR = (1L<<AT91C_ID_TWI); /* Clear AIC irq */\
+ AT91C_AIC_SVR[AT91C_ID_TWI] = (unsigned int)I2cHandler;\
+ AT91C_AIC_SMR[AT91C_ID_TWI] = ((AT91C_AIC_PRIOR_HIGHEST) | (AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED));\
+ *AT91C_AIC_IECR = (1L<<AT91C_ID_TWI); /* Enables AIC irq */\
+ *AT91C_PIOA_ASR = (AT91C_PA4_TWCK | AT91C_PA3_TWD); /* Sel. per. A */\
+ *AT91C_PIOA_PDR = (AT91C_PA4_TWCK | AT91C_PA3_TWD); /* Sel. per on pins*/\
+ *AT91C_PIOA_MDER = (AT91C_PA4_TWCK | AT91C_PA3_TWD); /* Open drain */\
+ *AT91C_PIOA_PPUDR = (AT91C_PA4_TWCK | AT91C_PA3_TWD); /* no pull up */\
+ *AT91C_TWI_CWGR = (CLDIV | (CLDIV << 8)); /* 400KHz clock */\
+ NoToTx = 0;\
+ }
+
+
+#define IOCTRLExit DISABLEI2cIrqs;\
+ *AT91C_AIC_IDCR = (1L<<AT91C_ID_TWI); /* Disable AIC irq */\
+ *AT91C_AIC_ICCR = (1L<<AT91C_ID_TWI); /* Clear AIC irq */\
+ *AT91C_PMC_PCDR = (1L<<AT91C_ID_TWI); /* Disable clock */\
+ *AT91C_PIOA_MDER = (AT91C_PA4_TWCK | AT91C_PA3_TWD); /* Open drain */\
+ *AT91C_PIOA_PPUDR = (AT91C_PA4_TWCK | AT91C_PA3_TWD); /* no pull up */\
+ *AT91C_PIOA_PER = (AT91C_PA4_TWCK | AT91C_PA3_TWD); /* Disable peripheal*/
+
+#define INSERTPower(Power) IoToAvr.Power = Power
+#define INSERTPwm(Pwm) IoToAvr.PwmFreq = Pwm
+
+const UBYTE CopyrightStr[] = {"\xCC"COPYRIGHTSTRING};
+
+
+
+#define UNLOCKTx if (I2cStatus == I2C_IDLE)\
+ {\
+ I2cStatus = I2C_TX;\
+ DISABLEI2cIrqs;\
+ pIrq = (UBYTE*)CopyrightStr;\
+ Cnt = 0;\
+ NoToTx = COPYRIGHTSTRINGLENGTH + 1; /* +1 is the 0xCC command */\
+ *AT91C_AIC_ICCR = (1L<<AT91C_ID_TWI);\
+ *AT91C_TWI_MMR = (AT91C_TWI_IADRSZ_NO | (DEVICE_ADR << 16)); /* no internal adr, write dir */\
+ *AT91C_TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_START;\
+ *AT91C_TWI_IER = 0x000001C4; /* Enable TX related irq */\
+ }\
+ else\
+ {\
+ if ((I2cStatus == I2C_ERROR) || ((I2cStatus == I2C_TX)))\
+ {\
+ IOCTRLInit;\
+ }\
+ }
+
+
+#define FULLDataTx if (I2cStatus == I2C_IDLE)\
+ {\
+ UBYTE I2cTmp, Sum;\
+ pIrq = (UBYTE*)&IoToAvr;\
+ for(I2cTmp = 0, Sum = 0; I2cTmp < BYTES_TO_TX; I2cTmp++, pIrq++)\
+ {\
+ I2cOutBuffer[I2cTmp] = *pIrq;\
+ Sum += *pIrq;\
+ }\
+ I2cOutBuffer[I2cTmp] = ~Sum;\
+ I2cStatus = I2C_TX;\
+ DISABLEI2cIrqs;\
+ pIrq = I2cOutBuffer;\
+ Cnt = 0;\
+ NoToTx = NO_TO_TX;\
+ *AT91C_AIC_ICCR = (1L<<AT91C_ID_TWI);\
+ *AT91C_TWI_MMR = (AT91C_TWI_IADRSZ_NO | (DEVICE_ADR << 16)); /* no internal adr, write dir */\
+ *AT91C_TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_START;\
+ *AT91C_TWI_IER = 0x000001C4; /* Enable TX related irq */\
+ }\
+ else\
+ {\
+ if ((I2cStatus == I2C_ERROR) || ((I2cStatus == I2C_TX)))\
+ {\
+ IOCTRLInit;\
+ }\
+ }
+
+
+#define FULLDataRx {\
+ if (I2cStatus == I2C_IDLE)\
+ {\
+ ULONG Tmp;\
+ RxSum = 0;\
+ I2cStatus = I2C_RX;\
+ DISABLEI2cIrqs;\
+ pIrq = I2cInBuffer;\
+ Cnt = 0;\
+ /* Reset error flags */\
+ Tmp = *AT91C_TWI_SR;\
+ Tmp = *AT91C_TWI_RHR;\
+ Tmp = Tmp; /* Suppress warning */\
+ *AT91C_TWI_MMR = (AT91C_TWI_MREAD | AT91C_TWI_IADRSZ_NO | (DEVICE_ADR << 16));\
+ *AT91C_TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN;\
+ Tmp = *AT91C_TWI_SR;\
+ *AT91C_TWI_IER = 0x000001C2;\
+ }\
+ else\
+ {\
+ if ((I2cStatus == I2C_ERROR) || (I2cStatus == I2C_RX))\
+ {\
+ IOCTRLInit;\
+ }\
+ }\
+ }
+
+static ULONG I2CTimerValue;
+#define CHECKTime(B) if (TIMEOUT < ((((*AT91C_PITC_PIIR) & AT91C_PITC_CPIV) - I2CTimerValue) & AT91C_PITC_CPIV))\
+ {\
+ B = TRUE;\
+ }\
+ else\
+ {\
+ B = FALSE;\
+ }
+
+
+#define SETTime I2CTimerValue = ((*AT91C_PITC_PIIR) & AT91C_PITC_CPIV)
+
+
+__ramfunc void I2cHandler(void)
+{
+
+ ULONG Tmp;
+ Tmp = *AT91C_TWI_SR;
+
+ if (Tmp & AT91C_TWI_RXRDY)
+ {
+ Cnt++;
+ if (Cnt < (NO_TO_RX - 1))
+ {
+ *pIrq = *AT91C_TWI_RHR;
+ RxSum += *pIrq;
+ }
+ else
+ {
+ if (Cnt == (NO_TO_RX - 1))
+ {
+
+ /* Issue stop cond. (NACK) to indicate read last byte */
+ ISSUEStopCond;
+ *pIrq = *AT91C_TWI_RHR;
+ RxSum += *pIrq;
+ }
+ else
+ {
+ if (Cnt == NO_TO_RX)
+ {
+
+ /* Now read last byte */
+ *pIrq = *AT91C_TWI_RHR;
+ I2cStatus = I2C_IDLE;
+ RxSum = ~RxSum;
+ if (RxSum == *pIrq)
+ {
+ UBYTE I2cIrqTmp;
+ for (I2cIrqTmp = 0, pIrq = (UBYTE*)&IoFromAvr; I2cIrqTmp < BYTES_TO_RX; I2cIrqTmp++, pIrq++)
+ {
+ *pIrq = I2cInBuffer[I2cIrqTmp];
+ }
+ }
+ }
+ }
+ }
+ pIrq++;
+ }
+
+ else
+ {
+ if (Tmp & AT91C_TWI_TXRDY)
+ {
+ if (Cnt < NoToTx)
+ {
+
+ /* When both shift and THR reg is empty - stop is sent automatically */
+ *AT91C_TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_START;
+ if (Cnt == (NoToTx - 1))
+ {
+ *AT91C_TWI_CR = AT91C_TWI_STOP;
+ }
+ *AT91C_TWI_THR = *pIrq;
+ Cnt++;
+ pIrq++;
+ }
+ else
+ {
+ I2cStatus = I2C_IDLE;
+ DISABLEI2cIrqs;
+ }
+ }
+ }
+
+ /* Overrun error - byte received while rx buffer is full */
+ if (Tmp & AT91C_TWI_OVRE)
+ {
+ I2cStatus = I2C_ERROR;
+ ISSUEStopCond;
+ DISABLEI2cIrqs;
+ }
+
+ /* Underrun error - trying to load invalid data to the shift register */
+ if (Tmp & AT91C_TWI_UNRE)
+ {
+ I2cStatus = I2C_ERROR;
+ DISABLEI2cIrqs;
+ }
+
+ /* NACK - Data byte has not been accepted by the reciever */
+ if (Tmp & AT91C_TWI_NACK)
+ {
+ I2cStatus = I2C_ERROR;
+ DISABLEI2cIrqs;
+ IOCTRLInit;
+ }
+}
+
+
+#endif
+
+
+#ifdef PCWIN
+
+
+#endif
diff --git a/AT91SAM7S256/Source/d_loader.c b/AT91SAM7S256/Source/d_loader.c
new file mode 100644
index 0000000..30f6376
--- /dev/null
+++ b/AT91SAM7S256/Source/d_loader.c
@@ -0,0 +1,1437 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 17-05-06 8:36 $
+//
+// Filename $Workfile:: d_loader.c $
+//
+// Version $Revision:: 75 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_loader.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "modules.h"
+#include "m_sched.h"
+#include "d_loader.h"
+#include "d_loader.r"
+#include <string.h>
+#include <ctype.h>
+
+#define FILEVERSION (0x00000106L)
+
+#define MAX_FILES ((SECTORSIZE/4) - 1) /* Last file entry is used for file version*/
+#define MAX_WRITE_BUFFERS 4
+#define FLASHOFFSET (0x100000L)
+
+#define IS_LOADER_ERR(LStatus) (((LStatus) & 0xFF00) != SUCCESS)
+#define SECTORINDEXUSERFLASH ((STARTOFUSERFLASH & ~FLASHOFFSET)/256/32)
+#define SECTORPOINTERUSERFLASH (((STARTOFUSERFLASH & ~FLASHOFFSET) - ((SECTORINDEXUSERFLASH * 32) * 256))/256)
+
+typedef struct
+{
+ const UBYTE *pFlash;
+ const UWORD *pSectorNo;
+ ULONG ReadLength;
+ ULONG DataLength;
+ ULONG FileDlPtr;
+ UBYTE SearchStr[FILENAME_SIZE];
+ UWORD FileIndex;
+ UWORD CheckSum;
+ UBYTE SearchType;
+ UBYTE Status;
+ UBYTE FileType;
+ UBYTE WriteBufNo;
+}HANDLE;
+
+typedef struct
+{
+ ULONG Buf[SECTORSIZE/4];
+ UBYTE BufIndex;
+ UBYTE Status;
+}WRITEBUF;
+
+static HANDLE HandleTable[MAX_HANDLES];
+static WRITEBUF WriteBuffer[MAX_WRITE_BUFFERS];
+static ULONG SectorTable[NOOFSECTORS>>5];
+static const ULONG *Files;
+static FILEHEADER Header;
+static ULONG FreeUserFlash;
+static UWORD FreeSectors;
+
+void dLoaderUpdateSectorTable(void);
+UWORD dLoaderGetFreeHandle(void);
+const UBYTE * dLoaderGetNextSectorPtr(UBYTE Handle);
+ULONG dLoaderReturnFreeFlash(void);
+UWORD dLoaderAllocateHeader(UWORD Handle, ULONG *FileStartAdr, FILEHEADER *pHeader, UWORD HeaderByteSize, UWORD CompleteFileSectorSize);
+UWORD dLoaderFlashFileHeader(UWORD Handle, ULONG FileStartAdr, FILEHEADER *pHeader, UWORD HeaderByteSize);
+UWORD dLoaderFindFirstSector(UBYTE Type, UWORD SectorCount, UWORD *pSector);
+UWORD dLoaderAllocateWriteBuffer(UWORD Handle);
+UWORD dLoaderSetFilePointer(UWORD Handle, ULONG BytePtr, const UBYTE **pData);
+UWORD dLoaderGetSectorNumber(ULONG Adr);
+void dLoaderCheckVersion(void);
+UWORD dLoaderCheckHandle(UWORD Handle, UBYTE Operation);
+ULONG dLoaderCalcFreeFileSpace(UWORD NosOfFreeSectors);
+UWORD dLoaderCheckDownload(UBYTE *pName);
+UWORD dLoaderAvailFileNo(void);
+
+
+void dLoaderInit(void)
+{
+ UWORD Tmp;
+
+ LOADERInit;
+
+ Files = (const ULONG*)STARTOFFILETABLE;
+
+ /* Clear handle table */
+ for (Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
+ {
+ HandleTable[Tmp].Status = FREE;
+ HandleTable[Tmp].WriteBufNo = FREEBUFNO;
+ }
+
+ /* Clear write buffers */
+ for (Tmp = 0; Tmp < MAX_WRITE_BUFFERS; Tmp++)
+ {
+ WriteBuffer[Tmp].Status = FREE;
+ }
+
+ dLoaderCheckVersion();
+ dLoaderUpdateSectorTable();
+ FreeUserFlash = dLoaderReturnFreeFlash();
+}
+
+UWORD dLoaderAvailFileNo(void)
+{
+ UBYTE Tmp, Tmp2;
+ UWORD ReturnVal;
+ const ULONG* FlashPtr;
+
+ ReturnVal = NOMOREFILES;
+ Tmp2 = 0;
+ FlashPtr = Files;
+ for(Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
+ {
+
+ /* Check for files allready downloading except datafiles as the have entered their */
+ /* filepointer in the filepointer table at begin of download */
+ if ((DOWNLOADING == HandleTable[Tmp].Status) && (DATAFILE != HandleTable[Tmp].FileType))
+ {
+ Tmp2++;
+ }
+ }
+ if ((0xFFFFFFFF == FlashPtr[(MAX_FILES - 1) - Tmp2]) || (0 == FlashPtr[(MAX_FILES - 1) - Tmp2]))
+ {
+ ReturnVal = SUCCESS;
+ }
+ return(ReturnVal);
+}
+
+
+UWORD dLoaderInsertPtrTable(const UBYTE *pAdr, UWORD Handle)
+{
+ UWORD TmpCnt;
+ UWORD Status;
+ ULONG SectorCopy[(SECTORSIZE/4)];
+ const ULONG* FlashPtr;
+
+ /* It is possible to add the file as checking for number of files */
+ /* is done when initiating the file download */
+ FlashPtr = Files;
+ memset(SectorCopy, 0, sizeof(SectorCopy));
+
+ TmpCnt = MAX_FILES - 1;
+ while(TmpCnt)
+ {
+
+ /* TmpCnt-- first because you want to copy from index 0 */
+ TmpCnt--;
+ SectorCopy[TmpCnt + 1] = FlashPtr[TmpCnt];
+ }
+
+ /* Copy the new file in position 0 */
+ SectorCopy[0] = (ULONG)pAdr;
+
+ /* Add the File version to the top of the file list */
+ SectorCopy[MAX_FILES] = FlashPtr[MAX_FILES];
+ dLoaderWritePage((ULONG)Files, SECTORSIZE, SectorCopy);
+
+ /* FileIndex in HandleTable should be incremented by one - new file index is 0 */
+ for (TmpCnt = 0; TmpCnt < MAX_HANDLES; TmpCnt++)
+ {
+ if (HandleTable[TmpCnt].Status != FREE)
+ {
+ (HandleTable[TmpCnt].FileIndex)++;
+ }
+ }
+ HandleTable[Handle].FileIndex = 0;
+
+ Status = SUCCESS | Handle;
+
+ return(Status);
+}
+
+
+UWORD dLoaderDeleteFilePtr(UWORD Handle)
+{
+
+ UWORD ErrorCode;
+ UWORD LongCnt;
+ ULONG SectorCopy[(SECTORSIZE>>2)];
+ const ULONG *pFlash;
+
+ ErrorCode = SUCCESS;
+ if (0xFFFFFFFF != Files[HandleTable[Handle].FileIndex])
+ {
+ ErrorCode = dLoaderCheckFiles(Handle);
+ if (0x8000 > ErrorCode)
+ {
+ pFlash = Files;
+ for (LongCnt = 0; LongCnt < (HandleTable[Handle].FileIndex); LongCnt++, pFlash++)
+ {
+ SectorCopy[LongCnt] = *pFlash;
+ }
+
+ /* Skip the file that has to be deleted */
+ pFlash++;
+ for ( ; LongCnt < (MAX_FILES - 1); LongCnt++, pFlash++)
+ {
+ SectorCopy[LongCnt] = *pFlash;
+ }
+
+ /* The top file entry is now free */
+ SectorCopy[MAX_FILES - 1] = 0xFFFFFFFF;
+
+ /* Insert the file version */
+ SectorCopy[MAX_FILES] = *pFlash;
+
+
+ /* Write the sectortable back into flash */
+ dLoaderWritePage((ULONG)Files, SECTORSIZE,(ULONG*) &SectorCopy);
+ dLoaderUpdateSectorTable();
+ FreeUserFlash = dLoaderReturnFreeFlash();
+
+ /* Update the HandleTable[].FileIndex */
+ for (LongCnt = 0; LongCnt < MAX_HANDLES; LongCnt++)
+ {
+ if ((HandleTable[Handle].FileIndex <= HandleTable[LongCnt].FileIndex) && (FREE != HandleTable[LongCnt].Status))
+ {
+ (HandleTable[LongCnt].FileIndex)--;
+ }
+ }
+ }
+ }
+ else
+ {
+ ErrorCode = FILENOTFOUND;
+ }
+ return(ErrorCode | Handle);
+}
+
+
+void dLoaderDeleteAllFiles(void)
+{
+ ULONG Tmp;
+ ULONG SectorBuf[SECTORSIZE/4];
+
+ /* Close all handles - all files is to be wiped out */
+ for (Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
+ {
+ dLoaderCloseHandle(Tmp);
+ }
+
+ for (Tmp = ((STARTOFUSERFLASH-FLASHOFFSET)/SECTORSIZE); Tmp < (SIZEOFFLASH/SECTORSIZE); Tmp++)
+ {
+ dLoaderErasePage(Tmp<<SECTORSIZESHIFT);
+ }
+
+ /* Insert the file version */
+ memset(SectorBuf, 0xFF, SECTORSIZE);
+ SectorBuf[(SECTORSIZE/4) - 1] = FILEVERSION;
+ dLoaderWritePage(STARTOFFILETABLE, SECTORSIZE, SectorBuf);
+
+ /* Update all other parameters */
+ dLoaderUpdateSectorTable();
+ FreeUserFlash = dLoaderReturnFreeFlash();
+}
+
+
+void dLoaderUpdateSectorTable(void)
+{
+ UWORD Tmp;
+ UWORD SectorNo;
+ const FILEHEADER *pFile;
+ ULONG FileStart;
+
+ Tmp = 0;
+
+ memset(SectorTable, 0, sizeof(SectorTable));
+
+ /* All file pointer are occupied as default */
+ while (Tmp < MAX_FILES)
+ {
+ SectorNo = dLoaderGetSectorNumber((ULONG)&Files[Tmp]);
+ SectorTable[SectorNo>>5] |= (0x1 << (SectorNo - ((SectorNo>>5)<<5)));
+ Tmp += (SECTORSIZE >> 2);
+ }
+
+ for (Tmp = 0; Tmp < MAX_FILES; Tmp++)
+ {
+ if ((0xFFFFFFFF != Files[Tmp]) && (0x00000000 != Files[Tmp]))
+ {
+ pFile = (const FILEHEADER *) Files[Tmp];
+ FileStart = pFile->FileStartAdr;
+
+ /* This is necessary if the start address is at the first address in an sector */
+ SectorNo = dLoaderGetSectorNumber((ULONG)pFile->FileStartAdr);
+ SectorTable[SectorNo>>5] |= (0x1 << (SectorNo - ((SectorNo>>5)<<5)));
+
+ /* This is necessary as the first sector (where the fileheader is) is not */
+ /* included in the sector table */
+ SectorNo = dLoaderGetSectorNumber((ULONG)Files[Tmp]);
+ SectorTable[SectorNo>>5] |= (0x1 << (SectorNo - ((SectorNo>>5)<<5)));
+
+ SectorNo = 0;
+ while(FileStart > ((ULONG)(&(pFile->FileSectorTable[SectorNo]))) && (NOOFSECTORS > pFile->FileSectorTable[SectorNo]))
+ {
+ SectorTable[(pFile->FileSectorTable[SectorNo])>>5] |= (0x1 << ((pFile->FileSectorTable[SectorNo]) - (((pFile->FileSectorTable[SectorNo])>>5)<<5)));
+ if (0 == ((ULONG)(&(pFile->FileSectorTable[SectorNo+1])) & (SECTORSIZE-1)))
+ {
+ SectorNo += (((pFile->FileSectorTable[SectorNo]) << SECTORSIZESHIFT) - ((ULONG)&(pFile->FileSectorTable[SectorNo]) & ~FLASHOFFSET)>>1);
+ }
+ else
+ {
+ SectorNo++;
+ }
+ }
+ }
+ }
+}
+
+
+UWORD dLoaderCreateFileHeader(ULONG FileSize, UBYTE *pName, UBYTE LinearState, UBYTE FileType)
+{
+ UWORD HeaderByteSize;
+ ULONG FileStartAdr;
+ ULONG CompleteFileByteSize;
+ UWORD Handle;
+ UBYTE Name[FILENAME_SIZE];
+ ULONG FileLength;
+ ULONG DataLength;
+ UWORD ErrorCode;
+ UWORD CompleteSectorNo;
+ UWORD Tmp;
+
+ memset(&(Header.FileName), 0, sizeof(Header.FileName));
+ memset(&(Header.FileSectorTable), 0xFF, sizeof(Header.FileSectorTable));
+
+ ErrorCode = dLoaderFind(pName, Name, &FileLength, &DataLength, (UBYTE)BUSY);
+ Handle = ErrorCode & 0x00FF;
+ if (SUCCESS == (ErrorCode & 0xFF00))
+ {
+ ErrorCode |= FILEEXISTS;
+ }
+ if (FILENOTFOUND == (ErrorCode & 0xFF00))
+ {
+ /* Here check for the download buffers for a matching download */
+ /* in progress */
+ ErrorCode &= 0x00FF;
+ ErrorCode = dLoaderCheckDownload(pName);
+
+ if (0x8000 > ErrorCode)
+ {
+
+ /* Check for file overflow */
+ ErrorCode = dLoaderAvailFileNo();
+ if (0x8000 > ErrorCode)
+ {
+
+ ErrorCode = dLoaderAllocateWriteBuffer(Handle);
+ if (0x8000 > ErrorCode)
+ {
+
+ dLoaderCopyFileName((Header.FileName), pName);
+ HandleTable[Handle].pSectorNo = 0;
+ HandleTable[Handle].DataLength = FileSize; /* used for end of file detection */
+ Header.FileSize = FileSize; /* used to program into flash */
+ if (DATAFILE == FileType)
+ {
+ Header.DataSize = 0;
+ }
+ else
+ {
+ Header.DataSize = FileSize;
+ }
+ HandleTable[Handle].FileType = FileType | LinearState; /* if it is a datafile it can be stopped */
+ Header.FileType = FileType | LinearState; /* FileType included for future appending */
+
+ /* File body size calculation*/
+ CompleteFileByteSize = FileSize;
+
+ /* Add the the fixed header to the fixed size */
+ CompleteFileByteSize += HEADERFIXEDSIZE;
+
+ /* Find the number of sectors used by the fixed file size */
+ CompleteSectorNo = (CompleteFileByteSize - 1) >> SECTORSIZESHIFT;
+
+ /* Add the size taken by the sectortable */
+ CompleteFileByteSize += (CompleteSectorNo << 1);
+
+ /* Recalc the number of sectors - to see wether the sectortable has caused */
+ /* the sectornumber to encrease */
+ Tmp = ((CompleteFileByteSize - 1) >> SECTORSIZESHIFT);
+
+ /* Substract from the original sectors used - Tmp holds the encreased number*/
+ Tmp -= CompleteSectorNo;
+ if (Tmp)
+ {
+ /* The sectortable takes up more than one sector */
+ CompleteFileByteSize += Tmp << 1;
+ CompleteSectorNo += Tmp;
+ }
+
+ HeaderByteSize = CompleteFileByteSize - FileSize;
+
+ if (HeaderByteSize & 0x0003)
+ {
+ /* Header size is not a multiplum of 4 - now make it a mul 4 */
+ HeaderByteSize += (0x0004 - (HeaderByteSize & 0x0003));
+ }
+
+ if (FileSize <= FreeUserFlash)
+ {
+
+
+ /* Allocate file header */
+ Tmp = (((CompleteFileByteSize - 1) >> SECTORSIZESHIFT) + 1);
+ Handle = dLoaderAllocateHeader(Handle, &FileStartAdr, &Header, HeaderByteSize, Tmp);
+ if (Handle < 0x8000)
+ {
+ dLoaderFlashFileHeader(Handle, FileStartAdr, &Header, HeaderByteSize);
+
+ /* If this is a datafile then add the filepointer to the filepointer table */
+ /* now as the datafile do not need to have a special size to be valid */
+ if (DATAFILE & HandleTable[Handle].FileType)
+ {
+ ErrorCode = dLoaderInsertPtrTable((const UBYTE *)HandleTable[Handle].FileDlPtr, Handle);
+ }
+ FreeSectors -= Tmp;
+ FreeUserFlash = dLoaderCalcFreeFileSpace(FreeSectors);
+ HandleTable[Handle].Status = DOWNLOADING;
+ }
+ }
+ else
+ {
+ ErrorCode = NOSPACE;
+ }
+ }
+ }
+ }
+ }
+
+ return(ErrorCode | Handle);
+}
+
+
+UWORD dLoaderWriteData(UWORD Handle, UBYTE *pBuf, UWORD *pLen)
+{
+ UWORD Tmp;
+ UBYTE *pSectorBuf;
+
+ Handle = dLoaderCheckHandle(Handle, DOWNLOADING);
+ if (0x8000 > Handle)
+ {
+
+ if (*pLen > HandleTable[Handle].DataLength)
+ {
+
+ /* Write request exceeds filesize - only flash up to filesize*/
+ *pLen = HandleTable[Handle].DataLength;
+ WriteBuffer[HandleTable[Handle].WriteBufNo].Status = DLERROR; /* save error untill close handle */
+ }
+
+ pSectorBuf = (UBYTE *)WriteBuffer[HandleTable[Handle].WriteBufNo].Buf;
+ for(Tmp = 0; Tmp < *pLen; Tmp++)
+ {
+ pSectorBuf[WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex] = pBuf[Tmp];
+ if ((WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex) >= (SECTORSIZE-1))
+ {
+ dLoaderWritePage(((ULONG)HandleTable[Handle].pFlash & ~(SECTORSIZE - 1)), SECTORSIZE, WriteBuffer[HandleTable[Handle].WriteBufNo].Buf);
+ WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex = 0;
+ HandleTable[Handle].pFlash = dLoaderGetNextSectorPtr(Handle);
+ memset(WriteBuffer[HandleTable[Handle].WriteBufNo].Buf, 0xFF, sizeof(WriteBuffer[0].Buf));
+ }
+ else
+ {
+ (WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex)++;
+ }
+ }
+ HandleTable[Handle].DataLength -= *pLen;
+
+ /* Check for correct end of file */
+ if (0 == HandleTable[Handle].DataLength)
+ {
+ if ((WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex) != 0)
+ {
+
+ /* write the last data into the file */
+ dLoaderWritePage(((ULONG)HandleTable[Handle].pFlash & ~(SECTORSIZE - 1)), WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex, WriteBuffer[HandleTable[Handle].WriteBufNo].Buf);
+ WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex = 0;
+ }
+ }
+ }
+ else
+ {
+ *pLen = 0;
+ }
+
+ if (DLERROR == WriteBuffer[HandleTable[Handle].WriteBufNo].Status)
+ {
+
+ /* DLERROR set due to over flow a file - EOFEXSPECTED should be set */
+ /* for repeated overflow requests */
+ Handle |= EOFEXSPECTED;
+ }
+ return(Handle);
+}
+
+
+UWORD dLoaderGetFreeHandle(void)
+{
+ UBYTE Tmp;
+ UWORD Handle;
+
+ Handle = NOMOREHANDLES;
+ for(Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
+ {
+ if (FREE == HandleTable[Tmp].Status)
+ {
+ HandleTable[Tmp].Status = BUSY;
+ Handle = 0; /* Clear NOMOREHANDLES */
+ Handle = Tmp;
+ Tmp = MAX_HANDLES;
+ }
+ }
+ return(Handle);
+}
+
+const UBYTE * dLoaderGetNextSectorPtr(UBYTE Handle)
+{
+ const UBYTE *pAdr;
+
+ /* Check for the last entry in a sector - if so, */
+ /* then this is the sector number on the next sector table */
+ if (!((ULONG)(HandleTable[Handle].pSectorNo + 1) & (SECTORSIZE-1)))
+ {
+ HandleTable[Handle].pSectorNo = (const UWORD *)(((ULONG)(*(HandleTable[Handle].pSectorNo)) << SECTORSIZESHIFT) | FLASHOFFSET);
+ }
+
+ /* If pointing at an illegal adr then set it to NULL */
+ if (SIZEOFFLASH < (ULONG)((ULONG)(HandleTable[Handle].pSectorNo) & ~FLASHOFFSET))
+ {
+ pAdr = NULL;
+ }
+ else
+ {
+ pAdr = (const UBYTE *)(((ULONG)(*(HandleTable[Handle].pSectorNo)) << SECTORSIZESHIFT) | FLASHOFFSET);
+ }
+
+ (HandleTable[Handle].pSectorNo)++;
+ return(pAdr);
+}
+
+UWORD dLoaderCloseHandle(UWORD Handle)
+{
+ UWORD RtnStatus;
+ FILEHEADER *TmpFileHeader;
+
+
+ RtnStatus = Handle;
+
+ /* if it is a normal handle or handle closed due to an error then error must be different */
+ /* from the no more handles available error (else you would delete a used handle) */
+ if (((0x8000 > Handle) || (NOMOREHANDLES != (Handle & 0xFF00))) && ((UBYTE)Handle < MAX_HANDLES))
+ {
+ Handle &= 0x00FF;
+ if (FREE == HandleTable[Handle].Status)
+ {
+ RtnStatus |= HANDLEALREADYCLOSED;
+ }
+ else
+ {
+
+ /* Handle was NOT free - now close it */
+ if (DOWNLOADING == HandleTable[Handle].Status)
+ {
+ if (DATAFILE & HandleTable[Handle].FileType)
+ {
+
+ /* This is a Datafile that should be closed and this is a legal action */
+ /* 1. Write the data from the writebuffer into flash */
+ /* 2. Update the Datalength in the file header */
+ /* This takes minimum 8 mS (2 page writes into flash) */
+
+ if (WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex)
+ {
+
+ /* There are databytes in the writebuffer write them into flash */
+ dLoaderWritePage(((ULONG)HandleTable[Handle].pFlash & ~(SECTORSIZE - 1)), WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex, WriteBuffer[HandleTable[Handle].WriteBufNo].Buf);
+ }
+
+ /* Now the databuffer is free now use if for a buffer for the fileheader*/
+ memcpy(WriteBuffer[HandleTable[Handle].WriteBufNo].Buf, (void const*)HandleTable[Handle].FileDlPtr, SECTORSIZE);
+ TmpFileHeader = (FILEHEADER *) WriteBuffer[HandleTable[Handle].WriteBufNo].Buf;
+ TmpFileHeader->DataSize = TmpFileHeader->FileSize - HandleTable[Handle].DataLength;
+ dLoaderWritePage(((ULONG)HandleTable[Handle].FileDlPtr & ~(SECTORSIZE - 1)), SECTORSIZE, WriteBuffer[HandleTable[Handle].WriteBufNo].Buf);
+ }
+ else
+ {
+
+ /* This is a system file being closed now update the file pointer table if no error and complete file written */
+ if ((DLERROR != WriteBuffer[HandleTable[Handle].WriteBufNo].Status) && (0 == HandleTable[Handle].DataLength))
+ {
+
+ /* no error durig download - add the file pointer to the file pointer table */
+ Handle = dLoaderInsertPtrTable((const UBYTE *) HandleTable[Handle].FileDlPtr, Handle);
+ }
+ else
+ {
+
+ /* an error has occured during download - now clean up the mess... */
+ dLoaderUpdateSectorTable();
+ FreeUserFlash = dLoaderReturnFreeFlash();
+ }
+ }
+ }
+ if (HandleTable[Handle].WriteBufNo != FREEBUFNO)
+ {
+ WriteBuffer[HandleTable[Handle].WriteBufNo].Status = FREE;
+ HandleTable[Handle].WriteBufNo = FREEBUFNO;
+ }
+ HandleTable[Handle].Status = FREE;
+ }
+ }
+ return(RtnStatus);
+}
+
+
+UWORD dLoaderOpenRead(UBYTE *pFileName, ULONG *pLength)
+{
+ UWORD Handle;
+ UBYTE Name[16];
+ const FILEHEADER *TmpHeader;
+ ULONG FileLength;
+ ULONG DataLength;
+
+ Handle = dLoaderFind(pFileName, Name, &FileLength, &DataLength, (UBYTE)BUSY);
+ if (0x8000 > Handle)
+ {
+ if (FileLength)
+ {
+ TmpHeader = (FILEHEADER const *)(Files[HandleTable[Handle].FileIndex]);
+ HandleTable[Handle].pFlash = (const UBYTE *)TmpHeader->FileStartAdr;
+ HandleTable[Handle].pSectorNo = TmpHeader->FileSectorTable;
+ HandleTable[Handle].DataLength = TmpHeader->DataSize;
+ HandleTable[Handle].ReadLength = 0;
+ *pLength = TmpHeader->DataSize;
+ }
+ else
+ {
+ Handle = FILENOTFOUND;
+ }
+ }
+ return(Handle);
+}
+
+UWORD dLoaderRead(UBYTE Handle, UBYTE *pBuffer, ULONG *pLength)
+{
+ UWORD ByteCnt, Status;
+
+ Status = dLoaderCheckHandle(Handle, BUSY);
+ if (0x8000 > Status)
+ {
+ Status = Handle;
+ ByteCnt = 0;
+ while (ByteCnt < *pLength)
+ {
+ if (HandleTable[Handle].DataLength <= HandleTable[Handle].ReadLength)
+ {
+ *pLength = ByteCnt;
+ Status |= ENDOFFILE;
+ }
+ else
+ {
+ *pBuffer = *(HandleTable[Handle].pFlash);
+ pBuffer++;
+ ByteCnt++;
+ HandleTable[Handle].pFlash++;
+ HandleTable[Handle].ReadLength++;
+ if (!((ULONG)(HandleTable[Handle].pFlash) & (SECTORSIZE-1)))
+ {
+ HandleTable[Handle].pFlash = dLoaderGetNextSectorPtr(Handle);
+ }
+ }
+ }
+ }
+ return(Status);
+}
+
+UWORD dLoaderDelete(UBYTE *pFile)
+{
+ UWORD LStatus;
+ ULONG FileLength;
+ ULONG DataLength;
+ UBYTE Name[FILENAME_LENGTH + 1];
+
+ LStatus = dLoaderFind(pFile, Name, &FileLength, &DataLength, (UBYTE)BUSY);
+
+ if (!IS_LOADER_ERR(LStatus))
+ {
+ LStatus = dLoaderDeleteFilePtr((UBYTE)LStatus);
+ }
+
+ dLoaderCloseHandle(LStatus);
+
+ return(LStatus);
+}
+
+UWORD dLoaderFind(UBYTE *pFind, UBYTE *pFound, ULONG *pFileLength, ULONG *pDataLength, UBYTE Session)
+{
+ UWORD Handle;
+
+ Handle = dLoaderGetFreeHandle();
+ if (Handle < 0x8000)
+ {
+ if (FILENAME_LENGTH < strlen((const char*)pFind))
+ {
+ Handle |= ILLEGALFILENAME;
+ }
+ else
+ {
+ HandleTable[Handle].FileIndex = 0xFFFF;
+ HandleTable[Handle].Status = Session;
+ dLoaderInsertSearchStr((HandleTable[Handle].SearchStr), pFind, &(HandleTable[Handle].SearchType));
+ Handle = dLoaderFindNext(Handle, pFound, pFileLength, pDataLength);
+ }
+ }
+
+ return(Handle);
+}
+
+UWORD dLoaderFindNext(UWORD Handle, UBYTE *pFound, ULONG *pFileLength, ULONG *pDataLength)
+{
+ UBYTE Tmp;
+ UWORD ReturnVal;
+ FILEHEADER *pHeader;
+
+ *pFileLength = 0;
+ ReturnVal = Handle | FILENOTFOUND;
+
+
+ for (Tmp = ((HandleTable[Handle].FileIndex) + 1); Tmp < MAX_FILES; Tmp++)
+ {
+ if (0xFFFFFFFF != Files[Tmp])
+ {
+ if (SUCCESS == dLoaderCheckName((UBYTE*)Files[Tmp], HandleTable[Handle].SearchStr, HandleTable[Handle].SearchType))
+ {
+ HandleTable[Handle].FileIndex = Tmp;
+ Tmp = MAX_FILES;
+ ReturnVal = Handle;
+ }
+ }
+ }
+ if (0x8000 > ReturnVal)
+ {
+ pHeader = (FILEHEADER *)Files[HandleTable[Handle].FileIndex];
+ if (NULL != pFileLength)
+ {
+ *pFileLength = pHeader->FileSize;
+ }
+ if (NULL != pDataLength)
+ {
+ *pDataLength = pHeader->DataSize;
+ }
+ if (NULL != pFound)
+ {
+ dLoaderCopyFileName(pFound, (UBYTE *)pHeader->FileName);
+ }
+ }
+ return(ReturnVal);
+}
+
+
+ULONG dLoaderReturnFreeFlash(void)
+{
+ ULONG SectorCnt, IndexPtr;
+ UWORD Sectors;
+
+
+ Sectors = 0;
+ IndexPtr = (ULONG)0x01 << SECTORPOINTERUSERFLASH; /* Offset in first index can be different from 0 */
+ for(SectorCnt = SECTORINDEXUSERFLASH; SectorCnt <= ((NOOFSECTORS>>5)-1); SectorCnt++)
+ {
+ for( ; IndexPtr > 0; IndexPtr<<=1)
+ {
+ if (!(SectorTable[SectorCnt] & IndexPtr))
+ {
+ Sectors++;
+ }
+ }
+ IndexPtr = 0x00000001;
+ }
+
+ FreeSectors = Sectors;
+ return(dLoaderCalcFreeFileSpace(Sectors));
+}
+
+ULONG dLoaderCalcFreeFileSpace(UWORD NosOfFreeSectors)
+{
+ UWORD SectorCnt;
+ ULONG Space;
+ ULONG HeaderSpace;
+
+ /* Calculate only if any sectors available */
+ if (NosOfFreeSectors)
+ {
+
+ Space = (ULONG)NosOfFreeSectors << SECTORSIZESHIFT;
+
+ /* (FreeSectors - 1) is beacuse the the first sector of a file do not */
+ /* require an entry in the sector table - it is pointed to by the filepointer */
+ /* in the file pointer table*/
+ SectorCnt = NosOfFreeSectors - 1;
+
+ /* If more that one sector is used for the header the first filebody sector do not */
+ /* require an entry in the sectortable - it is pointed to by the file startpointer */
+ /* in the file header */
+ if ((((SectorCnt<<1) + HEADERFIXEDSIZE) & (SECTORSIZE - 1)) < 4)
+ {
+ SectorCnt--;
+ }
+
+ HeaderSpace = (HEADERFIXEDSIZE + (SectorCnt << 1));
+ if (HeaderSpace & 0x0003)
+ {
+ /* Header size is not a multiplum of 4 - now make it a mul 4 */
+ HeaderSpace += (0x0004 - (HeaderSpace & 0x0003));
+ }
+ Space -= HeaderSpace;
+ }
+ return(Space);
+}
+
+
+UWORD dLoaderGetFilePtr(UBYTE *pFileName, UBYTE *pPtrToFile, ULONG *pFileLength)
+{
+ UWORD RtnVal;
+ UBYTE FoundFile[16];
+ FILEHEADER *File;
+ ULONG DataLength;
+
+
+ RtnVal = dLoaderFind(pFileName, FoundFile, pFileLength, &DataLength, (UBYTE)BUSY);
+ if (0x8000 > RtnVal)
+ {
+
+ File = (FILEHEADER*) Files[HandleTable[RtnVal].FileIndex];
+ if (LINEAR & File->FileType)
+ {
+ *((ULONG*)pPtrToFile) = File->FileStartAdr;
+ }
+ else
+ {
+ RtnVal |= NOTLINEARFILE;
+ }
+ }
+ return(RtnVal);
+}
+
+UWORD dLoaderAllocateHeader(UWORD Handle, ULONG *FileStartAdr, FILEHEADER *pHeader, UWORD HeaderByteSize, UWORD CompleteFileSectorSize)
+{
+ UWORD Tmp;
+ UWORD SectorTableIndex;
+ ULONG SectorIndex;
+ UWORD HeaderSectorSize;
+ UBYTE EvenHeader;
+ UWORD FileBodySectorSize;
+ UWORD ErrorCode;
+
+ HeaderSectorSize = ((HeaderByteSize - 1) >> SECTORSIZESHIFT) + 1;
+ FileBodySectorSize = (((pHeader->FileSize - (SECTORSIZE - (HeaderByteSize & (SECTORSIZE - 1)))) - 1) >> SECTORSIZESHIFT) + 1;
+
+ /* First allocate the file file header - this means the file name, */
+ /* the file start adress, and the sector table */
+
+ /* SectorTableIndex indicates in the last word of a sector in which */
+ /* sector the sectortable continues */
+ SectorTableIndex = ((SECTORSIZE - HEADERFIXEDSIZE)>>1) - 1;
+
+ /* Find first free sector - here there is a differende between linear or not*/
+ ErrorCode = dLoaderFindFirstSector(pHeader->FileType, CompleteFileSectorSize, &Tmp);
+
+ if (SUCCESS == ErrorCode)
+ {
+ *FileStartAdr = (ULONG)((ULONG)Tmp << SECTORSIZESHIFT) | FLASHOFFSET;
+ HandleTable[Handle].FileDlPtr = *FileStartAdr;
+
+ SectorIndex = (Tmp >> 5);
+ Tmp &= 0x1F;
+
+ SectorTable[SectorIndex]|= (0x01<<Tmp);
+
+ /* Advance to next sector */
+ Tmp++;
+
+ /* if only one sector used for for file header */
+ pHeader->FileStartAdr = (ULONG)(*FileStartAdr) + HeaderByteSize;
+
+ /* if there is a sectortable it always starts right after the fixed header (Name + start + size)*/
+ HandleTable[Handle].pSectorNo = (const UWORD *)(*FileStartAdr + HEADERFIXEDSIZE);
+
+ /* First header has been allocated by find first function */
+ HeaderSectorSize--;
+ UWORD TmpHSS = HeaderSectorSize;
+
+ /* Next part is only executed when more than one sector is used */
+ if (HeaderSectorSize)
+ {
+ UBYTE ExitCode = FALSE;
+
+ while ((FALSE == ExitCode) && (SectorIndex < (NOOFSECTORS/32)))
+ {
+ for(; ((Tmp < 32) && (ExitCode == FALSE)); Tmp++)
+ {
+ if (!(SectorTable[SectorIndex] & (0x01<<Tmp)))
+ {
+ /* Sector is free you can have this one */
+ SectorTable[SectorIndex] |= (0x01<<Tmp);
+ pHeader->FileSectorTable[SectorTableIndex] = (SectorIndex << 5) + Tmp;
+ SectorTableIndex += (SECTORSIZE/2);
+ HeaderSectorSize--;
+ if (0 == HeaderSectorSize)
+ {
+ pHeader->FileStartAdr = (((SectorIndex << 5) + Tmp) << SECTORSIZESHIFT) + (HeaderByteSize - (TmpHSS<<SECTORSIZESHIFT)) | FLASHOFFSET;
+ ExitCode = TRUE;
+ }
+ }
+ }
+ if (FALSE == ExitCode)
+ {
+ SectorIndex++;
+ Tmp = 0;
+ }
+ }
+ }
+
+ EvenHeader = FALSE;
+ if (((HeaderByteSize & (SECTORSIZE - 1)) >= (SECTORSIZE - 2)) || (0 == (HeaderByteSize & (SECTORSIZE - 1))))
+ {
+
+ /* The header uses exact one or several sectors */
+ /* meaning that the next sector do not go into */
+ /* the sectortable as it is pointed to by the */
+ /* FileStart pointer */
+ EvenHeader = TRUE;
+ }
+
+ /* Now allocated the file body */
+ SectorTableIndex = 0;
+ while ((FileBodySectorSize > 0) && (SectorIndex < (NOOFSECTORS/32)))
+ {
+ for(; Tmp < 32; Tmp++)
+ {
+ if (!(SectorTable[SectorIndex] & (0x01<<Tmp)))
+ {
+ if (TRUE == EvenHeader)
+ {
+ /* This sector do not go into the sectortable */
+ /* it is pointed to by the filestart pointer */
+ SectorTable[SectorIndex] |= (0x01<<Tmp);
+ pHeader->FileStartAdr = (((SectorIndex << 5) + Tmp) << SECTORSIZESHIFT) | FLASHOFFSET;
+ EvenHeader = FALSE;
+ }
+ else
+ {
+
+ /* Sector is free you can have this one */
+ SectorTable[SectorIndex] |= (0x01<<Tmp);
+ if (((((SECTORSIZE - HEADERFIXEDSIZE)>>1)-1) == SectorTableIndex) || (((SectorTableIndex - ((SECTORSIZE - HEADERFIXEDSIZE)>>1)) & 0x7F) == 127))
+ {
+ SectorTableIndex++;
+ }
+ pHeader->FileSectorTable[SectorTableIndex] = (SectorIndex << 5) + Tmp;
+ SectorTableIndex++;
+ FileBodySectorSize--;
+ if (0 == FileBodySectorSize)
+ {
+ Tmp = 32;
+ SectorIndex = (NOOFSECTORS/32);
+ }
+ }
+ }
+ }
+ SectorIndex++;
+ Tmp = 0;
+ }
+ }
+ else
+ {
+ Handle |= ErrorCode;
+ }
+ return(Handle);
+}
+
+
+UWORD dLoaderFindFirstSector(UBYTE Type, UWORD SectorCount, UWORD *pSector)
+{
+ UWORD CompleteSectorSize;
+ UWORD SectorIndex;
+ UBYTE Tmp;
+ UWORD SectorCnt;
+ UWORD ErrorCode;
+
+
+ ErrorCode = SUCCESS;
+
+ SectorIndex = SECTORINDEXUSERFLASH;
+ Tmp = SECTORPOINTERUSERFLASH;
+
+
+
+ if (LINEAR & Type)
+ {
+ CompleteSectorSize = SectorCount;
+ ErrorCode = NOLINEARSPACE;
+
+ /* find linear adress space */
+ SectorCnt = CompleteSectorSize;
+
+ while ((SectorCnt > 0) && (SectorIndex < (NOOFSECTORS>>5)))
+ {
+ if ((SectorTable[SectorIndex]) & ((ULONG)0x01<<Tmp))
+ {
+ SectorCnt = CompleteSectorSize;
+ }
+ else
+ {
+ SectorCnt--;
+ if (0 == SectorCnt)
+ {
+ *pSector = ((SectorIndex<<5) + Tmp) - CompleteSectorSize + 1;
+ SectorIndex = (NOOFSECTORS>>5);
+ ErrorCode = SUCCESS;
+ }
+ }
+
+ if (0x1F == Tmp)
+ {
+ SectorIndex++;
+ }
+ Tmp = (Tmp + 1) & 0x1F;
+ }
+ }
+ else
+ {
+ ErrorCode = UNDEFINEDERROR;
+ while(SectorIndex < (NOOFSECTORS>>5))
+ {
+ if (!((SectorTable[SectorIndex]) & ((ULONG)0x01<<Tmp)))
+ {
+ *pSector = (SectorIndex<<5) + Tmp;
+ SectorIndex = (NOOFSECTORS>>5);
+ ErrorCode = SUCCESS;
+ }
+ if (0x1F == Tmp)
+ {
+ SectorIndex++;
+ }
+ Tmp = (Tmp + 1) & 0x1F;
+ }
+ }
+ return(ErrorCode);
+}
+
+
+UWORD dLoaderFlashFileHeader(UWORD Handle, ULONG FileStartAdr, FILEHEADER *pHeader, UWORD HeaderByteSize)
+{
+ ULONG *pBufPtr;
+ ULONG FlashPtr;
+ UWORD HeaderSectorSize;
+
+ pBufPtr = (ULONG*)pHeader;
+ FlashPtr = FileStartAdr;
+ HeaderSectorSize = (HeaderByteSize - 1) >> SECTORSIZESHIFT;
+
+ dLoaderWritePage(FlashPtr, SECTORSIZE, pBufPtr);
+
+ while(HeaderSectorSize)
+ {
+ pBufPtr += (SECTORSIZE>>2);
+ FlashPtr = (((*(pBufPtr - 1) & 0xFFFF0000) >> 16) << SECTORSIZESHIFT) | FLASHOFFSET;
+ dLoaderWritePage(FlashPtr, SECTORSIZE, pBufPtr);
+ HeaderSectorSize--;
+ }
+
+ /* Prepare for actual data download */
+ memcpy(WriteBuffer[HandleTable[Handle].WriteBufNo].Buf, pBufPtr, SECTORSIZE);
+ WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex = (UWORD)(pHeader->FileStartAdr) & (SECTORSIZE-1);
+ HandleTable[Handle].pFlash = (UBYTE *)pHeader->FileStartAdr;
+
+ return(Handle);
+}
+
+UWORD dLoaderGetSectorNumber(ULONG Adr)
+{
+ UWORD SectorNo;
+
+ SectorNo = (Adr & ~FLASHOFFSET)>>SECTORSIZESHIFT;
+
+ return(SectorNo);
+}
+
+
+UWORD dLoaderAllocateWriteBuffer(UWORD Handle)
+{
+ UBYTE Tmp;
+ UWORD ErrorCode;
+
+ ErrorCode = NOWRITEBUFFERS;
+ for (Tmp = 0; Tmp < MAX_WRITE_BUFFERS; Tmp++)
+ {
+ if (FREE == WriteBuffer[Tmp].Status)
+ {
+ WriteBuffer[Tmp].Status = BUSY;
+ memset(WriteBuffer[Tmp].Buf, 0xFF, sizeof(WriteBuffer[Tmp].Buf));
+ WriteBuffer[Tmp].BufIndex = 0;
+ HandleTable[Handle].WriteBufNo = Tmp;
+ ErrorCode = SUCCESS;
+ Tmp = MAX_WRITE_BUFFERS;
+ }
+ }
+ Handle |= ErrorCode;
+ return(Handle);
+}
+
+UWORD dLoaderCheckFiles(UBYTE Handle)
+{
+ UBYTE Tmp;
+ UBYTE Index;
+ UWORD ErrorCode;
+
+ ErrorCode = SUCCESS;
+ Index = HandleTable[Handle].FileIndex;
+ for (Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
+ {
+ if ((BUSY == HandleTable[Tmp].Status) && (Index == HandleTable[Tmp].FileIndex) && (Tmp != Handle))
+ {
+ ErrorCode = FILEISBUSY;
+ }
+ }
+ return(Handle | ErrorCode);
+}
+
+void dLoaderCopyFileName(UBYTE *pDst, UBYTE *pSrc)
+{
+ UBYTE Tmp;
+
+ for(Tmp = 0; Tmp < FILENAME_SIZE; Tmp++, pDst++)
+ {
+ if ('\0' != *pSrc)
+ {
+ *pDst = *pSrc;
+ pSrc++;
+ }
+ else
+ {
+ *pDst = '\0';
+ }
+ }
+}
+
+void dLoaderCheckVersion(void)
+{
+ ULONG Version;
+
+ Version = *(const ULONG*)(STARTOFFILETABLE + (MAX_FILES * 4));
+ if (Version != FILEVERSION)
+ {
+ dLoaderDeleteAllFiles();
+ }
+}
+
+UWORD dLoaderOpenAppend(UBYTE *pFileName, ULONG *pAvailSize)
+{
+ UWORD Handle;
+ ULONG FileSize, DataSize;
+ UBYTE Name[FILENAME_SIZE];
+ FILEHEADER *pHeader;
+
+ *pAvailSize = 0;
+
+ Handle = dLoaderFind(pFileName, Name, &FileSize, &DataSize, (UBYTE)BUSY);
+ if (0x8000 > Handle)
+ {
+
+ /* Check for an append in progress for this file */
+ if (0x8000 > dLoaderCheckDownload(pFileName))
+ {
+
+ /* File has bee found - check for then correct filetype (Datafile) */
+ pHeader = (FILEHEADER *)Files[HandleTable[Handle].FileIndex];
+ if (DATAFILE & pHeader->FileType)
+ {
+ if (FileSize > DataSize)
+ {
+ /* Append is possible */
+ Handle = dLoaderAllocateWriteBuffer(Handle);
+ if (Handle < 0x8000)
+ {
+ dLoaderSetFilePointer(Handle, DataSize, &(HandleTable[Handle].pFlash));
+ WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex = (ULONG)(HandleTable[Handle].pFlash) & (SECTORSIZE - 1);
+ memcpy(WriteBuffer[HandleTable[Handle].WriteBufNo].Buf, (const UBYTE *)((ULONG)(HandleTable[Handle].pFlash) & ~(SECTORSIZE - 1)), WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex );
+ HandleTable[Handle].FileDlPtr = Files[HandleTable[Handle].FileIndex];
+ HandleTable[Handle].Status = (UBYTE)DOWNLOADING;
+ *pAvailSize = FileSize - DataSize;
+ HandleTable[Handle].DataLength = *pAvailSize;
+ HandleTable[Handle].FileType = pHeader->FileType;
+ }
+ }
+ else
+ {
+ Handle |= FILEISFULL;
+ }
+ }
+ else
+ {
+ Handle |= APPENDNOTPOSSIBLE;
+ }
+ }
+ else
+ {
+ Handle |= FILEISBUSY;
+ }
+ }
+
+ return(Handle);
+}
+
+
+UWORD dLoaderSetFilePointer(UWORD Handle, ULONG BytePtr, const UBYTE **pData)
+{
+ ULONG AdrOffset;
+ const UBYTE *Adr;
+ UWORD SectorNo;
+ UWORD Tmp;
+ FILEHEADER *pHeader;
+
+
+ pData = pData;
+ pHeader = (FILEHEADER*)Files[HandleTable[Handle].FileIndex];
+ HandleTable[Handle].pSectorNo = pHeader->FileSectorTable;
+
+ /* Get the sector offset */
+ AdrOffset = SECTORSIZE - ((pHeader->FileStartAdr) & (SECTORSIZE - 1));
+
+ if (BytePtr > AdrOffset)
+ {
+ BytePtr = BytePtr - AdrOffset;
+ SectorNo = ((BytePtr >> SECTORSIZESHIFT) + 1);
+
+ for (Tmp = 0; Tmp < SectorNo; Tmp++)
+ {
+ Adr = dLoaderGetNextSectorPtr(Handle);
+ if (BytePtr > SECTORSIZE)
+ {
+ BytePtr -= SECTORSIZE;
+ }
+ }
+ *pData = (const UBYTE *)((ULONG)Adr + BytePtr);
+ }
+ else
+ {
+
+ /* Pointer reside in the first sector of the file body */
+ *pData = (const UBYTE *)((ULONG)(pHeader->FileStartAdr) + BytePtr);
+ }
+ return(Handle);
+}
+
+void dLoaderCpyToLower(UBYTE *pDst, UBYTE *pSrc, UBYTE Length)
+{
+ UBYTE Tmp;
+
+ for(Tmp = 0; Tmp < Length; Tmp++)
+ {
+ pDst[Tmp] =(UBYTE)toupper((UWORD)pSrc[Tmp]);
+ }
+
+ /* The requried length has been copied - now fill with zeros */
+ for(Tmp = Length; Tmp < FILENAME_SIZE; Tmp++)
+ {
+ pDst[Tmp] = '\0';
+ }
+}
+
+UWORD dLoaderCheckName(UBYTE *pName, UBYTE *pSearchStr, UBYTE SearchType)
+{
+ UBYTE TmpName[FILENAME_SIZE];
+ UWORD RtnVal;
+
+ RtnVal = UNDEFINEDERROR;
+
+ dLoaderCpyToLower(TmpName, pName, (UBYTE)FILENAME_SIZE);
+
+ RtnVal = SUCCESS;
+ switch (SearchType)
+ {
+ case FULLNAME:
+ {
+ if (0 != strcmp((const char*)TmpName, (const char *)pSearchStr))
+ {
+ RtnVal = UNDEFINEDERROR;
+ }
+ }
+ break;
+ case NAME:
+ {
+ if (0 != memcmp(TmpName, pSearchStr, strlen((const char *)pSearchStr)))
+ {
+ RtnVal = UNDEFINEDERROR;
+ }
+ }
+ break;
+ case EXTENTION:
+ {
+ if (0 == strstr((const char *)TmpName, (const char*)pSearchStr))
+ {
+ RtnVal = UNDEFINEDERROR;
+ }
+ }
+ break;
+ case WILDCARD:
+ {
+ RtnVal = SUCCESS;
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+ return(RtnVal);
+}
+
+void dLoaderInsertSearchStr(UBYTE *pDst, UBYTE *pSrc, UBYTE *pSearchType)
+{
+ UBYTE Tmp;
+
+ *pSearchType = WILDCARD;
+ if (0 != strstr((char const *)pSrc, "*.*"))
+ {
+
+ /* find all */
+ strcpy ((PSZ)pDst, (PSZ)pSrc);
+ *pSearchType = WILDCARD;
+ }
+ else
+ {
+
+ /* Using other wild cards? */
+ Tmp = strlen((char const *)pSrc);
+ if (0 != strstr((PSZ)(pSrc), ".*"))
+ {
+
+ /* Extention wildcard */
+ dLoaderCpyToLower(pDst, pSrc, (Tmp-1));
+ *pSearchType = NAME;
+ }
+ else
+ {
+ if (0 != strstr((PSZ)(pSrc), "*."))
+ {
+
+ /* Filename wildcard */
+ dLoaderCpyToLower(pDst, &pSrc[1], (UBYTE)4);
+ *pSearchType = EXTENTION;
+ }
+ else
+ {
+
+ /* no wildcards used */
+ dLoaderCpyToLower(pDst, pSrc, Tmp);
+ *pSearchType = FULLNAME;
+ }
+ }
+ }
+}
+
+UWORD dLoaderCheckHandle(UWORD Handle, UBYTE Operation)
+{
+
+ if (MAX_HANDLES > Handle)
+ {
+ if (Operation != HandleTable[(UBYTE)Handle].Status)
+ {
+ Handle |= ILLEGALHANDLE;
+ }
+ }
+ else
+ {
+ Handle |= ILLEGALHANDLE;
+ }
+ return(Handle);
+}
+
+ULONG dLoaderReturnFreeUserFlash(void)
+{
+ return(FreeUserFlash);
+}
+
+UWORD dLoaderRenameFile(UBYTE Handle, UBYTE *pNewName)
+{
+ ULONG SectorBuf[SECTORSIZE/4];
+ ULONG *pFile;
+ UBYTE Tmp;
+ FILEHEADER *pHeader;
+
+ pFile = (ULONG *)Files[HandleTable[Handle].FileIndex];
+ for (Tmp = 0; Tmp < (SECTORSIZE/4); Tmp++)
+ {
+ SectorBuf[Tmp] = pFile[Tmp];
+ }
+
+ pHeader = (FILEHEADER *) SectorBuf;
+
+ dLoaderCopyFileName((pHeader->FileName), pNewName);
+ dLoaderWritePage((ULONG)pFile, SECTORSIZE, SectorBuf);
+ return(SUCCESS);
+}
+
+
+UWORD dLoaderCheckDownload(UBYTE *pName)
+{
+ UBYTE Tmp;
+ UWORD ErrorCode;
+
+ ErrorCode = SUCCESS;
+ for(Tmp = 0; Tmp < MAX_HANDLES; Tmp ++)
+ {
+ if (DOWNLOADING == HandleTable[Tmp].Status)
+ {
+ if (SUCCESS == dLoaderCheckName(pName, HandleTable[Tmp].SearchStr, FULLNAME))
+ {
+ Tmp = MAX_HANDLES;
+ ErrorCode = FILEEXISTS;
+ }
+ }
+ }
+ return(ErrorCode);
+}
+
+
+void dLoaderExit(void)
+{
+}
diff --git a/AT91SAM7S256/Source/d_loader.h b/AT91SAM7S256/Source/d_loader.h
new file mode 100644
index 0000000..0279631
--- /dev/null
+++ b/AT91SAM7S256/Source/d_loader.h
@@ -0,0 +1,99 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 28-03-07 14:54 $
+//
+// Filename $Workfile:: d_loader.h $
+//
+// Version $Revision:: 40 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_loader.h $
+//
+// Platform C
+//
+
+#ifndef D_LOADER
+#define D_LOADER
+
+#define STARTOFFILETABLE (0x13FF00L)
+#define STARTOFUSERFLASH (0x121400L)//(0x11F000L)
+#define SIZEOFUSERFLASH (STARTOFFILETABLE - STARTOFUSERFLASH)
+
+#define SIZEOFFLASH 262144L
+#define SECTORSIZE 256L
+#define SECTORSIZESHIFT 8
+#define NOOFSECTORS (SIZEOFFLASH/SECTORSIZE)
+#define HEADERFIXEDSIZE (FILENAME_SIZE + 4 + 4 + 4 + 2 + 2)
+#define FILENAME_SIZE (FILENAME_LENGTH + 1)
+
+#define FULLNAME 1
+#define NAME 2
+#define EXTENTION 3
+#define WILDCARD 4
+
+/* Enum related to HandleTable Status */
+enum
+{
+ FREE,
+ BUSY,
+ DOWNLOADING,
+ SEARCHING,
+ DLERROR
+};
+
+/* Enum related to HandleTable WriteBufNo */
+enum
+{
+ FREEBUFNO = 0xFF
+};
+
+
+/* Constants related to filetype */
+enum
+{
+ SYSTEMFILE = 0x01,
+ DATAFILE = 0x02,
+ LINEAR = 0x04,
+ NONLINEAR = 0x08
+};
+
+typedef struct
+{
+ UBYTE FileName[FILENAME_SIZE];
+ ULONG FileStartAdr;
+ ULONG FileSize;
+ ULONG DataSize;
+ UWORD CheckSum;
+ UWORD FileType;
+ UWORD FileSectorTable[SIZEOFUSERFLASH/SECTORSIZE];
+}FILEHEADER;
+
+void dLoaderInit(void);
+__ramfunc UWORD dLoaderWritePage(ULONG Flash_Address, UWORD Size, ULONG *pBuf);
+UWORD dLoaderInsertPtrTable(const UBYTE *pAdr, UWORD Handle);
+UWORD dLoaderCreateFileHeader(ULONG FileSize, UBYTE *pName, UBYTE LinearState, UBYTE FileType);
+UWORD dLoaderWriteData(UWORD Handle, UBYTE *pBuf, UWORD *pLen);
+UWORD dLoaderCloseHandle(UWORD Handle);
+UWORD dLoaderOpenRead(UBYTE *pFileName, ULONG *pLength);
+UWORD dLoaderRead(UBYTE Handle, UBYTE *pBuf, ULONG *pLength);
+UWORD dLoaderDelete(UBYTE *pFile);
+UWORD dLoaderFind(UBYTE *pFind, UBYTE *pFound, ULONG *pFileLength, ULONG *pDataLength, UBYTE Session);
+UWORD dLoaderFindNext(UWORD Handle, UBYTE *pFound, ULONG *pFileLength, ULONG *pDataLength);
+UWORD dLoaderDeleteFilePtr(UWORD Handle);
+void dLoaderDeleteAllFiles(void);
+UWORD dLoaderGetFilePtr(UBYTE *pFileName, UBYTE *pPtrToFile, ULONG *pFileLength);
+void dLoaderCopyFileName(UBYTE *pDst, UBYTE *pSrc);
+UWORD dLoaderOpenAppend(UBYTE *pFileName, ULONG *pAvailSize);
+void dLoaderCpyToLower(UBYTE *pDst, UBYTE *pSrc, UBYTE Length);
+UWORD dLoaderCheckName(UBYTE *pName, UBYTE *pSearchStr, UBYTE SearchType);
+void dLoaderInsertSearchStr(UBYTE *pDst, UBYTE *pSrc, UBYTE *pSearchType);
+ULONG dLoaderReturnFreeUserFlash(void);
+UWORD dLoaderRenameFile(UBYTE Handle, UBYTE *pNewName);
+UWORD dLoaderCheckFiles(UBYTE Handle);
+
+
+
+
+void dLoaderExit(void);
+
+#endif
diff --git a/AT91SAM7S256/Source/d_loader.r b/AT91SAM7S256/Source/d_loader.r
new file mode 100644
index 0000000..bec0c90
--- /dev/null
+++ b/AT91SAM7S256/Source/d_loader.r
@@ -0,0 +1,117 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 8:27 $
+//
+// Filename $Workfile:: d_loader.r $
+//
+// Version $Revision:: 8 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_loader.r $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+#define AT91C_MC_CORRECT_KEY 0x5A000000L
+
+static ULONG SectorImage[SECTORSIZE>>2];
+
+#define LOADERInit
+
+
+__ramfunc UWORD AT91F_Flash_Ready (void)
+{
+ UWORD status;
+ status = 0;
+
+ //* Wait the end of command
+ while ((status & AT91C_MC_FRDY) != AT91C_MC_FRDY )
+ {
+ status = AT91C_BASE_MC->MC_FSR;
+ }
+ return status;
+}
+
+__ramfunc UWORD dLoaderWritePage(ULONG Flash_Address, UWORD Size, ULONG *pBuf)
+{
+ //* set the Flash controller base address
+ AT91PS_MC ptMC = AT91C_BASE_MC;
+ unsigned int i, page, status;
+ unsigned int * Flash;
+
+ //* init flash pointer
+ Flash = (unsigned int *) (Flash_Address | (unsigned int)AT91C_IFLASH);
+
+ //* Get the Flash page number
+ page = ((Flash_Address & ~(unsigned int)AT91C_IFLASH) >> SECTORSIZESHIFT);
+
+ //* copy the new value
+ if (Size & 0x0003)
+ {
+ Size = Size + (0x0004 - (Size & 0x0003));
+ }
+ for (i=0; (i < SECTORSIZE) & (Size > 0) ;i++, Flash++,pBuf++,Size-=4 )
+ {
+ //* copy the flash to the write buffer ensuring code generation
+ *Flash=*pBuf;
+ }
+
+ //* Write the write page command
+ ptMC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG | (AT91C_MC_PAGEN & (page <<8));
+
+ //* Wait the end of command
+ status = AT91F_Flash_Ready();
+
+ //* Check the result
+ if ( (status & ( AT91C_MC_PROGE | AT91C_MC_LOCKE ))!=0)
+ {
+ return FALSE;
+ }
+ return TRUE;
+
+}
+
+__ramfunc UWORD dLoaderErasePage(ULONG Flash_Address)
+{
+ //* set the Flash controller base address
+ AT91PS_MC ptMC = AT91C_BASE_MC;
+ unsigned int i, page, status, Size;
+ unsigned int * Flash;
+
+ Size = SECTORSIZE;
+
+ //* init flash pointer
+ Flash = (unsigned int *) (Flash_Address | (unsigned int)AT91C_IFLASH);
+
+ //* Get the Flash page number
+ page = ((Flash_Address & ~(unsigned int)AT91C_IFLASH) >> SECTORSIZESHIFT);
+
+ //* copy the new value
+ for (i=0; (i < SECTORSIZE) & (Size > 0) ;i++, Flash++,Size-=4 )
+ {
+ //* copy the flash to the write buffer ensuring code generation
+ *Flash=0xFFFFFFFF;
+ }
+
+ //* Write the write page command
+ ptMC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG | (AT91C_MC_PAGEN & (page <<8));
+
+ //* Wait the end of command
+ status = AT91F_Flash_Ready();
+
+ //* Check the result
+ if ( (status & ( AT91C_MC_PROGE | AT91C_MC_LOCKE ))!=0)
+ {
+ return FALSE;
+ }
+ return TRUE;
+
+}
+
+
+
+
+
+#endif
diff --git a/AT91SAM7S256/Source/d_lowspeed.c b/AT91SAM7S256/Source/d_lowspeed.c
new file mode 100644
index 0000000..e3b5ba8
--- /dev/null
+++ b/AT91SAM7S256/Source/d_lowspeed.c
@@ -0,0 +1,77 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: d_lowspeed.c $
+//
+// Version $Revision:: 14 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_lowspeed $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "m_sched.h"
+#include "d_lowspeed.h"
+#include "d_lowspeed.r"
+
+
+void dLowSpeedInit(void)
+{
+ LOWSpeedTxInit;
+ LOWSpeedTimerInit;
+ //ENABLEDebugOutput;
+}
+
+void dLowSpeedStartTimer(void)
+{
+ ENABLEPWMTimerForLowCom;
+}
+
+void dLowSpeedStopTimer(void)
+{
+ DISABLEPWMTimerForLowCom;
+}
+
+void dLowSpeedInitPins(UBYTE ChannelNumber)
+{
+ ENABLETxPins(ChannelNumber);
+}
+
+UBYTE dLowSpeedSendData(UBYTE ChannelNumber, UBYTE *DataOutBuffer, UBYTE NumberOfTxByte)
+{
+ UBYTE Status;
+
+ TxData(ChannelNumber, Status, DataOutBuffer, NumberOfTxByte);
+ return(Status);
+}
+
+void dLowSpeedReceiveData(UBYTE ChannelNumber, UBYTE *DataInBuffer, UBYTE ByteToRx)
+{
+ RxData(ChannelNumber, DataInBuffer, ByteToRx);
+}
+
+UBYTE dLowSpeedComTxStatus(UBYTE ChannelNumber)
+{
+ UBYTE Status;
+
+ STATUSTxCom(ChannelNumber, Status)
+
+ return(Status);
+}
+
+UBYTE dLowSpeedComRxStatus(UBYTE ChannelNumber)
+{
+ UBYTE Status;
+
+ STATUSRxCom(ChannelNumber, Status)
+
+ return(Status);
+}
+
+void dLowSpeedExit(void)
+{
+ LOWSpeedExit;
+}
diff --git a/AT91SAM7S256/Source/d_lowspeed.h b/AT91SAM7S256/Source/d_lowspeed.h
new file mode 100644
index 0000000..9a680f0
--- /dev/null
+++ b/AT91SAM7S256/Source/d_lowspeed.h
@@ -0,0 +1,28 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: d_lowspeed.h $
+//
+// Version $Revision:: 7 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_lowspeed $
+//
+// Platform C
+//
+
+#ifndef D_LOWSPEED
+#define D_LOWSPEED
+
+void dLowSpeedInit(void);
+void dLowSpeedStartTimer(void);
+void dLowSpeedStopTimer(void);
+void dLowSpeedInitPins(UBYTE ChannelNumber);
+UBYTE dLowSpeedSendData(UBYTE ChannelNumber, UBYTE *DataOutBuffer, UBYTE NumberOfTxByte);
+void dLowSpeedReceiveData(UBYTE ChannelNumber, UBYTE *DataInBuffer, UBYTE ByteToRx);
+UBYTE dLowSpeedComTxStatus(UBYTE ChannelNumber);
+UBYTE dLowSpeedComRxStatus(UBYTE ChannelNumber);
+void dLowSpeedExit(void);
+
+#endif
diff --git a/AT91SAM7S256/Source/d_lowspeed.r b/AT91SAM7S256/Source/d_lowspeed.r
new file mode 100644
index 0000000..f811193
--- /dev/null
+++ b/AT91SAM7S256/Source/d_lowspeed.r
@@ -0,0 +1,932 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 19-09-06 15:05 $
+//
+// Filename $Workfile:: d_lowspeed.r $
+//
+// Version $Revision:: 24 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_lowspeed $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+#if defined (PROTOTYPE_PCB_3) || (PROTOTYPE_PCB_4)
+
+#define CHANNEL_ONE_CLK AT91C_PIO_PA23 /* PA23 is Clk */
+#define CHANNEL_ONE_DATA AT91C_PIO_PA18 /* PA18 is Data */
+
+#define CHANNEL_TWO_CLK AT91C_PIO_PA28 /* PA28 is Clk */
+#define CHANNEL_TWO_DATA AT91C_PIO_PA19 /* PA19 is Data */
+
+#define CHANNEL_THREE_CLK AT91C_PIO_PA29 /* PA29 is Clk */
+#define CHANNEL_THREE_DATA AT91C_PIO_PA20 /* PA20 is Data */
+
+#define CHANNEL_FOUR_CLK AT91C_PIO_PA30 /* PA30 is Clk */
+#define CHANNEL_FOUR_DATA AT91C_PIO_PA2 /* PA2 is Data */
+
+#else
+
+#define CHANNEL_ONE_CLK AT91C_PIO_PA28 /* PA28 is Clk */
+#define CHANNEL_ONE_DATA AT91C_PIO_PA20 /* PA20 is Data */
+
+#endif
+
+typedef struct
+{
+ UWORD MaskBit;
+ UBYTE ChannelState;
+ UBYTE TxState;
+ UBYTE RxState;
+ UBYTE ReStartState;
+ UBYTE TxByteCnt;
+ UBYTE RxByteCnt;
+ UBYTE *pComOutBuffer;
+ UBYTE *pComInBuffer;
+ UBYTE AckStatus;
+ UBYTE RxBitCnt;
+ UBYTE ReStartBit;
+ UBYTE ComDeviceAddress;
+ UBYTE RxWaitCnt;
+}LOWSPEEDPARAMETERS;
+
+static LOWSPEEDPARAMETERS LowSpeedData[4];
+
+ULONG DATA_PINS[4] = {CHANNEL_ONE_DATA, CHANNEL_TWO_DATA, CHANNEL_THREE_DATA, CHANNEL_FOUR_DATA};
+ULONG CLK_PINS[4] = {CHANNEL_ONE_CLK, CHANNEL_TWO_CLK, CHANNEL_THREE_CLK, CHANNEL_FOUR_CLK};
+
+#define LOWSPEED_CHANNEL1 0
+#define LOWSPEED_CHANNEL2 1
+#define LOWSPEED_CHANNEL3 2
+#define LOWSPEED_CHANNEL4 3
+#define NO_OF_LOWSPEED_COM_CHANNEL 4
+
+#define MASK_BIT_8 0x80
+
+#define PIO_INQ 0x04
+
+//Used for variable ChannelState
+#define LOWSPEED_IDLE 0x00
+#define LOWSPEED_TX_STOP_BIT 0x01
+#define LOWSPEED_TRANSMITTING 0x02
+#define LOWSPEED_RECEIVING 0x04
+#define LOWSPEED_TEST_WAIT_STATE 0x08
+#define LOWSPEED_RESTART_CONDITION 0x10
+#define LOWSPEED_WAIT_BEFORE_RX 0x20
+
+//Used for variable TxState
+#define TX_IDLE 0x00
+#define TX_DATA_MORE_DATA 0x01
+#define TX_DATA_CLK_HIGH 0x02
+#define TX_EVALUATE_ACK_CLK_HIGH 0x03
+#define TX_DATA_READ_ACK_CLK_LOW 0x04
+#define TX_DATA_CLK_LOW 0x05
+#define TX_ACK_EVALUATED_CLK_LOW 0x06
+
+//Used for variable RxState
+#define RX_IDLE 0x00
+#define RX_START_BIT_CLK_HIGH 0x01
+#define RX_DATA_CLK_HIGH 0x02
+#define RX_ACK_TX_CLK_HIGH 0x03
+#define RX_DATA_CLK_LOW 0x04
+#define RX_DONE_OR_NOT_CLK_LOW 0x05
+
+//Used for variable ReStart
+#define RESTART_STATE_IDLE 0x00
+#define RESTART_STATE_ONE 0x01
+#define RESTART_STATE_TWO 0x02
+#define RESTART_STATE_THREE 0x03
+#define RESTART_STATE_FOUR 0x04
+#define RESTART_STATE_FIVE 0x05
+#define RESTART_STATE_SIX 0x06
+#define RESTART_STATE_SEVEN 0x07
+
+#define LOWSpeedTxInit {\
+ LowSpeedData[LOWSPEED_CHANNEL1].ChannelState = 0;\
+ LowSpeedData[LOWSPEED_CHANNEL2].ChannelState = 0;\
+ LowSpeedData[LOWSPEED_CHANNEL3].ChannelState = 0;\
+ LowSpeedData[LOWSPEED_CHANNEL4].ChannelState = 0;\
+ }
+
+#define LOWSpeedTimerInit {\
+ *AT91C_PMC_PCER = 0x400; /* Enable clock for PWM, PID10*/\
+ *AT91C_PWMC_MR = 0x01; /* CLKA is output from prescaler */\
+ *AT91C_PWMC_MR |= 0x600; /* Prescaler MCK divided with 64 */\
+ *AT91C_PWMC_CH0_CMR = 0x06; /* Channel 0 uses MCK divided by 64 */\
+ *AT91C_PWMC_CH0_CMR &= 0xFFFFFEFF; /* Left alignment on periode */\
+ *AT91C_PWMC_CH0_CPRDR = 0x20; /* Set to 39 => 52uSecondes interrupt */\
+ *AT91C_PWMC_IDR = AT91C_PWMC_CHID0; /* Disable interrupt for PWM output channel 0 */\
+ *AT91C_AIC_IDCR = 0x400; /* Disable AIC intterupt on ID10 PWM */\
+ AT91C_AIC_SVR[10] = (unsigned int)LowSpeedPwmIrqHandler;\
+ AT91C_AIC_SMR[10] = 0x01; /* Enable trigger on level */\
+ *AT91C_AIC_ICCR = 0x400; /* Clear interrupt register PID10*/\
+ *AT91C_PWMC_IER = AT91C_PWMC_CHID0; /* Enable interrupt for PWM output channel 0 */\
+ *AT91C_AIC_IECR = 0x400; /* Enable interrupt from PWM */\
+ }
+
+#define LOWSpeedExit
+
+#define ENABLEDebugOutput {\
+ *AT91C_PIOA_PER = AT91C_PIO_PA29; /* Enable PIO on PA029 */\
+ *AT91C_PIOA_OER = AT91C_PIO_PA29; /* PA029 set to Output */\
+ *AT91C_PIOA_CODR = 0x20000000;\
+ }
+
+#define SETDebugOutputHigh *AT91C_PIOA_SODR = 0x20000000
+
+#define SETDebugOutputLow *AT91C_PIOA_CODR = 0x20000000
+
+
+#define SETClkComOneHigh *AT91C_PIOA_SODR = CHANNEL_ONE_CLK
+
+#define SETClkComOneLow *AT91C_PIOA_CODR = CHANNEL_ONE_CLK
+
+#define GetClkComOnePinLevel *AT91C_PIOA_PDSR & CHANNEL_ONE_CLK
+
+#define SETClkComTwoHigh *AT91C_PIOA_SODR = CHANNEL_TWO_CLK
+
+#define SETClkComTwoLow *AT91C_PIOA_CODR = CHANNEL_TWO_CLK
+
+#define GetClkComTwoPinLevel *AT91C_PIOA_PDSR & CHANNEL_TWO_CLK
+
+#define SETClkComThreeHigh *AT91C_PIOA_SODR = CHANNEL_THREE_CLK
+
+#define SETClkComThreeLow *AT91C_PIOA_CODR = CHANNEL_THREE_CLK
+
+#define GetClkComThreePinLevel *AT91C_PIOA_PDSR & CHANNEL_THREE_CLK
+
+#define SETClkComFourHigh *AT91C_PIOA_SODR = CHANNEL_FOUR_CLK
+
+#define SETClkComFourLow *AT91C_PIOA_CODR = CHANNEL_FOUR_CLK
+
+#define GetClkComFourPinLevel *AT91C_PIOA_PDSR & CHANNEL_FOUR_CLK
+
+
+#define SETDataComOneHigh *AT91C_PIOA_SODR = CHANNEL_ONE_DATA
+
+#define SETDataComOneLow *AT91C_PIOA_CODR = CHANNEL_ONE_DATA
+
+#define GetDataComOnePinLevel *AT91C_PIOA_PDSR & CHANNEL_ONE_DATA
+
+#define GETDataComOnePinDirection *AT91C_PIOA_OSR & CHANNEL_ONE_DATA
+
+#define SETDataComTwoHigh *AT91C_PIOA_SODR = CHANNEL_TWO_DATA
+
+#define SETDataComTwoLow *AT91C_PIOA_CODR = CHANNEL_TWO_DATA
+
+#define GetDataComTwoPinLevel *AT91C_PIOA_PDSR & CHANNEL_TWO_DATA
+
+#define GETDataComTwoPinDirection *AT91C_PIOA_OSR & CHANNEL_TWO_DATA
+
+#define SETDataComThreeHigh *AT91C_PIOA_SODR = CHANNEL_THREE_DATA
+
+#define SETDataComThreeLow *AT91C_PIOA_CODR = CHANNEL_THREE_DATA
+
+#define GetDataComThreePinLevel *AT91C_PIOA_PDSR & CHANNEL_THREE_DATA
+
+#define GETDataComThreePinDirection *AT91C_PIOA_OSR & CHANNEL_THREE_DATA
+
+#define SETDataComFourHigh *AT91C_PIOA_SODR = CHANNEL_FOUR_DATA
+
+#define SETDataComFourLow *AT91C_PIOA_CODR = CHANNEL_FOUR_DATA
+
+#define GetDataComFourPinLevel *AT91C_PIOA_PDSR & CHANNEL_FOUR_DATA
+
+#define GETDataComFourPinDirection *AT91C_PIOA_OSR & CHANNEL_FOUR_DATA
+
+#define SETDataComOneToInput *AT91C_PIOA_ODR = CHANNEL_ONE_DATA;
+
+#define SETDataComOneToOutput *AT91C_PIOA_OER = CHANNEL_ONE_DATA;
+
+#define SETDataComTwoToInput *AT91C_PIOA_ODR = CHANNEL_TWO_DATA;
+
+#define SETDataComTwoToOutput *AT91C_PIOA_OER = CHANNEL_TWO_DATA;
+
+#define SETDataComThreeToInput *AT91C_PIOA_ODR = CHANNEL_THREE_DATA;
+
+#define SETDataComThreeToOutput *AT91C_PIOA_OER = CHANNEL_THREE_DATA;
+
+#define SETDataComFourToInput *AT91C_PIOA_ODR = CHANNEL_FOUR_DATA;
+
+#define SETDataComFourToOutput *AT91C_PIOA_OER = CHANNEL_FOUR_DATA;
+
+#define DISABLEPullupDataComOne *AT91C_PIOA_PPUDR = CHANNEL_ONE_DATA;
+
+#define DISABLEPullupClkComOne *AT91C_PIOA_PPUDR = CHANNEL_ONE_CLK;
+
+#define DISABLEPullupDataComTwo *AT91C_PIOA_PPUDR = CHANNEL_TWO_DATA;
+
+#define DISABLEPullupClkComTwo *AT91C_PIOA_PPUDR = CHANNEL_TWO_CLK;
+
+#define DISABLEPullupDataComThree *AT91C_PIOA_PPUDR = CHANNEL_THREE_DATA;
+
+#define DISABLEPullupClkComThree *AT91C_PIOA_PPUDR = CHANNEL_THREE_CLK;
+
+#define DISABLEPullupDataComFour *AT91C_PIOA_PPUDR = CHANNEL_FOUR_DATA;
+
+#define DISABLEPullupClkComFour *AT91C_PIOA_PPUDR = CHANNEL_FOUR_CLK;
+
+#define ENABLEPullupDataComOne *AT91C_PIOA_PPUER = CHANNEL_ONE_DATA;
+
+#define ENABLEPullupClkComOne *AT91C_PIOA_PPUER = CHANNEL_ONE_CLK;
+
+#define ENABLEPullupDataComTwo *AT91C_PIOA_PPUER = CHANNEL_TWO_DATA;
+
+#define ENABLEPullupClkComTwo *AT91C_PIOA_PPUER = CHANNEL_TWO_CLK;
+
+#define ENABLEPullupDataComThree *AT91C_PIOA_PPUER = CHANNEL_THREE_DATA;
+
+#define ENABLEPullupClkComThree *AT91C_PIOA_PPUER = CHANNEL_THREE_CLK;
+
+#define ENABLEPullupDataComFour *AT91C_PIOA_PPUER = CHANNEL_FOUR_DATA;
+
+#define ENABLEPullupClkComFour *AT91C_PIOA_PPUER = CHANNEL_FOUR_CLK;
+
+#define SETClkLow(ChannelNr) {\
+ if (ChannelNr == 0)\
+ {\
+ SETClkComOneLow;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 1)\
+ {\
+ SETClkComTwoLow;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 2)\
+ {\
+ SETClkComThreeLow;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 3)\
+ {\
+ SETClkComFourLow;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+
+#define SETClkHigh(ChannelNr) {\
+ if (ChannelNr == 0)\
+ {\
+ SETClkComOneHigh;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 1)\
+ {\
+ SETClkComTwoHigh;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 2)\
+ {\
+ SETClkComThreeHigh;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 3)\
+ {\
+ SETClkComFourHigh;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+#define SETDataLow(ChannelNr) {\
+ if (ChannelNr == 0)\
+ {\
+ SETDataComOneLow;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 1)\
+ {\
+ SETDataComTwoLow;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 2)\
+ {\
+ SETDataComThreeLow;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 3)\
+ {\
+ SETDataComFourLow;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+#define SETDataHigh(ChannelNr) {\
+ if (ChannelNr == 0)\
+ {\
+ SETDataComOneHigh;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 1)\
+ {\
+ SETDataComTwoHigh;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 2)\
+ {\
+ SETDataComThreeHigh;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 3)\
+ {\
+ SETDataComFourHigh;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+#define SETDataToInput(ChannelNr) {\
+ if (ChannelNr == 0)\
+ {\
+ SETDataComOneToInput;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 1)\
+ {\
+ SETDataComTwoToInput;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 2)\
+ {\
+ SETDataComThreeToInput;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 3)\
+ {\
+ SETDataComFourToInput;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+
+#define SETDataToOutput(ChannelNr) {\
+ if (ChannelNr == 0)\
+ {\
+ SETDataComOneToOutput;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 1)\
+ {\
+ SETDataComTwoToOutput;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 2)\
+ {\
+ SETDataComThreeToOutput;\
+ }\
+ else\
+ {\
+ if (ChannelNr == 3)\
+ {\
+ SETDataComFourToOutput;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+
+#define ENABLEPWMTimerForLowCom {\
+ *AT91C_PWMC_ENA = AT91C_PWMC_CHID0; /* Enable PWM output channel 0 */\
+ }
+
+#define DISABLEPWMTimerForLowCom {\
+ *AT91C_PWMC_DIS = AT91C_PWMC_CHID0; /* Disable PWM output channel 0 */\
+ }
+
+#define OLD_DISABLEPWMTimerForLowCom {\
+ *AT91C_PWMC_DIS = AT91C_PWMC_CHID0; /* Disable PWM output channel 0 */\
+ *AT91C_PWMC_IDR = AT91C_PWMC_CHID0; /* Disable interrupt from PWM output channel 0 */\
+ *AT91C_AIC_IDCR = 0x400; /* Disable Irq from PID10 */\
+ *AT91C_AIC_ICCR = 0x400; /* Clear interrupt register PID10*/\
+ *AT91C_PMC_PCDR = 0x400; /* Disable clock for PWM, PID10*/\
+ }
+
+__ramfunc void LowSpeedPwmIrqHandler(void)
+{
+ ULONG TestVar;
+ ULONG PinStatus;
+ UBYTE ChannelNr;
+
+ TestVar = *AT91C_PWMC_ISR;
+ TestVar = TestVar;
+ PinStatus = *AT91C_PIOA_PDSR;
+
+ for (ChannelNr = 0; ChannelNr < NO_OF_LOWSPEED_COM_CHANNEL; ChannelNr++)
+ {
+ switch(LowSpeedData[ChannelNr].ChannelState)
+ {
+ case LOWSPEED_IDLE:
+ {
+ }
+ break;
+
+ case LOWSPEED_TX_STOP_BIT:
+ {
+ SETDataHigh(ChannelNr);
+ LowSpeedData[ChannelNr].ChannelState = LOWSPEED_IDLE; //Now we have send a STOP sequence, disable this channel
+ }
+ break;
+
+ case LOWSPEED_TRANSMITTING:
+ {
+ switch(LowSpeedData[ChannelNr].TxState)
+ {
+ case TX_DATA_MORE_DATA:
+ {
+ PinStatus |= CLK_PINS[ChannelNr];
+ LowSpeedData[ChannelNr].TxState = TX_DATA_CLK_HIGH;
+ }
+ break;
+
+ case TX_DATA_CLK_HIGH:
+ {
+ SETClkLow(ChannelNr);
+ if (LowSpeedData[ChannelNr].MaskBit == 0) //Is Byte Done, then we need a ack from receiver
+ {
+ SETDataToInput(ChannelNr); //Set datapin to input
+ LowSpeedData[ChannelNr].TxState = TX_DATA_READ_ACK_CLK_LOW;
+ }
+ else
+ {
+ if (*LowSpeedData[ChannelNr].pComOutBuffer & LowSpeedData[ChannelNr].MaskBit) //Setup data pin in relation to the data
+ {
+ SETDataHigh(ChannelNr); //Set data output high
+ }
+ else
+ {
+ SETDataLow(ChannelNr); //Set data output low
+ }
+ LowSpeedData[ChannelNr].TxState = TX_DATA_CLK_LOW;
+ }
+ }
+ break;
+
+ case TX_EVALUATE_ACK_CLK_HIGH:
+ {
+ SETClkLow(ChannelNr);
+ if (LowSpeedData[ChannelNr].AckStatus == 1)
+ {
+ LowSpeedData[ChannelNr].TxByteCnt--;
+ if (LowSpeedData[ChannelNr].TxByteCnt > 0) //Here initialise to send next byte
+ {
+ LowSpeedData[ChannelNr].MaskBit = MASK_BIT_8;
+ LowSpeedData[ChannelNr].pComOutBuffer++;
+ }
+ LowSpeedData[ChannelNr].TxState = TX_ACK_EVALUATED_CLK_LOW; //Received ack, now make a stop sequence or send next byte
+ }
+ else
+ { //Data communication error !
+ LowSpeedData[ChannelNr].TxByteCnt = 0;
+ SETClkHigh(ChannelNr);
+ LowSpeedData[ChannelNr].ChannelState = LOWSPEED_TX_STOP_BIT; //Received ack, now make a stop sequence or send next byte.
+ }
+ }
+ break;
+
+ case TX_DATA_READ_ACK_CLK_LOW:
+ {
+ if (!(PinStatus & DATA_PINS[ChannelNr]))
+ {
+ LowSpeedData[ChannelNr].AckStatus = 1; //Read ack signal from receiver
+ }
+ SETDataToOutput(ChannelNr);
+ SETDataLow(ChannelNr);
+ LowSpeedData[ChannelNr].TxState = TX_EVALUATE_ACK_CLK_HIGH;
+ SETClkHigh(ChannelNr);
+ }
+ break;
+
+ case TX_DATA_CLK_LOW:
+ {
+ LowSpeedData[ChannelNr].MaskBit = LowSpeedData[ChannelNr].MaskBit >> 1; //Get ready for the next bit which should be clk out next time
+ SETClkHigh(ChannelNr); //Clk goes high = The reciever reads the data
+ LowSpeedData[ChannelNr].TxState = TX_DATA_CLK_HIGH;
+ }
+ break;
+
+ case TX_ACK_EVALUATED_CLK_LOW:
+ {
+ if (LowSpeedData[ChannelNr].MaskBit != 0)
+ {
+ LowSpeedData[ChannelNr].TxState = TX_DATA_MORE_DATA;
+ }
+ else
+ {
+ if (LowSpeedData[ChannelNr].ReStartBit != 0)
+ {
+ LowSpeedData[ChannelNr].ChannelState = LOWSPEED_RESTART_CONDITION;
+ LowSpeedData[ChannelNr].ReStartState = RESTART_STATE_ONE;
+ SETDataLow(ChannelNr);
+ SETClkHigh(ChannelNr); //Clk goes high = The reciever reads the data
+ }
+ else
+ {
+ if (LowSpeedData[ChannelNr].RxByteCnt != 0)
+ {
+ LowSpeedData[ChannelNr].ChannelState = LOWSPEED_WAIT_BEFORE_RX;
+ }
+ else
+ {
+ LowSpeedData[ChannelNr].ChannelState = LOWSPEED_TX_STOP_BIT;
+ SETClkHigh(ChannelNr); //Clk goes high = The reciever reads the data
+ }
+ }
+ LowSpeedData[ChannelNr].TxState = TX_IDLE;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case LOWSPEED_RESTART_CONDITION:
+ {
+ switch(LowSpeedData[ChannelNr].ReStartState)
+ {
+ case RESTART_STATE_ONE:
+ {
+ LowSpeedData[ChannelNr].ReStartState = RESTART_STATE_TWO;
+ }
+ break;
+
+ case RESTART_STATE_TWO:
+ {
+ SETDataHigh(ChannelNr);
+ LowSpeedData[ChannelNr].ReStartState = RESTART_STATE_THREE;
+ }
+ break;
+
+ case RESTART_STATE_THREE:
+ {
+ SETClkLow(ChannelNr);
+ LowSpeedData[ChannelNr].ReStartState = RESTART_STATE_FOUR;
+ }
+ break;
+
+ case RESTART_STATE_FOUR:
+ {
+ SETClkHigh(ChannelNr);
+ LowSpeedData[ChannelNr].ReStartState = RESTART_STATE_FIVE;
+ }
+ break;
+
+ case RESTART_STATE_FIVE:
+ {
+ SETDataLow(ChannelNr);
+ LowSpeedData[ChannelNr].ReStartState = RESTART_STATE_SIX;
+ }
+ break;
+
+ case RESTART_STATE_SIX:
+ {
+ LowSpeedData[ChannelNr].ReStartState = RESTART_STATE_SEVEN;
+ }
+ break;
+
+ case RESTART_STATE_SEVEN:
+ {
+ SETClkLow(ChannelNr);
+ LowSpeedData[ChannelNr].ReStartState = RESTART_STATE_IDLE;
+ LowSpeedData[ChannelNr].ReStartBit = 0;
+ LowSpeedData[ChannelNr].pComOutBuffer = &LowSpeedData[ChannelNr].ComDeviceAddress;
+ *LowSpeedData[ChannelNr].pComOutBuffer += 0x01;
+ LowSpeedData[ChannelNr].ChannelState = LOWSPEED_TRANSMITTING;
+ LowSpeedData[ChannelNr].MaskBit = MASK_BIT_8;
+ LowSpeedData[ChannelNr].TxByteCnt = 0x01;
+ LowSpeedData[ChannelNr].TxState = TX_DATA_CLK_HIGH;
+ LowSpeedData[ChannelNr].AckStatus = 0;
+ }
+ break;
+ }
+ }
+ break;
+
+ case LOWSPEED_WAIT_BEFORE_RX:
+ {
+ LowSpeedData[ChannelNr].RxWaitCnt++;
+ if (LowSpeedData[ChannelNr].RxWaitCnt > 5)
+ {
+ LowSpeedData[ChannelNr].ChannelState = LOWSPEED_RECEIVING;
+ SETDataToInput(ChannelNr);
+ }
+ }
+ break;
+
+ case LOWSPEED_RECEIVING:
+ {
+ switch(LowSpeedData[ChannelNr].RxState)
+ {
+ case RX_START_BIT_CLK_HIGH:
+ {
+ SETClkLow(ChannelNr);
+ LowSpeedData[ChannelNr].RxState = RX_DATA_CLK_LOW;
+ }
+ break;
+
+ case RX_DATA_CLK_HIGH:
+ {
+ LowSpeedData[ChannelNr].RxBitCnt++;
+ if(PinStatus & DATA_PINS[ChannelNr])
+ {
+ *LowSpeedData[ChannelNr].pComInBuffer |= 0x01;
+ }
+ SETClkLow(ChannelNr);
+ if (LowSpeedData[ChannelNr].RxBitCnt < 8)
+ {
+ *LowSpeedData[ChannelNr].pComInBuffer = *LowSpeedData[ChannelNr].pComInBuffer << 1;
+ }
+ else
+ {
+ if (LowSpeedData[ChannelNr].RxByteCnt > 1)
+ {
+ SETDataToOutput(ChannelNr);
+ SETDataLow(ChannelNr);
+ }
+ }
+ LowSpeedData[ChannelNr].RxState = RX_DATA_CLK_LOW;
+ }
+ break;
+
+ case RX_ACK_TX_CLK_HIGH:
+ {
+ SETClkLow(ChannelNr);
+ SETDataToInput(ChannelNr);
+ LowSpeedData[ChannelNr].pComInBuffer++;
+ LowSpeedData[ChannelNr].RxByteCnt--;
+ LowSpeedData[ChannelNr].RxBitCnt = 0;
+ LowSpeedData[ChannelNr].RxState = RX_DONE_OR_NOT_CLK_LOW;
+ }
+ break;
+
+ case RX_DATA_CLK_LOW:
+ {
+ SETClkHigh(ChannelNr);
+ if (LowSpeedData[ChannelNr].RxBitCnt == 8)
+ {
+ LowSpeedData[ChannelNr].RxState = RX_ACK_TX_CLK_HIGH;
+ }
+ else
+ {
+ LowSpeedData[ChannelNr].RxState = RX_DATA_CLK_HIGH;
+ }
+ }
+ break;
+
+ case RX_DONE_OR_NOT_CLK_LOW:
+ {
+ if (LowSpeedData[ChannelNr].RxByteCnt == 0)
+ {
+ LowSpeedData[ChannelNr].ChannelState = LOWSPEED_IDLE;
+ LowSpeedData[ChannelNr].RxState = RX_IDLE;
+ SETClkHigh(ChannelNr);
+ }
+ else
+ {
+ LowSpeedData[ChannelNr].RxState = RX_START_BIT_CLK_HIGH;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+
+#define ENABLETxPins(ChannelNumber) {\
+ if (ChannelNumber == LOWSPEED_CHANNEL1)\
+ {\
+ *AT91C_PIOA_PER = CHANNEL_ONE_CLK | CHANNEL_ONE_DATA; /* Enable PIO on PA20 & PA28 */\
+ *AT91C_PIOA_PPUDR = CHANNEL_ONE_CLK | CHANNEL_ONE_DATA; /* Disable Pull-up resistor */\
+ *AT91C_PIOA_ODR = CHANNEL_ONE_CLK | CHANNEL_ONE_DATA; /* PA20 & PA28 set to Input */\
+ }\
+ if (ChannelNumber == LOWSPEED_CHANNEL2)\
+ {\
+ *AT91C_PIOA_PER = CHANNEL_TWO_CLK | CHANNEL_TWO_DATA; /* Enable PIO on PA20 & PA28 */\
+ *AT91C_PIOA_PPUDR = CHANNEL_TWO_CLK | CHANNEL_TWO_DATA; /* Disable Pull-up resistor */\
+ *AT91C_PIOA_ODR = CHANNEL_TWO_CLK | CHANNEL_TWO_DATA; /* PA20 & PA28 set to Input */\
+ }\
+ if (ChannelNumber == LOWSPEED_CHANNEL3)\
+ {\
+ *AT91C_PIOA_PER = CHANNEL_THREE_CLK | CHANNEL_THREE_DATA; /* */\
+ *AT91C_PIOA_PPUDR = CHANNEL_THREE_CLK | CHANNEL_THREE_DATA; /* */\
+ *AT91C_PIOA_ODR = CHANNEL_THREE_CLK | CHANNEL_THREE_DATA; /* */\
+ }\
+ if (ChannelNumber == LOWSPEED_CHANNEL4)\
+ {\
+ *AT91C_PIOA_PER = CHANNEL_FOUR_CLK | CHANNEL_FOUR_DATA; /* */\
+ *AT91C_PIOA_PPUDR = CHANNEL_FOUR_CLK | CHANNEL_FOUR_DATA; /* */\
+ *AT91C_PIOA_ODR = CHANNEL_FOUR_CLK | CHANNEL_FOUR_DATA; /* */\
+ }\
+ }
+
+#define TxData(ChannelNumber, Status, DataOutBuffer, NumberOfByte) {\
+ if (ChannelNumber == LOWSPEED_CHANNEL1)\
+ {\
+ if (GetDataComOnePinLevel && GetClkComOnePinLevel)\
+ {\
+ *AT91C_PIOA_PER = CHANNEL_ONE_CLK | CHANNEL_ONE_DATA; /* Enable PIO on PA20 & PA28 */\
+ *AT91C_PIOA_OER = CHANNEL_ONE_CLK | CHANNEL_ONE_DATA; /* PA20 & PA28 set to Output */\
+ *AT91C_PIOA_PPUDR = CHANNEL_ONE_CLK | CHANNEL_ONE_DATA; /* Disable Pull-up resistor */\
+ SETClkComOneHigh;\
+ LowSpeedData[LOWSPEED_CHANNEL1].pComOutBuffer = DataOutBuffer;\
+ LowSpeedData[LOWSPEED_CHANNEL1].ComDeviceAddress = *LowSpeedData[LOWSPEED_CHANNEL1].pComOutBuffer;\
+ LowSpeedData[LOWSPEED_CHANNEL1].MaskBit = MASK_BIT_8;\
+ LowSpeedData[LOWSPEED_CHANNEL1].TxByteCnt = NumberOfByte;\
+ LowSpeedData[LOWSPEED_CHANNEL1].ChannelState = LOWSPEED_TRANSMITTING;\
+ LowSpeedData[LOWSPEED_CHANNEL1].TxState = TX_DATA_CLK_HIGH;\
+ SETDataComOneLow;\
+ LowSpeedData[LOWSPEED_CHANNEL1].AckStatus = 0;\
+ Status = 1;\
+ }\
+ else\
+ {\
+ Status = 0;\
+ }\
+ }\
+ if (ChannelNumber == LOWSPEED_CHANNEL2)\
+ {\
+ if (GetDataComTwoPinLevel && GetClkComTwoPinLevel)\
+ {\
+ *AT91C_PIOA_PER = CHANNEL_TWO_CLK | CHANNEL_TWO_DATA; /* Enable PIO on PA20 & PA28 */\
+ *AT91C_PIOA_OER = CHANNEL_TWO_CLK | CHANNEL_TWO_DATA; /* PA20 & PA28 set to Output */\
+ *AT91C_PIOA_PPUDR = CHANNEL_TWO_CLK | CHANNEL_TWO_DATA; /* Disable Pull-up resistor */\
+ SETClkComTwoHigh;\
+ LowSpeedData[LOWSPEED_CHANNEL2].pComOutBuffer = DataOutBuffer;\
+ LowSpeedData[LOWSPEED_CHANNEL2].ComDeviceAddress = *LowSpeedData[LOWSPEED_CHANNEL2].pComOutBuffer;\
+ LowSpeedData[LOWSPEED_CHANNEL2].MaskBit = MASK_BIT_8;\
+ LowSpeedData[LOWSPEED_CHANNEL2].TxByteCnt = NumberOfByte;\
+ LowSpeedData[LOWSPEED_CHANNEL2].ChannelState = LOWSPEED_TRANSMITTING;\
+ LowSpeedData[LOWSPEED_CHANNEL2].TxState = TX_DATA_CLK_HIGH;\
+ SETDataComTwoLow;\
+ LowSpeedData[LOWSPEED_CHANNEL2].AckStatus = 0;\
+ Status = 1;\
+ }\
+ else\
+ {\
+ Status = 0;\
+ }\
+ }\
+ if (ChannelNumber == LOWSPEED_CHANNEL3)\
+ {\
+ if (GetDataComThreePinLevel && GetClkComThreePinLevel)\
+ {\
+ *AT91C_PIOA_PER = CHANNEL_THREE_CLK | CHANNEL_THREE_DATA; /* */\
+ *AT91C_PIOA_OER = CHANNEL_THREE_CLK | CHANNEL_THREE_DATA; /* */\
+ *AT91C_PIOA_PPUDR = CHANNEL_THREE_CLK | CHANNEL_THREE_DATA; /* */\
+ SETClkComThreeHigh;\
+ LowSpeedData[LOWSPEED_CHANNEL3].pComOutBuffer = DataOutBuffer;\
+ LowSpeedData[LOWSPEED_CHANNEL3].ComDeviceAddress = *LowSpeedData[LOWSPEED_CHANNEL3].pComOutBuffer;\
+ LowSpeedData[LOWSPEED_CHANNEL3].MaskBit = MASK_BIT_8;\
+ LowSpeedData[LOWSPEED_CHANNEL3].TxByteCnt = NumberOfByte;\
+ LowSpeedData[LOWSPEED_CHANNEL3].ChannelState = LOWSPEED_TRANSMITTING;\
+ LowSpeedData[LOWSPEED_CHANNEL3].TxState = TX_DATA_CLK_HIGH;\
+ SETDataComThreeLow;\
+ LowSpeedData[LOWSPEED_CHANNEL3].AckStatus = 0;\
+ Status = 1;\
+ }\
+ else\
+ {\
+ Status = 0;\
+ }\
+ }\
+ if (ChannelNumber == LOWSPEED_CHANNEL4)\
+ {\
+ if (GetDataComFourPinLevel && GetClkComFourPinLevel)\
+ {\
+ *AT91C_PIOA_PER = CHANNEL_FOUR_CLK | CHANNEL_FOUR_DATA; /* */\
+ *AT91C_PIOA_OER = CHANNEL_FOUR_CLK | CHANNEL_FOUR_DATA; /* */\
+ *AT91C_PIOA_PPUDR = CHANNEL_FOUR_CLK | CHANNEL_FOUR_DATA; /* */\
+ SETClkComFourHigh;\
+ LowSpeedData[LOWSPEED_CHANNEL4].pComOutBuffer = DataOutBuffer;\
+ LowSpeedData[LOWSPEED_CHANNEL4].ComDeviceAddress = *LowSpeedData[LOWSPEED_CHANNEL4].pComOutBuffer;\
+ LowSpeedData[LOWSPEED_CHANNEL4].MaskBit = MASK_BIT_8;\
+ LowSpeedData[LOWSPEED_CHANNEL4].TxByteCnt = NumberOfByte;\
+ LowSpeedData[LOWSPEED_CHANNEL4].ChannelState = LOWSPEED_TRANSMITTING;\
+ LowSpeedData[LOWSPEED_CHANNEL4].TxState = TX_DATA_CLK_HIGH;\
+ SETDataComFourLow;\
+ LowSpeedData[LOWSPEED_CHANNEL4].AckStatus = 0;\
+ Status = 1;\
+ }\
+ else\
+ {\
+ Status = 0;\
+ }\
+ }\
+ }
+
+#define RxData(ChannelNumber, DataInBuffer, RxBytes) {\
+ LowSpeedData[ChannelNumber].pComInBuffer = DataInBuffer;\
+ LowSpeedData[ChannelNumber].RxBitCnt = 0;\
+ LowSpeedData[ChannelNumber].RxByteCnt = RxBytes;\
+ LowSpeedData[ChannelNumber].RxState = RX_DATA_CLK_LOW;\
+ LowSpeedData[ChannelNumber].ReStartBit = 1;\
+ LowSpeedData[ChannelNumber].RxWaitCnt = 0;\
+ }
+
+
+#define STATUSTxCom(ChannelNumber, Status) {\
+ if (LowSpeedData[ChannelNumber].ChannelState != 0)\
+ {\
+ if (LowSpeedData[ChannelNumber].TxByteCnt == 0)\
+ {\
+ if (LowSpeedData[ChannelNumber].MaskBit == 0)\
+ {\
+ if (LowSpeedData[ChannelNumber].AckStatus == 1)\
+ {\
+ Status = 0x01; /* TX SUCCESS */\
+ }\
+ else\
+ {\
+ Status = 0xFF; /* TX ERROR */\
+ }\
+ }\
+ else\
+ {\
+ Status = 0;\
+ }\
+ }\
+ else\
+ {\
+ Status = 0;\
+ }\
+ }\
+ else\
+ {\
+ if (LowSpeedData[ChannelNumber].RxByteCnt == 0)\
+ {\
+ if (LowSpeedData[ChannelNumber].AckStatus == 1)\
+ {\
+ Status = 0x01; /* TX SUCCESS */\
+ }\
+ else\
+ {\
+ Status = 0xFF; /* TX ERROR */\
+ }\
+ }\
+ else\
+ {\
+ Status = 0xFF; /* TX ERROR */\
+ }\
+ }\
+ }
+
+#define STATUSRxCom(ChannelNumber, Status) {\
+ if (LowSpeedData[ChannelNumber].ChannelState == LOWSPEED_IDLE)\
+ {\
+ if (LowSpeedData[ChannelNumber].RxByteCnt == 0)\
+ {\
+ Status = 0x01; /* RX SUCCESS */\
+ }\
+ else\
+ {\
+ Status = 0xFF; /* RX ERROR */\
+ }\
+ }\
+ else\
+ {\
+ Status = 0;\
+ }\
+ }
+
+
+#endif
+
+#ifdef PCWIN
+
+#endif
diff --git a/AT91SAM7S256/Source/d_output.c b/AT91SAM7S256/Source/d_output.c
new file mode 100644
index 0000000..e542cf6
--- /dev/null
+++ b/AT91SAM7S256/Source/d_output.c
@@ -0,0 +1,1605 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 5-02-07 13:48 $
+//
+// Filename $Workfile:: d_output.c $
+//
+// Version $Revision:: 118 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_output.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "m_sched.h"
+#include "d_output.h"
+#include "d_output.r"
+
+#define MAXIMUM_SPEED_FW 100
+#define MAXIMUM_SPEED_RW -100
+
+#define INPUT_SCALE_FACTOR 100
+
+#define MAX_COUNT_TO_RUN 10000000
+
+#define REG_MAX_VALUE 100
+#define REG_MIN_VALUE -100
+
+#define RAMP_TIME_INTERVAL 25 // Measured in 1 mS => 25 mS interval
+#define REGULATION_TIME 100 // Measured in 1 mS => 100 mS regulation interval
+
+#define RAMPDOWN_STATE_RAMPDOWN 0
+#define RAMPDOWN_STATE_CONTINIUE 1
+
+#define COAST_MOTOR_MODE 0
+
+void dOutputRampDownSynch(UBYTE MotorNr);
+
+typedef struct
+{
+ SBYTE MotorSetSpeed; // Motor setpoint in speed
+ SBYTE MotorTargetSpeed; // Speed order for the movement
+ SBYTE MotorActualSpeed; // Actual speed for motor (Calculated within the PID regulation)
+ SBYTE TurnParameter; // Tell the turning parameter used
+ UBYTE RegPParameter; // Current P parameter used within the regulation
+ UBYTE RegIParameter; // Current I parameter used within the regulation
+ UBYTE RegDParameter; // Current D parameter used within the regulation
+ UBYTE RegulationTimeCount; // Time counter used to evaluate when the regulation should run again (100 mS)
+ UBYTE MotorRunState; // Hold current motor state (Ramp-up, Running, Ramp-Down, Idle)
+ UBYTE RegulationMode; // Hold current regulation mode (Position control, Synchronization mode)
+ UBYTE MotorOverloaded; // Set if the motor speed in regulation is calculated to be above maximum
+ UBYTE MotorRunForever; // Tell that the motor is set to run forever
+ UWORD MotorRampDownCount; // Counter to tell if the ramp-down can reach it gaol and therefor need some additional help
+ SWORD MotorRampDownIncrement; // Tell the number of count between each speed adjustment during Ramp-Down
+ UWORD MotorRampUpCount; // Used to speedup Ramp-Up if position regulation is not enabled
+ SWORD MotorRampUpIncrement; // Tell the number of count between each speed adjustment during Ramp-up
+ SWORD AccError; // Accumulated Error, used within the integrator of the PID regulation
+ SWORD OldPositionError; // Used within position regulation
+ SLONG DeltaCaptureCount; // Counts within last regulation time-periode
+ SLONG CurrentCaptureCount; // Total counts since motor counts has been reset
+ SLONG MotorTachoCountToRun; // Holds number of counts to run. 0 = Run forever
+ SLONG MotorBlockTachoCount; // Hold CaptureCount for current movement
+ SLONG MotorRampTachoCountOld; // Used to hold old position during Ramp-Up
+ SLONG MotorRampTachoCountStart; // Used to hold position when Ramp-up started
+ SLONG RotationCaptureCount; // Counter for additional rotation counter
+}MOTORDATA;
+
+typedef struct
+{
+ SLONG SyncTachoDif;
+ SLONG SyncTurnParameter;
+ SWORD SyncOldError;
+ SWORD SyncAccError;
+}SYNCMOTORDATA;
+
+static MOTORDATA MotorData[3];
+static SYNCMOTORDATA SyncData;
+
+void dOutputInit(void)
+{
+ UBYTE Temp;
+
+ OUTPUTInit;
+ ENABLECaptureMotorA;
+ ENABLECaptureMotorB;
+ ENABLECaptureMotorC;
+
+ for (Temp = 0; Temp < 3; Temp++)
+ {
+ MotorData[Temp].MotorSetSpeed = 0;
+ MotorData[Temp].MotorTargetSpeed = 0;
+ MotorData[Temp].MotorActualSpeed = 0;
+ MotorData[Temp].MotorRampUpCount = 0;
+ MotorData[Temp].MotorRampDownCount = 0;
+ MotorData[Temp].MotorRunState = 0;
+ MotorData[Temp].MotorTachoCountToRun = 0;
+ MotorData[Temp].MotorRunForever = 1;
+ MotorData[Temp].AccError = 0;
+ MotorData[Temp].RegulationTimeCount = 0;
+ MotorData[Temp].RegPParameter = DEFAULT_P_GAIN_FACTOR;
+ MotorData[Temp].RegIParameter = DEFAULT_I_GAIN_FACTOR;
+ MotorData[Temp].RegDParameter = DEFAULT_D_GAIN_FACTOR;
+ MotorData[Temp].RegulationMode = 0;
+ MotorData[Temp].MotorOverloaded = 0;
+ INSERTMode(Temp, COAST_MOTOR_MODE);
+ INSERTSpeed(Temp, MotorData[Temp].MotorSetSpeed);
+ }
+}
+
+/* This function is called every 1 mS and will go through all the motors and there dependencies */
+/* Actual motor speed is only passed (updated) to the AVR controller form this function */
+/* DeltacaptureCount used to count number of Tachocount within last 100 mS. Used with position control regulation */
+/* CurrentCaptureCount used to tell total current position. Used to tell when movement has been obtained */
+/* MotorBlockTachoCount tell current position within current movement. Reset when a new block is started from the VM */
+/* RotationCaptureCount is additional counter for the rotationsensor. Uses it own value so it does conflict with other CaptureCount */
+void dOutputCtrl(void)
+{
+ UBYTE MotorNr;
+ SLONG NewTachoCount[3];
+
+ TACHOCaptureReadResetAll(NewTachoCount[MOTOR_A], NewTachoCount[MOTOR_B], NewTachoCount[MOTOR_C]);
+
+ for (MotorNr = 0; MotorNr < 3; MotorNr++)
+ {
+ MotorData[MotorNr].DeltaCaptureCount += NewTachoCount[MotorNr];
+ MotorData[MotorNr].CurrentCaptureCount += NewTachoCount[MotorNr];
+ MotorData[MotorNr].MotorBlockTachoCount += NewTachoCount[MotorNr];
+ MotorData[MotorNr].RotationCaptureCount += NewTachoCount[MotorNr];
+ MotorData[MotorNr].RegulationTimeCount++;
+
+ if (MotorData[MotorNr].MotorRunState == MOTOR_RUN_STATE_RAMPUP)
+ {
+ dOutputRampUpFunction(MotorNr);
+ }
+ if (MotorData[MotorNr].MotorRunState == MOTOR_RUN_STATE_RAMPDOWN)
+ {
+ dOutputRampDownFunction(MotorNr);
+ }
+ if (MotorData[MotorNr].MotorRunState == MOTOR_RUN_STATE_RUNNING)
+ {
+ dOutputTachoLimitControl(MotorNr);
+ }
+ if (MotorData[MotorNr].MotorRunState == MOTOR_RUN_STATE_IDLE)
+ {
+ dOutputMotorIdleControl(MotorNr);
+ }
+ if (MotorData[MotorNr].MotorRunState == MOTOR_RUN_STATE_HOLD)
+ {
+ MotorData[MotorNr].MotorSetSpeed = 0;
+ MotorData[MotorNr].MotorActualSpeed = 0;
+ MotorData[MotorNr].MotorTargetSpeed = 0;
+ MotorData[MotorNr].RegulationTimeCount = 0;
+ MotorData[MotorNr].DeltaCaptureCount = 0;
+ MotorData[MotorNr].MotorRunState = MOTOR_RUN_STATE_RUNNING;
+
+ }
+ if (MotorData[MotorNr].RegulationTimeCount > REGULATION_TIME)
+ {
+ MotorData[MotorNr].RegulationTimeCount = 0;
+ dOutputRegulateMotor(MotorNr);
+ MotorData[MotorNr].DeltaCaptureCount = 0;
+ }
+ }
+ INSERTSpeed(MOTOR_A, MotorData[MOTOR_A].MotorActualSpeed);
+ INSERTSpeed(MOTOR_B, MotorData[MOTOR_B].MotorActualSpeed);
+ INSERTSpeed(MOTOR_C, MotorData[MOTOR_C].MotorActualSpeed);
+}
+
+void dOutputExit(void)
+{
+ OUTPUTExit;
+}
+
+/* Called eveyr 1 mS */
+/* Data mapping for controller (IO-Map is updated with these values) */
+void dOutputGetMotorParameters(UBYTE *CurrentMotorSpeed, SLONG *TachoCount, SLONG *BlockTachoCount, UBYTE *RunState, UBYTE *MotorOverloaded, SLONG *RotationCount)
+{
+ UBYTE Tmp;
+
+ for (Tmp = 0; Tmp < 3; Tmp++)
+ {
+ CurrentMotorSpeed[Tmp] = MotorData[Tmp].MotorActualSpeed;
+ TachoCount[Tmp] = MotorData[Tmp].CurrentCaptureCount;
+ BlockTachoCount[Tmp] = MotorData[Tmp].MotorBlockTachoCount;
+ RotationCount[Tmp] = MotorData[Tmp].RotationCaptureCount;
+ RunState[Tmp] = MotorData[Tmp].MotorRunState;
+ MotorOverloaded[Tmp] = MotorData[Tmp].MotorOverloaded;
+ }
+}
+
+void dOutputSetMode(UBYTE Motor, UBYTE Mode) //Set motor mode (break, Float)
+{
+ INSERTMode(Motor, Mode);
+}
+
+/* Update the regulation state for the motor */
+/* Need to reset regulation parameter depending on current status of the motor */
+/* AccError & OldPositionError used for position regulation and Sync Parameter are used for synchronization regulation */
+void dOutputEnableRegulation(UBYTE MotorNr, UBYTE RegulationMode)
+{
+ MotorData[MotorNr].RegulationMode = RegulationMode;
+
+ if ((MotorData[MotorNr].RegulationMode & REGSTATE_REGULATED) && (MotorData[MotorNr].MotorSetSpeed == 0) && (MotorData[MotorNr].MotorRunState != MOTOR_RUN_STATE_RAMPDOWN))
+ {
+ MotorData[MotorNr].AccError = 0;
+ MotorData[MotorNr].OldPositionError = 0;
+ }
+
+ if (MotorData[MotorNr].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ if (((MotorData[MotorNr].MotorActualSpeed == 0) || (MotorData[MotorNr].TurnParameter != 0) || (MotorData[MotorNr].TurnParameter == 0)) && (MotorData[MotorNr].MotorRunState != MOTOR_RUN_STATE_RAMPDOWN))
+ {
+ SyncData.SyncTachoDif = 0;
+
+ SyncData.SyncAccError = 0;
+ SyncData.SyncOldError = 0;
+ SyncData.SyncTurnParameter = 0;
+ }
+ }
+}
+
+/* Disable current regulation if enabled */
+void dOutputDisableRegulation(UBYTE MotorNr)
+{
+ MotorData[MotorNr].RegulationMode = REGSTATE_IDLE;
+}
+
+/* Calling this function with reset count which tell current position and which is used to tell if the wanted position is obtained */
+/* Calling this function will reset current movement of the motor if it is running */
+void dOutputResetTachoLimit(UBYTE MotorNr)
+{
+ MotorData[MotorNr].CurrentCaptureCount = 0;
+ MotorData[MotorNr].MotorTachoCountToRun = 0;
+
+ if (MotorData[MotorNr].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ dOutputResetSyncMotors(MotorNr);
+ }
+
+ if (MotorData[MotorNr].MotorRunForever == 1)
+ {
+ MotorData[MotorNr].MotorRunForever = 0; // To ensure that we get the same functionality for all combination on motor durations
+ }
+}
+
+/* MotorBlockTachoCount tells current position in current movement. */
+/* Used within the synchronization to compare current motor position. Reset on every new movement from the VM */
+void dOutputResetBlockTachoLimit(UBYTE MotorNr)
+{
+ MotorData[MotorNr].MotorBlockTachoCount = 0;
+}
+
+/* Additional counter add to help the VM application keep track of number of rotation for the rotation sensor */
+/* This values can be reset independtly from the other tacho count values used with regulation and position control */
+void dOutputResetRotationCaptureCount(UBYTE MotorNr)
+{
+ MotorData[MotorNr].RotationCaptureCount = 0;
+}
+
+/* Can be used to set new PID values */
+void dOutputSetPIDParameters(UBYTE Motor, UBYTE NewRegPParameter, UBYTE NewRegIParameter, UBYTE NewRegDParameter)
+{
+ MotorData[Motor].RegPParameter = NewRegPParameter;
+ MotorData[Motor].RegIParameter = NewRegIParameter;
+ MotorData[Motor].RegDParameter = NewRegDParameter;
+}
+
+/* Called to set TachoCountToRun which is used for position control for the model */
+/* Must be called before motor start */
+/* TachoCountToRun is calculated as a signed value */
+void dOutputSetTachoLimit(UBYTE MotorNr, ULONG BlockTachoCntToTravel)
+{
+ if (BlockTachoCntToTravel == 0)
+ {
+ MotorData[MotorNr].MotorRunForever = 1;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorRunForever = 0;
+
+ if (MotorData[MotorNr].MotorSetSpeed == 0)
+ {
+ if (MotorData[MotorNr].MotorTargetSpeed > 0)
+ {
+ MotorData[MotorNr].MotorTachoCountToRun += BlockTachoCntToTravel;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorTachoCountToRun -= BlockTachoCntToTravel;
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].MotorSetSpeed > 0)
+ {
+ MotorData[MotorNr].MotorTachoCountToRun += BlockTachoCntToTravel;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorTachoCountToRun -= BlockTachoCntToTravel;
+ }
+ }
+ }
+}
+
+/* This function is used for setting up the motor mode and motor speed */
+void dOutputSetSpeed (UBYTE MotorNr, UBYTE NewMotorRunState, SBYTE Speed, SBYTE NewTurnParameter)
+{
+ if ((MotorData[MotorNr].MotorSetSpeed != Speed) || (MotorData[MotorNr].MotorRunState != NewMotorRunState) || (NewMotorRunState == MOTOR_RUN_STATE_IDLE) || (MotorData[MotorNr].TurnParameter != NewTurnParameter))
+ {
+ if (MotorData[MotorNr].MotorTargetSpeed == 0)
+ {
+ MotorData[MotorNr].AccError = 0;
+ MotorData[MotorNr].OldPositionError = 0;
+ MotorData[MotorNr].RegulationTimeCount = 0;
+ MotorData[MotorNr].DeltaCaptureCount = 0;
+ TACHOCountReset(MotorNr);
+ }
+ switch (NewMotorRunState)
+ {
+ case MOTOR_RUN_STATE_IDLE:
+ {
+ //MotorData[MotorNr].MotorSetSpeed = 0;
+ //MotorData[MotorNr].MotorTargetSpeed = 0;
+ //MotorData[MotorNr].TurnParameter = 0;
+ MotorData[MotorNr].RegulationMode = REGSTATE_IDLE;
+ }
+ break;
+
+ case MOTOR_RUN_STATE_RAMPUP:
+ {
+ if (MotorData[MotorNr].MotorSetSpeed == 0)
+ {
+ MotorData[MotorNr].MotorSetSpeed = Speed;
+ MotorData[MotorNr].TurnParameter = NewTurnParameter;
+ MotorData[MotorNr].MotorRampUpIncrement = 0;
+ MotorData[MotorNr].MotorRampTachoCountStart = MotorData[MotorNr].CurrentCaptureCount;
+ MotorData[MotorNr].MotorRampUpCount = 0;
+ }
+ else
+ {
+ if (Speed > 0)
+ {
+ if (MotorData[MotorNr].MotorSetSpeed >= Speed)
+ {
+ NewMotorRunState = MOTOR_RUN_STATE_RUNNING;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorSetSpeed = Speed;
+ MotorData[MotorNr].TurnParameter = NewTurnParameter;
+ MotorData[MotorNr].MotorRampUpIncrement = 0;
+ MotorData[MotorNr].MotorRampTachoCountStart = MotorData[MotorNr].CurrentCaptureCount;
+ MotorData[MotorNr].MotorRampUpCount = 0;
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].MotorSetSpeed <= Speed)
+ {
+ NewMotorRunState = MOTOR_RUN_STATE_RUNNING;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorSetSpeed = Speed;
+ MotorData[MotorNr].TurnParameter = NewTurnParameter;
+ MotorData[MotorNr].MotorRampUpIncrement = 0;
+ MotorData[MotorNr].MotorRampTachoCountStart = MotorData[MotorNr].CurrentCaptureCount;
+ MotorData[MotorNr].MotorRampUpCount = 0;
+ }
+ }
+ }
+ }
+ break;
+
+ case MOTOR_RUN_STATE_RUNNING:
+ {
+ MotorData[MotorNr].MotorSetSpeed = Speed;
+ MotorData[MotorNr].MotorTargetSpeed = Speed;
+ MotorData[MotorNr].TurnParameter = NewTurnParameter;
+
+ if (MotorData[MotorNr].MotorSetSpeed == 0)
+ {
+ NewMotorRunState = MOTOR_RUN_STATE_HOLD;
+ }
+ }
+ break;
+
+ case MOTOR_RUN_STATE_RAMPDOWN:
+ {
+ if (MotorData[MotorNr].MotorTargetSpeed >= 0)
+ {
+ if (MotorData[MotorNr].MotorSetSpeed <= Speed)
+ {
+ NewMotorRunState = MOTOR_RUN_STATE_RUNNING;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorSetSpeed = Speed;
+ MotorData[MotorNr].TurnParameter = NewTurnParameter;
+ MotorData[MotorNr].MotorRampDownIncrement = 0;
+ MotorData[MotorNr].MotorRampTachoCountStart = MotorData[MotorNr].CurrentCaptureCount;
+ MotorData[MotorNr].MotorRampDownCount = 0;
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].MotorSetSpeed >= Speed)
+ {
+ NewMotorRunState = MOTOR_RUN_STATE_RUNNING;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorSetSpeed = Speed;
+ MotorData[MotorNr].TurnParameter = NewTurnParameter;
+ MotorData[MotorNr].MotorRampDownIncrement = 0;
+ MotorData[MotorNr].MotorRampTachoCountStart = MotorData[MotorNr].CurrentCaptureCount;
+ MotorData[MotorNr].MotorRampDownCount = 0;
+ }
+ }
+ }
+ break;
+ }
+ MotorData[MotorNr].MotorRunState = NewMotorRunState;
+ MotorData[MotorNr].MotorOverloaded = 0;
+ }
+}
+
+/* Function used for controlling the Ramp-up periode */
+/* Ramp-up is done with 1 increment in speed every X number of TachoCount, where X depend on duration of the periode and the wanted speed */
+void dOutputRampUpFunction(UBYTE MotorNr)
+{
+ if (MotorData[MotorNr].MotorTargetSpeed == 0)
+ {
+ if (MotorData[MotorNr].MotorSetSpeed > 0)
+ {
+ MotorData[MotorNr].MotorTargetSpeed = MIN_MOVEMENT_POWER;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorTargetSpeed = -MIN_MOVEMENT_POWER;
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].MotorRampUpIncrement == 0)
+ {
+ if (MotorData[MotorNr].MotorSetSpeed > 0)
+ {
+ MotorData[MotorNr].MotorRampUpIncrement = (SWORD)((MotorData[MotorNr].MotorTachoCountToRun - MotorData[MotorNr].MotorRampTachoCountStart) / (MotorData[MotorNr].MotorSetSpeed - MotorData[MotorNr].MotorTargetSpeed));
+ }
+ else
+ {
+ MotorData[MotorNr].MotorRampUpIncrement = (SWORD)(-((MotorData[MotorNr].MotorTachoCountToRun - MotorData[MotorNr].MotorRampTachoCountStart) / (MotorData[MotorNr].MotorSetSpeed - MotorData[MotorNr].MotorTargetSpeed)));
+ }
+ MotorData[MotorNr].MotorRampTachoCountOld = MotorData[MotorNr].CurrentCaptureCount;
+ }
+ if (MotorData[MotorNr].MotorSetSpeed > 0)
+ {
+ if (MotorData[MotorNr].CurrentCaptureCount > (MotorData[MotorNr].MotorRampTachoCountOld + MotorData[MotorNr].MotorRampUpIncrement))
+ {
+ MotorData[MotorNr].MotorTargetSpeed += 1;
+ MotorData[MotorNr].MotorRampTachoCountOld = MotorData[MotorNr].CurrentCaptureCount;
+ MotorData[MotorNr].MotorRampUpCount = 0;
+ }
+ else
+ {
+ if (!(MotorData[MotorNr].RegulationMode & REGSTATE_REGULATED))
+ {
+ MotorData[MotorNr].MotorRampUpCount++;
+ if (MotorData[MotorNr].MotorRampUpCount > 100)
+ {
+ MotorData[MotorNr].MotorRampUpCount = 0;
+ MotorData[MotorNr].MotorTargetSpeed++;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].CurrentCaptureCount < (MotorData[MotorNr].MotorRampTachoCountOld + MotorData[MotorNr].MotorRampUpIncrement))
+ {
+ MotorData[MotorNr].MotorTargetSpeed -= 1;
+ MotorData[MotorNr].MotorRampTachoCountOld = MotorData[MotorNr].CurrentCaptureCount;
+ MotorData[MotorNr].MotorRampUpCount = 0;
+ }
+ else
+ {
+ if (!(MotorData[MotorNr].RegulationMode & REGSTATE_REGULATED))
+ {
+ MotorData[MotorNr].MotorRampUpCount++;
+ if (MotorData[MotorNr].MotorRampUpCount > 100)
+ {
+ MotorData[MotorNr].MotorRampUpCount = 0;
+ MotorData[MotorNr].MotorTargetSpeed--;
+ }
+ }
+ }
+ }
+ }
+ if (MotorData[MotorNr].MotorSetSpeed > 0)
+ {
+ if ((MotorData[MotorNr].CurrentCaptureCount - MotorData[MotorNr].MotorRampTachoCountStart) >= (MotorData[MotorNr].MotorTachoCountToRun - MotorData[MotorNr].MotorRampTachoCountStart))
+ {
+ MotorData[MotorNr].MotorTargetSpeed = MotorData[MotorNr].MotorSetSpeed;
+ MotorData[MotorNr].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ }
+ }
+ else
+ {
+ if ((MotorData[MotorNr].CurrentCaptureCount + MotorData[MotorNr].MotorRampTachoCountStart) <= (MotorData[MotorNr].MotorTachoCountToRun + MotorData[MotorNr].MotorRampTachoCountStart))
+ {
+ MotorData[MotorNr].MotorTargetSpeed = MotorData[MotorNr].MotorSetSpeed;
+ MotorData[MotorNr].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ }
+ }
+ if (MotorData[MotorNr].MotorSetSpeed > 0)
+ {
+ if (MotorData[MotorNr].MotorTargetSpeed > MotorData[MotorNr].MotorSetSpeed)
+ {
+ MotorData[MotorNr].MotorTargetSpeed = MotorData[MotorNr].MotorSetSpeed;
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].MotorTargetSpeed < MotorData[MotorNr].MotorSetSpeed)
+ {
+ MotorData[MotorNr].MotorTargetSpeed = MotorData[MotorNr].MotorSetSpeed;
+ }
+ }
+ if (MotorData[MotorNr].RegulationMode == REGSTATE_IDLE)
+ {
+ MotorData[MotorNr].MotorActualSpeed = MotorData[MotorNr].MotorTargetSpeed;
+ }
+}
+
+/* Function used for controlling the Ramp-down periode */
+/* Ramp-down is done with 1 decrement in speed every X number of TachoCount, where X depend on duration of the periode and the wanted speed */
+void dOutputRampDownFunction(UBYTE MotorNr)
+{
+ if (MotorData[MotorNr].MotorRampDownIncrement == 0)
+ {
+ if (MotorData[MotorNr].MotorTargetSpeed > 0)
+ {
+ if ((MotorData[MotorNr].MotorTargetSpeed > MIN_MOVEMENT_POWER) && (MotorData[MotorNr].MotorSetSpeed == 0))
+ {
+ MotorData[MotorNr].MotorRampDownIncrement = ((MotorData[MotorNr].MotorTachoCountToRun - MotorData[MotorNr].CurrentCaptureCount) / ((MotorData[MotorNr].MotorTargetSpeed - MotorData[MotorNr].MotorSetSpeed) - MIN_MOVEMENT_POWER));
+ }
+ else
+ {
+ MotorData[MotorNr].MotorRampDownIncrement = ((MotorData[MotorNr].MotorTachoCountToRun - MotorData[MotorNr].CurrentCaptureCount) / (MotorData[MotorNr].MotorTargetSpeed - MotorData[MotorNr].MotorSetSpeed));
+ }
+ }
+ else
+ {
+ if ((MotorData[MotorNr].MotorTargetSpeed < -MIN_MOVEMENT_POWER) && (MotorData[MotorNr].MotorSetSpeed == 0))
+ {
+ MotorData[MotorNr].MotorRampDownIncrement = (-((MotorData[MotorNr].MotorTachoCountToRun - MotorData[MotorNr].CurrentCaptureCount) / ((MotorData[MotorNr].MotorTargetSpeed - MotorData[MotorNr].MotorSetSpeed) + MIN_MOVEMENT_POWER)));
+ }
+ else
+ {
+ MotorData[MotorNr].MotorRampDownIncrement = (-((MotorData[MotorNr].MotorTachoCountToRun - MotorData[MotorNr].CurrentCaptureCount) / (MotorData[MotorNr].MotorTargetSpeed - MotorData[MotorNr].MotorSetSpeed)));
+ }
+ }
+ MotorData[MotorNr].MotorRampTachoCountOld = MotorData[MotorNr].CurrentCaptureCount;
+ }
+ if (MotorData[MotorNr].MotorTargetSpeed > 0)
+ {
+ if (MotorData[MotorNr].CurrentCaptureCount > (MotorData[MotorNr].MotorRampTachoCountOld + (SLONG)MotorData[MotorNr].MotorRampDownIncrement))
+ {
+ MotorData[MotorNr].MotorTargetSpeed--;
+ if (MotorData[MotorNr].MotorTargetSpeed < MIN_MOVEMENT_POWER)
+ {
+ MotorData[MotorNr].MotorTargetSpeed = MIN_MOVEMENT_POWER;
+ }
+ MotorData[MotorNr].MotorRampTachoCountOld = MotorData[MotorNr].CurrentCaptureCount;
+ MotorData[MotorNr].MotorRampDownCount = 0;
+ dOutputRampDownSynch(MotorNr);
+ }
+ else
+ {
+ if (!(MotorData[MotorNr].RegulationMode & REGSTATE_REGULATED))
+ {
+ MotorData[MotorNr].MotorRampDownCount++;
+ if (MotorData[MotorNr].MotorRampDownCount > (UWORD)(30 * MotorData[MotorNr].MotorRampDownIncrement))
+ {
+ MotorData[MotorNr].MotorRampDownCount = (UWORD)(20 * MotorData[MotorNr].MotorRampDownIncrement);
+ MotorData[MotorNr].MotorTargetSpeed++;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].CurrentCaptureCount < (MotorData[MotorNr].MotorRampTachoCountOld + (SLONG)MotorData[MotorNr].MotorRampDownIncrement))
+ {
+ MotorData[MotorNr].MotorTargetSpeed++;
+ if (MotorData[MotorNr].MotorTargetSpeed > -MIN_MOVEMENT_POWER)
+ {
+ MotorData[MotorNr].MotorTargetSpeed = -MIN_MOVEMENT_POWER;
+ }
+ MotorData[MotorNr].MotorRampTachoCountOld = MotorData[MotorNr].CurrentCaptureCount;
+ MotorData[MotorNr].MotorRampDownCount = 0;
+ dOutputRampDownSynch(MotorNr);
+ }
+ else
+ {
+ if (!(MotorData[MotorNr].RegulationMode & REGSTATE_REGULATED))
+ {
+ MotorData[MotorNr].MotorRampDownCount++;
+ if (MotorData[MotorNr].MotorRampDownCount > (UWORD)(30 * (-MotorData[MotorNr].MotorRampDownIncrement)))
+ {
+ MotorData[MotorNr].MotorRampDownCount = (UWORD)(20 * (-MotorData[MotorNr].MotorRampDownIncrement));
+ MotorData[MotorNr].MotorTargetSpeed--;
+ }
+ }
+ }
+ }
+ if ((MotorData[MotorNr].RegulationMode & REGSTATE_SYNCHRONE) && (MotorData[MotorNr].TurnParameter != 0))
+ {
+ dOutputSyncTachoLimitControl(MotorNr);
+ if (MotorData[MotorNr].MotorRunState == MOTOR_RUN_STATE_IDLE)
+ {
+ dOutputMotorReachedTachoLimit(MotorNr);
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].MotorTargetSpeed > 0)
+ {
+ if (MotorData[MotorNr].CurrentCaptureCount >= MotorData[MotorNr].MotorTachoCountToRun)
+ {
+ dOutputMotorReachedTachoLimit(MotorNr);
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].CurrentCaptureCount <= MotorData[MotorNr].MotorTachoCountToRun)
+ {
+ dOutputMotorReachedTachoLimit(MotorNr);
+ }
+ }
+ }
+ if (MotorData[MotorNr].RegulationMode == REGSTATE_IDLE)
+ {
+ MotorData[MotorNr].MotorActualSpeed = MotorData[MotorNr].MotorTargetSpeed;
+ }
+}
+
+/* Function used to tell whether the wanted position is obtained */
+void dOutputTachoLimitControl(UBYTE MotorNr)
+{
+ if (MotorData[MotorNr].MotorRunForever == 0)
+ {
+ if (MotorData[MotorNr].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ dOutputSyncTachoLimitControl(MotorNr);
+ }
+ else
+ {
+ if (MotorData[MotorNr].MotorSetSpeed > 0)
+ {
+ if ((MotorData[MotorNr].CurrentCaptureCount >= MotorData[MotorNr].MotorTachoCountToRun))
+ {
+ MotorData[MotorNr].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorNr].RegulationMode = REGSTATE_IDLE;
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].MotorSetSpeed < 0)
+ {
+ if (MotorData[MotorNr].CurrentCaptureCount <= MotorData[MotorNr].MotorTachoCountToRun)
+ {
+ MotorData[MotorNr].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorNr].RegulationMode = REGSTATE_IDLE;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].CurrentCaptureCount > MAX_COUNT_TO_RUN)
+ {
+ MotorData[MotorNr].CurrentCaptureCount = 0;
+ }
+ if (MotorData[MotorNr].MotorTargetSpeed != 0)
+ {
+ MotorData[MotorNr].MotorTachoCountToRun = MotorData[MotorNr].CurrentCaptureCount;
+ }
+ }
+ if (MotorData[MotorNr].RegulationMode == REGSTATE_IDLE)
+ {
+ MotorData[MotorNr].MotorActualSpeed = MotorData[MotorNr].MotorTargetSpeed;
+ }
+}
+
+/* Function used to decrease speed slowly when the motor is set to idle */
+void dOutputMotorIdleControl(UBYTE MotorNr)
+{
+ INSERTMode(MotorNr, COAST_MOTOR_MODE);
+
+ if (MotorData[MotorNr].MotorActualSpeed != 0)
+ {
+ if (MotorData[MotorNr].MotorActualSpeed > 0)
+ {
+ MotorData[MotorNr].MotorActualSpeed--;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorActualSpeed++;
+ }
+ }
+
+ if (MotorData[MotorNr].MotorTargetSpeed != 0)
+ {
+ if (MotorData[MotorNr].MotorTargetSpeed > 0)
+ {
+ MotorData[MotorNr].MotorTargetSpeed--;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorTargetSpeed++;
+ }
+ }
+
+ if (MotorData[MotorNr].MotorSetSpeed != 0)
+ {
+ if (MotorData[MotorNr].MotorSetSpeed > 0)
+ {
+ MotorData[MotorNr].MotorSetSpeed--;
+ }
+ else
+ {
+ MotorData[MotorNr].MotorSetSpeed++;
+ }
+ }
+}
+
+/* Function called to evaluate which regulation princip that need to run and which MotorNr to use (I.E.: Which motors are synched together)*/
+void dOutputRegulateMotor(UBYTE MotorNr)
+{
+ UBYTE SyncMotorOne;
+ UBYTE SyncMotorTwo;
+
+ if (MotorData[MotorNr].RegulationMode & REGSTATE_REGULATED)
+ {
+ dOutputCalculateMotorPosition(MotorNr);
+ }
+ else
+ {
+ if (MotorData[MotorNr].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ dOutputMotorSyncStatus(MotorNr, &SyncMotorOne, &SyncMotorTwo);
+
+ if ((SyncMotorOne != 0xFF) &&(SyncMotorTwo != 0xFF))
+ {
+ dOutputSyncMotorPosition(SyncMotorOne, SyncMotorTwo);
+ }
+ }
+ }
+}
+
+/* Regulation function used when Position regulation is enabled */
+/* The regulation form only control one motor at a time */
+void dOutputCalculateMotorPosition(UBYTE MotorNr)
+{
+ SWORD PositionError;
+ SWORD PValue;
+ SWORD IValue;
+ SWORD DValue;
+ SWORD TotalRegValue;
+ SWORD NewSpeedCount = 0;
+
+ NewSpeedCount = (SWORD)((MotorData[MotorNr].MotorTargetSpeed * MAX_CAPTURE_COUNT)/INPUT_SCALE_FACTOR);
+
+ PositionError = (SWORD)(MotorData[MotorNr].OldPositionError - MotorData[MotorNr].DeltaCaptureCount) + NewSpeedCount;
+
+ //Overflow control on PositionError
+ if (MotorData[MotorNr].RegPParameter != 0)
+ {
+ if (PositionError > (SWORD)(32000 / MotorData[MotorNr].RegPParameter))
+ {
+ PositionError = (SWORD)(32000 / MotorData[MotorNr].RegPParameter);
+ }
+ if (PositionError < (SWORD)(-(32000 / MotorData[MotorNr].RegPParameter)))
+ {
+ PositionError = (SWORD)(-(32000 / MotorData[MotorNr].RegPParameter));
+ }
+ }
+ else
+ {
+ if (PositionError > (SWORD)32000)
+ {
+ PositionError = (SWORD)32000;
+ }
+ if (PositionError < (SWORD)-32000)
+ {
+ PositionError = (SWORD)-32000;
+ }
+ }
+
+ PValue = PositionError * (SWORD)(MotorData[MotorNr].RegPParameter/REG_CONST_DIV);
+ if (PValue > (SWORD)REG_MAX_VALUE)
+ {
+ PValue = REG_MAX_VALUE;
+ }
+ if (PValue <= (SWORD)REG_MIN_VALUE)
+ {
+ PValue = REG_MIN_VALUE;
+ }
+
+ DValue = (PositionError - MotorData[MotorNr].OldPositionError) * (SWORD)(MotorData[MotorNr].RegDParameter/REG_CONST_DIV);
+ MotorData[MotorNr].OldPositionError = PositionError;
+
+ MotorData[MotorNr].AccError = (MotorData[MotorNr].AccError * 3) + PositionError;
+ MotorData[MotorNr].AccError = MotorData[MotorNr].AccError / 4;
+
+ if (MotorData[MotorNr].AccError > (SWORD)800)
+ {
+ MotorData[MotorNr].AccError = 800;
+ }
+ if (MotorData[MotorNr].AccError <= (SWORD)-800)
+ {
+ MotorData[MotorNr].AccError = -800;
+ }
+ IValue = MotorData[MotorNr].AccError * (SWORD)(MotorData[MotorNr].RegIParameter/REG_CONST_DIV);
+
+ if (IValue > (SWORD)REG_MAX_VALUE)
+ {
+ IValue = REG_MAX_VALUE;
+ }
+ if (IValue <= (SWORD)REG_MIN_VALUE)
+ {
+ IValue = REG_MIN_VALUE;
+ }
+ TotalRegValue = (SWORD)((PValue + IValue + DValue)/2);
+
+ if (TotalRegValue > MAXIMUM_SPEED_FW)
+ {
+ TotalRegValue = MAXIMUM_SPEED_FW;
+ MotorData[MotorNr].MotorOverloaded = 1;
+ }
+ if (TotalRegValue < MAXIMUM_SPEED_RW)
+ {
+ TotalRegValue = MAXIMUM_SPEED_RW;
+ MotorData[MotorNr].MotorOverloaded = 1;
+ }
+ MotorData[MotorNr].MotorActualSpeed = (SBYTE)TotalRegValue;
+}
+
+/* Regulation function used when syncrhonization regulation is enabled */
+/* The regulation form controls two motors at a time */
+void dOutputSyncMotorPosition(UBYTE MotorOne, UBYTE MotorTwo)
+{
+ SLONG TempTurnParameter;
+ SWORD PValue;
+ SWORD IValue;
+ SWORD DValue;
+ SWORD CorrectionValue;
+ SWORD MotorSpeed;
+
+ SyncData.SyncTachoDif = (SLONG)((MotorData[MotorOne].MotorBlockTachoCount) - (MotorData[MotorTwo].MotorBlockTachoCount));
+
+ if (MotorData[MotorOne].TurnParameter != 0)
+ {
+ if ((MotorData[MotorOne].MotorBlockTachoCount != 0) || (MotorData[MotorTwo].MotorBlockTachoCount))
+ {
+ if (MotorData[MotorOne].MotorTargetSpeed >= 0)
+ {
+ if (MotorData[MotorOne].TurnParameter > 0)
+ {
+ TempTurnParameter = (SLONG)(((SLONG)MotorData[MotorTwo].TurnParameter * (SLONG)MotorData[MotorTwo].MotorTargetSpeed)/100);
+ }
+ else
+ {
+ TempTurnParameter = (SLONG)(((SLONG)MotorData[MotorOne].TurnParameter * (SLONG)MotorData[MotorOne].MotorTargetSpeed)/100);
+ }
+ }
+ else
+ {
+ if (MotorData[MotorOne].TurnParameter > 0)
+ {
+ TempTurnParameter = (SLONG)(((SLONG)MotorData[MotorOne].TurnParameter * (-(SLONG)MotorData[MotorOne].MotorTargetSpeed))/100);
+ }
+ else
+ {
+ TempTurnParameter = (SLONG)(((SLONG)MotorData[MotorTwo].TurnParameter * (-(SLONG)MotorData[MotorTwo].MotorTargetSpeed))/100);
+ }
+ }
+ }
+ else
+ {
+ TempTurnParameter = MotorData[MotorOne].TurnParameter;
+ }
+ }
+ else
+ {
+ TempTurnParameter = 0;
+ }
+
+ SyncData.SyncTurnParameter += (SLONG)(((TempTurnParameter * (MAX_CAPTURE_COUNT))/INPUT_SCALE_FACTOR)*2);
+ //SyncTurnParameter should ophold difference between the two motors.
+
+ SyncData.SyncTachoDif += SyncData.SyncTurnParameter;
+
+ if ((SWORD)SyncData.SyncTachoDif > 500)
+ {
+ SyncData.SyncTachoDif = 500;
+ }
+ if ((SWORD)SyncData.SyncTachoDif < -500)
+ {
+ SyncData.SyncTachoDif = -500;
+ }
+
+ PValue = (SWORD)SyncData.SyncTachoDif * (SWORD)(MotorData[MotorOne].RegPParameter/REG_CONST_DIV);
+
+ DValue = ((SWORD)SyncData.SyncTachoDif - SyncData.SyncOldError) * (SWORD)(MotorData[MotorOne].RegDParameter/REG_CONST_DIV);
+ SyncData.SyncOldError = (SWORD)SyncData.SyncTachoDif;
+
+ SyncData.SyncAccError += (SWORD)SyncData.SyncTachoDif;
+
+ if (SyncData.SyncAccError > (SWORD)900)
+ {
+ SyncData.SyncAccError = 900;
+ }
+ if (SyncData.SyncAccError < (SWORD)-900)
+ {
+ SyncData.SyncAccError = -900;
+ }
+ IValue = SyncData.SyncAccError * (SWORD)(MotorData[MotorOne].RegIParameter/REG_CONST_DIV);
+
+ CorrectionValue = (SWORD)((PValue + IValue + DValue)/4);
+
+ MotorSpeed = (SWORD)MotorData[MotorOne].MotorTargetSpeed - CorrectionValue;
+
+ if (MotorSpeed > (SWORD)MAXIMUM_SPEED_FW)
+ {
+ MotorSpeed = MAXIMUM_SPEED_FW;
+ }
+ else
+ {
+ if (MotorSpeed < (SWORD)MAXIMUM_SPEED_RW)
+ {
+ MotorSpeed = MAXIMUM_SPEED_RW;
+ }
+ }
+
+ if (MotorData[MotorOne].TurnParameter != 0)
+ {
+ if (MotorData[MotorOne].MotorTargetSpeed > 0)
+ {
+ if (MotorSpeed > (SWORD)MotorData[MotorOne].MotorTargetSpeed)
+ {
+ MotorSpeed = (SWORD)MotorData[MotorOne].MotorTargetSpeed;
+ }
+ else
+ {
+ if (MotorSpeed < (SWORD)-MotorData[MotorOne].MotorTargetSpeed)
+ {
+ MotorSpeed = -MotorData[MotorOne].MotorTargetSpeed;
+ }
+ }
+ }
+ else
+ {
+ if (MotorSpeed < (SWORD)MotorData[MotorOne].MotorTargetSpeed)
+ {
+ MotorSpeed = (SWORD)MotorData[MotorOne].MotorTargetSpeed;
+ }
+ else
+ {
+ if (MotorSpeed > (SWORD)-MotorData[MotorOne].MotorTargetSpeed)
+ {
+ MotorSpeed = -MotorData[MotorOne].MotorTargetSpeed;
+ }
+ }
+ }
+ }
+ MotorData[MotorOne].MotorActualSpeed = (SBYTE)MotorSpeed;
+
+ MotorSpeed = (SWORD)MotorData[MotorTwo].MotorTargetSpeed + CorrectionValue;
+
+ if (MotorSpeed > (SWORD)MAXIMUM_SPEED_FW)
+ {
+ MotorSpeed = MAXIMUM_SPEED_FW;
+ }
+ else
+ {
+ if (MotorSpeed < (SWORD)MAXIMUM_SPEED_RW)
+ {
+ MotorSpeed = MAXIMUM_SPEED_RW;
+ }
+ }
+
+ if (MotorData[MotorOne].TurnParameter != 0)
+ {
+ if (MotorData[MotorTwo].MotorTargetSpeed > 0)
+ {
+ if (MotorSpeed > (SWORD)MotorData[MotorTwo].MotorTargetSpeed)
+ {
+ MotorSpeed = (SWORD)MotorData[MotorTwo].MotorTargetSpeed;
+ }
+ else
+ {
+ if (MotorSpeed < (SWORD)-MotorData[MotorTwo].MotorTargetSpeed)
+ {
+ MotorSpeed = -MotorData[MotorTwo].MotorTargetSpeed;
+ }
+ }
+ }
+ else
+ {
+ if (MotorSpeed < (SWORD)MotorData[MotorTwo].MotorTargetSpeed)
+ {
+ MotorSpeed = (SWORD)MotorData[MotorTwo].MotorTargetSpeed;
+ }
+ else
+ {
+ if (MotorSpeed > (SWORD)-MotorData[MotorTwo].MotorTargetSpeed)
+ {
+ MotorSpeed = -MotorData[MotorTwo].MotorTargetSpeed;
+ }
+ }
+ }
+ }
+ MotorData[MotorTwo].MotorActualSpeed = (SBYTE)MotorSpeed;
+}
+
+//Called when the motor is ramping down
+void dOutputMotorReachedTachoLimit(UBYTE MotorNr)
+{
+ UBYTE MotorOne, MotorTwo;
+
+ if (MotorData[MotorNr].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ if (MotorNr == MOTOR_A)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne + 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & B
+ MotorData[MotorOne].MotorSetSpeed = 0;
+ MotorData[MotorOne].MotorTargetSpeed = 0;
+ MotorData[MotorOne].MotorActualSpeed = 0;
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorOne].RegulationMode = REGSTATE_IDLE;
+ MotorData[MotorTwo].MotorSetSpeed = 0;
+ MotorData[MotorTwo].MotorTargetSpeed = 0;
+ MotorData[MotorTwo].MotorActualSpeed = 0;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].RegulationMode = REGSTATE_IDLE;
+ }
+ else
+ {
+ MotorTwo = MotorOne + 2;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & C
+ MotorData[MotorOne].MotorSetSpeed = 0;
+ MotorData[MotorOne].MotorTargetSpeed = 0;
+ MotorData[MotorOne].MotorActualSpeed = 0;
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorOne].RegulationMode = REGSTATE_IDLE;
+ MotorData[MotorTwo].MotorSetSpeed = 0;
+ MotorData[MotorTwo].MotorTargetSpeed = 0;
+ MotorData[MotorTwo].MotorActualSpeed = 0;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].RegulationMode = REGSTATE_IDLE;
+ }
+ else
+ {
+ //Only Motor A has Sync setting => Stop normal
+ MotorData[MotorNr].MotorSetSpeed = 0;
+ MotorData[MotorNr].MotorTargetSpeed = 0;
+ MotorData[MotorNr].MotorActualSpeed = 0;
+ MotorData[MotorNr].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorNr].RegulationMode = REGSTATE_IDLE;
+ }
+ }
+ }
+ if (MotorNr == MOTOR_B)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne - 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & B
+ MotorData[MotorOne].MotorSetSpeed = 0;
+ MotorData[MotorOne].MotorTargetSpeed = 0;
+ MotorData[MotorOne].MotorActualSpeed = 0;
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorOne].RegulationMode = REGSTATE_IDLE;
+ MotorData[MotorTwo].MotorSetSpeed = 0;
+ MotorData[MotorTwo].MotorTargetSpeed = 0;
+ MotorData[MotorTwo].MotorActualSpeed = 0;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].RegulationMode = REGSTATE_IDLE;
+ }
+ MotorTwo = MotorOne + 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor B & C
+ MotorData[MotorOne].MotorSetSpeed = 0;
+ MotorData[MotorOne].MotorTargetSpeed = 0;
+ MotorData[MotorOne].MotorActualSpeed = 0;
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorOne].RegulationMode = REGSTATE_IDLE;
+ MotorData[MotorTwo].MotorSetSpeed = 0;
+ MotorData[MotorTwo].MotorTargetSpeed = 0;
+ MotorData[MotorTwo].MotorActualSpeed = 0;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].RegulationMode = REGSTATE_IDLE;
+ }
+ else
+ {
+ //Only Motor B has Sync settings => Stop normal
+ MotorData[MotorNr].MotorSetSpeed = 0;
+ MotorData[MotorNr].MotorTargetSpeed = 0;
+ MotorData[MotorNr].MotorActualSpeed = 0;
+ MotorData[MotorNr].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorNr].RegulationMode = REGSTATE_IDLE;
+ }
+ }
+ if (MotorNr == MOTOR_C)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne - 2;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & C
+ MotorData[MotorOne].MotorSetSpeed = 0;
+ MotorData[MotorOne].MotorTargetSpeed = 0;
+ MotorData[MotorOne].MotorActualSpeed = 0;
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorOne].RegulationMode = REGSTATE_IDLE;
+ MotorData[MotorTwo].MotorSetSpeed = 0;
+ MotorData[MotorTwo].MotorTargetSpeed = 0;
+ MotorData[MotorTwo].MotorActualSpeed = 0;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].RegulationMode = REGSTATE_IDLE;
+ }
+ MotorTwo = MotorOne - 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor B & C
+ MotorData[MotorOne].MotorSetSpeed = 0;
+ MotorData[MotorOne].MotorTargetSpeed = 0;
+ MotorData[MotorOne].MotorActualSpeed = 0;
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorOne].RegulationMode = REGSTATE_IDLE;
+ MotorData[MotorTwo].MotorSetSpeed = 0;
+ MotorData[MotorTwo].MotorTargetSpeed = 0;
+ MotorData[MotorTwo].MotorActualSpeed = 0;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].RegulationMode = REGSTATE_IDLE;
+ }
+ else
+ {
+ //Only Motor C has Sync settings => Stop normal
+ MotorData[MotorNr].MotorSetSpeed = 0;
+ MotorData[MotorNr].MotorTargetSpeed = 0;
+ MotorData[MotorNr].MotorActualSpeed = 0;
+ MotorData[MotorNr].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorNr].RegulationMode = REGSTATE_IDLE;
+ }
+ }
+ }
+ else
+ {
+ if (MotorData[MotorNr].MotorSetSpeed == 0)
+ {
+ MotorData[MotorNr].MotorSetSpeed = 0;
+ MotorData[MotorNr].MotorTargetSpeed = 0;
+ MotorData[MotorNr].MotorActualSpeed = 0;
+ }
+ MotorData[MotorNr].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorNr].RegulationMode = REGSTATE_IDLE;
+ }
+}
+
+/* Function used for control tacho limit when motors are synchronised */
+/* Special control is needed when the motor are turning */
+void dOutputSyncTachoLimitControl(UBYTE MotorNr)
+{
+ UBYTE MotorOne, MotorTwo;
+
+ if (MotorNr == MOTOR_A)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne + 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & B
+ }
+ else
+ {
+ MotorTwo = MotorOne + 2;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & C
+ }
+ else
+ {
+ //Only Motor A has Sync setting => Stop normal
+ MotorOne = 0xFF;
+ MotorTwo = 0xFF;
+ }
+ }
+ }
+ if (MotorNr == MOTOR_B)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne - 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & B, which has already been called when running throught motor A
+ //MotorOne = 0xFF;
+ //MotorTwo = 0xFF;
+ }
+ else
+ {
+ MotorTwo = MotorOne + 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor B & C
+ }
+ else
+ {
+ //Only Motor B has Sync settings => Stop normal
+ MotorOne = 0xFF;
+ MotorTwo = 0xFF;
+ }
+ }
+ }
+ if (MotorNr == MOTOR_C)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne - 2;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & C, which has already been called when running throught motor A
+ //MotorOne = 0xFF;
+ //MotorTwo = 0xFF;
+ }
+ else
+ {
+ MotorTwo = MotorOne - 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor B & C, which has already been called when running throught motor B
+ //MotorOne = 0xFF;
+ //MotorTwo = 0xFF;
+ }
+ else
+ {
+ //Only Motor C has Sync settings => Stop normal
+ MotorOne = 0xFF;
+ MotorTwo = 0xFF;
+ }
+ }
+ }
+
+ if ((MotorOne != 0xFF) && (MotorTwo != 0xFF))
+ {
+ if (MotorData[MotorOne].TurnParameter != 0)
+ {
+ if (MotorData[MotorOne].TurnParameter > 0)
+ {
+ if (MotorData[MotorTwo].MotorTargetSpeed >= 0)
+ {
+ if ((SLONG)(MotorData[MotorTwo].CurrentCaptureCount >= MotorData[MotorTwo].MotorTachoCountToRun))
+ {
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+
+ MotorData[MotorOne].CurrentCaptureCount = MotorData[MotorTwo].CurrentCaptureCount;
+ MotorData[MotorOne].MotorTachoCountToRun = MotorData[MotorTwo].MotorTachoCountToRun;
+ }
+ }
+ else
+ {
+ if ((SLONG)(MotorData[MotorOne].CurrentCaptureCount <= MotorData[MotorOne].MotorTachoCountToRun))
+ {
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+
+ MotorData[MotorTwo].CurrentCaptureCount = MotorData[MotorOne].CurrentCaptureCount;
+ MotorData[MotorTwo].MotorTachoCountToRun = MotorData[MotorOne].MotorTachoCountToRun;
+ }
+ }
+ }
+ else
+ {
+ if (MotorData[MotorOne].MotorTargetSpeed >= 0)
+ {
+ if ((SLONG)(MotorData[MotorOne].CurrentCaptureCount >= MotorData[MotorOne].MotorTachoCountToRun))
+ {
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+
+ MotorData[MotorTwo].CurrentCaptureCount = MotorData[MotorOne].CurrentCaptureCount;
+ MotorData[MotorTwo].MotorTachoCountToRun = MotorData[MotorOne].MotorTachoCountToRun;
+ }
+ }
+ else
+ {
+ if ((SLONG)(MotorData[MotorTwo].CurrentCaptureCount <= MotorData[MotorTwo].MotorTachoCountToRun))
+ {
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+
+ MotorData[MotorOne].CurrentCaptureCount = MotorData[MotorTwo].CurrentCaptureCount;
+ MotorData[MotorOne].MotorTachoCountToRun = MotorData[MotorTwo].MotorTachoCountToRun;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (MotorData[MotorOne].MotorSetSpeed > 0)
+ {
+ if ((MotorData[MotorOne].CurrentCaptureCount >= MotorData[MotorOne].MotorTachoCountToRun) || (MotorData[MotorTwo].CurrentCaptureCount >= MotorData[MotorTwo].MotorTachoCountToRun))
+ {
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ }
+ }
+ else
+ {
+ if (MotorData[MotorOne].MotorSetSpeed < 0)
+ {
+ if ((MotorData[MotorOne].CurrentCaptureCount <= MotorData[MotorOne].MotorTachoCountToRun) || (MotorData[MotorTwo].CurrentCaptureCount <= MotorData[MotorTwo].MotorTachoCountToRun))
+ {
+ MotorData[MotorOne].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ MotorData[MotorTwo].MotorRunState = MOTOR_RUN_STATE_IDLE;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* Function which can evaluate which motor are synched */
+void dOutputMotorSyncStatus(UBYTE MotorNr, UBYTE *SyncMotorOne, UBYTE *SyncMotorTwo)
+{
+ if (MotorNr < MOTOR_C)
+ {
+ if (MotorNr == MOTOR_A)
+ {
+ *SyncMotorOne = MotorNr;
+ *SyncMotorTwo = *SyncMotorOne + 1;
+ if (MotorData[*SyncMotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & B
+ }
+ else
+ {
+ *SyncMotorTwo = *SyncMotorOne + 2;
+ if (MotorData[*SyncMotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & C
+ }
+ else
+ {
+ //Only Motor A has Sync setting => Do nothing, treat motor as motor without regulation
+ *SyncMotorTwo = 0xFF;
+ }
+ }
+ }
+ if (MotorNr == MOTOR_B)
+ {
+ *SyncMotorOne = MotorNr;
+ *SyncMotorTwo = *SyncMotorOne + 1;
+ if (MotorData[*SyncMotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ if (!(MotorData[MOTOR_A].RegulationMode & REGSTATE_SYNCHRONE))
+ {
+ //Synchronise motor B & C
+ }
+ }
+ else
+ {
+ //Only Motor B has Sync settings or Motor is sync. with Motor A and has therefore already been called
+ *SyncMotorTwo = 0xFF;
+ }
+ }
+ }
+ else
+ {
+ *SyncMotorOne = 0xFF;
+ *SyncMotorTwo = 0xFF;
+ }
+}
+/* Function which is called when motors are synchronized and the motor position is reset */
+void dOutputResetSyncMotors(UBYTE MotorNr)
+{
+ UBYTE MotorOne, MotorTwo;
+
+ if (MotorNr == MOTOR_A)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne + 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & B
+ }
+ else
+ {
+ MotorTwo = MotorOne + 2;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & C
+ }
+ else
+ {
+ //Only Motor A has Sync setting => Stop normal
+ MotorOne = 0xFF;
+ MotorTwo = 0xFF;
+ }
+ }
+ }
+ if (MotorNr == MOTOR_B)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne - 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & B
+ }
+ else
+ {
+ MotorTwo = MotorOne + 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor B & C
+ }
+ else
+ {
+ //Only Motor B has Sync settings => Stop normal
+ MotorOne = 0xFF;
+ MotorTwo = 0xFF;
+ }
+ }
+ }
+ if (MotorNr == MOTOR_C)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne - 2;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & C
+ }
+ else
+ {
+ MotorTwo = MotorOne - 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor B & C
+ }
+ else
+ {
+ //Only Motor C has Sync settings => Stop normal
+ MotorOne = 0xFF;
+ MotorTwo = 0xFF;
+ }
+ }
+ }
+
+ if ((MotorOne != 0xFF) && (MotorTwo != 0xFF))
+ {
+ MotorData[MotorOne].CurrentCaptureCount = 0;
+ MotorData[MotorOne].MotorTachoCountToRun = 0;
+ MotorData[MotorTwo].CurrentCaptureCount = 0;
+ MotorData[MotorTwo].MotorTachoCountToRun = 0;
+ }
+ else
+ {
+ MotorData[MotorNr].CurrentCaptureCount = 0;
+ MotorData[MotorNr].MotorTachoCountToRun = 0;
+ }
+}
+
+/* Function which is called when motors are synchronized and motor is ramping down */
+void dOutputRampDownSynch(UBYTE MotorNr)
+{
+ UBYTE MotorOne, MotorTwo;
+
+ if (MotorNr == MOTOR_A)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne + 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & B
+ }
+ else
+ {
+ MotorTwo = MotorOne + 2;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & C
+ }
+ else
+ {
+ //Only Motor A has Sync setting => Stop normal
+ MotorOne = 0xFF;
+ MotorTwo = 0xFF;
+ }
+ }
+ }
+ if (MotorNr == MOTOR_B)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne - 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & B, which has already been called when running throught motor A
+ //MotorOne = 0xFF;
+ //MotorTwo = 0xFF;
+ }
+ else
+ {
+ MotorTwo = MotorOne + 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor B & C
+ }
+ else
+ {
+ //Only Motor B has Sync settings => Stop normal
+ MotorOne = 0xFF;
+ MotorTwo = 0xFF;
+ }
+ }
+ }
+ if (MotorNr == MOTOR_C)
+ {
+ MotorOne = MotorNr;
+ MotorTwo = MotorOne - 2;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor A & C, which has already been called when running throught motor A
+ }
+ else
+ {
+ MotorTwo = MotorOne - 1;
+ if (MotorData[MotorTwo].RegulationMode & REGSTATE_SYNCHRONE)
+ {
+ //Synchronise motor B & C,, which has already been called when running throught motor B
+ }
+ else
+ {
+ //Only Motor C has Sync settings => Stop normal
+ MotorOne = 0xFF;
+ MotorTwo = 0xFF;
+ }
+ }
+ }
+
+ if ((MotorOne != 0xFF) && (MotorTwo != 0xFF))
+ {
+ if (MotorData[MotorOne].TurnParameter != 0)
+ {
+ if (MotorData[MotorOne].TurnParameter > 0)
+ {
+ if (MotorData[MotorOne].MotorTargetSpeed >= 0)
+ {
+ if (MotorData[MotorTwo].MotorActualSpeed < 0)
+ {
+ MotorData[MotorTwo].MotorTargetSpeed--;
+ }
+ }
+ else
+ {
+ if (MotorData[MotorTwo].MotorActualSpeed > 0)
+ {
+ MotorData[MotorTwo].MotorTargetSpeed++;
+ }
+ }
+ }
+ else
+ {
+ if (MotorData[MotorOne].MotorTargetSpeed >= 0)
+ {
+ if (MotorData[MotorTwo].MotorActualSpeed < 0)
+ {
+ MotorData[MotorTwo].MotorTargetSpeed--;
+ }
+ }
+ else
+ {
+ if (MotorData[MotorTwo].MotorActualSpeed > 0)
+ {
+ MotorData[MotorTwo].MotorTargetSpeed++;
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/AT91SAM7S256/Source/d_output.h b/AT91SAM7S256/Source/d_output.h
new file mode 100644
index 0000000..cb0de5e
--- /dev/null
+++ b/AT91SAM7S256/Source/d_output.h
@@ -0,0 +1,90 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: d_output.h $
+//
+// Version $Revision:: 48 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_output.h $
+//
+// Platform C
+//
+
+#ifndef D_OUTPUT
+#define D_OUTPUT
+
+#define NEW_MOTOR
+
+#ifdef NEW_MOTOR
+
+//Constant reffering to new motor
+#define REG_CONST_DIV 32 // Constant which the PID constants value will be divided with
+#define DEFAULT_P_GAIN_FACTOR 96//3
+#define DEFAULT_I_GAIN_FACTOR 32//1
+#define DEFAULT_D_GAIN_FACTOR 32//1
+#define MIN_MOVEMENT_POWER 10
+#define MAX_CAPTURE_COUNT 100
+
+#else
+
+//Constant reffering to Old motor
+#define REG_CONST_DIV 1 // Constant which the PID constants value will be divided with
+#define DEFAULT_P_GAIN_FACTOR 3
+#define DEFAULT_I_GAIN_FACTOR 1
+#define DEFAULT_D_GAIN_FACTOR 1
+#define MIN_MOVEMENT_POWER 30
+#define MAX_CAPTURE_COUNT 80
+
+#endif
+
+//Constant reffering to RegMode parameter
+#define REGSTATE_IDLE 0x00
+#define REGSTATE_REGULATED 0x01
+#define REGSTATE_SYNCHRONE 0x02
+
+//Constant reffering to RunState parameter
+#define MOTOR_RUN_STATE_IDLE 0x00
+#define MOTOR_RUN_STATE_RAMPUP 0x10
+#define MOTOR_RUN_STATE_RUNNING 0x20
+#define MOTOR_RUN_STATE_RAMPDOWN 0x40
+#define MOTOR_RUN_STATE_HOLD 0x60
+
+
+enum
+{
+ MOTOR_A,
+ MOTOR_B,
+ MOTOR_C
+};
+
+void dOutputInit(void);
+void dOutputExit(void);
+
+void dOutputCtrl(void);
+void dOutputGetMotorParameters(UBYTE *CurrentMotorSpeed, SLONG *TachoCount, SLONG *BlockTachoCount, UBYTE *RunState, UBYTE *MotorOverloaded, SLONG *RotationCount);
+void dOutputSetMode(UBYTE Motor, UBYTE Mode);
+void dOutputSetSpeed (UBYTE MotorNr, UBYTE NewMotorRunState, SBYTE Speed, SBYTE TurnParameter);
+void dOutputEnableRegulation(UBYTE Motor, UBYTE RegulationMode);
+void dOutputDisableRegulation(UBYTE Motor);
+void dOutputSetTachoLimit(UBYTE Motor, ULONG TachoCntToTravel);
+void dOutputResetTachoLimit(UBYTE Motor);
+void dOutputResetBlockTachoLimit(UBYTE Motor);
+void dOutputResetRotationCaptureCount(UBYTE MotorNr);
+void dOutputSetPIDParameters(UBYTE Motor, UBYTE NewRegPParameter, UBYTE NewRegIParameter, UBYTE NewRegDParameter);
+
+void dOutputRegulateMotor(UBYTE MotorNr);
+void dOutputCalculateRampUpParameter(UBYTE MotorNr, ULONG NewTachoLimit);
+void dOutputRampDownFunction(UBYTE MotorNr);
+void dOutputRampUpFunction(UBYTE MotorNr);
+void dOutputTachoLimitControl(UBYTE MotorNr);
+void dOutputCalculateMotorPosition(UBYTE MotorNr);
+void dOutputSyncMotorPosition(UBYTE MotorOne, UBYTE MotorTwo);
+void dOutputMotorReachedTachoLimit(UBYTE MotorNr);
+void dOutputMotorIdleControl(UBYTE MotorNr);
+void dOutputSyncTachoLimitControl(UBYTE MotorNr);
+void dOutputMotorSyncStatus(UBYTE MotorNr, UBYTE *SyncMotorOne, UBYTE *SyncMotorTwo);
+void dOutputResetSyncMotors(UBYTE MotorNr);
+
+#endif
diff --git a/AT91SAM7S256/Source/d_output.r b/AT91SAM7S256/Source/d_output.r
new file mode 100644
index 0000000..0ed35ff
--- /dev/null
+++ b/AT91SAM7S256/Source/d_output.r
@@ -0,0 +1,306 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 12:13 $
+//
+// Filename $Workfile:: d_output.r $
+//
+// Version $Revision:: 36 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_output.r $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+#if defined (PROTOTYPE_PCB_3) || (PROTOTYPE_PCB_4)
+
+#define MOTOR_A_DIR AT91C_PIO_PA1
+#define MOTOR_A_INT AT91C_PIO_PA15
+
+#define MOTOR_B_DIR AT91C_PIO_PA9
+#define MOTOR_B_INT AT91C_PIO_PA26
+
+#define MOTOR_C_DIR AT91C_PIO_PA8
+#define MOTOR_C_INT AT91C_PIO_PA0
+
+#else
+
+#define MOTOR_A_DIR AT91C_PIO_PA1
+#define MOTOR_A_INT AT91C_PIO_PA15
+
+#define MOTOR_B_DIR AT91C_PIO_PA9
+#define MOTOR_B_INT AT91C_PIO_PA26
+
+#define MOTOR_C_DIR AT91C_PIO_PA8
+#define MOTOR_C_INT AT91C_PIO_PA27
+
+#endif
+
+#define FORWARD 0x01
+#define REVERSE -0x01
+
+#define TIMER_0_ID12 (1L << AT91C_ID_TC0)
+#define TIMER_1_ID13 (1L << AT91C_ID_TC1)
+#define TIMER_2_ID14 (1L << AT91C_ID_TC2)
+
+typedef struct
+{
+ SLONG TachoCountTable;
+ SLONG TachoCountTableOld;
+ SBYTE MotorDirection;
+}TACHOPARAMETERS;
+
+static TACHOPARAMETERS MotorTachoValue[3];
+
+#define OUTPUTInit {\
+ UBYTE Tmp;\
+ for (Tmp = 0; Tmp < NOS_OF_AVR_OUTPUTS; Tmp++)\
+ {\
+ IoToAvr.PwmValue[Tmp] = 0;\
+ }\
+ IoToAvr.OutputMode = 0x00;\
+ IoToAvr.PwmFreq = 8;\
+ }
+
+#define INSERTSpeed(Motor, Speed) IoToAvr.PwmValue[Motor] = Speed
+
+#define INSERTMode(Motor, Mode) if (Mode & 0x02)\
+ {\
+ IoToAvr.OutputMode |= (0x01 << Motor);\
+ }\
+ else\
+ {\
+ IoToAvr.OutputMode &= ~(0x01 << Motor);\
+ }
+
+#define ENABLEDebugOutput {\
+ *AT91C_PIOA_PER = 0x20000000; /* Enable PIO on PA029 */\
+ *AT91C_PIOA_OER = 0x20000000; /* PA029 set to Output */\
+ }
+
+#define SETDebugOutputHigh *AT91C_PIOA_SODR = 0x20000000
+
+#define SETDebugOutputLow *AT91C_PIOA_CODR = 0x20000000
+
+#define ENABLECaptureMotorA {\
+ *AT91C_PIOA_PDR = MOTOR_A_INT; /* Disable PIO on PA15 */\
+ *AT91C_PIOA_BSR = MOTOR_A_INT; /* Enable Peripheral B on PA15 */\
+ *AT91C_PIOA_PPUDR = MOTOR_A_INT | MOTOR_A_DIR; /* Disable Pull Up resistor on PA15 & PA1 */\
+ *AT91C_PIOA_PER = MOTOR_A_DIR; /* Enable PIO on PA1 */\
+ *AT91C_PIOA_ODR = MOTOR_A_DIR; /* PA1 set to input */\
+ *AT91C_PIOA_IFER = MOTOR_A_INT | MOTOR_A_DIR; /* Enable filter on PA15 & PA1 */\
+ *AT91C_PMC_PCER = TIMER_1_ID13; /* Enable clock for TC1*/\
+ *AT91C_TCB_BMR = AT91C_TCB_TC1XC1S_NONE; /* No external clock signal XC2 */\
+ *AT91C_TCB_BCR = 0x0; /* Clear SYNC */\
+ *AT91C_TC1_CMR = *AT91C_TC1_CMR & 0X00000000; /* Clear all bits in TC1_CMR */\
+ *AT91C_TC1_CMR = *AT91C_TC1_CMR & 0xFFFF7FFF; /* Enable capture mode */\
+ *AT91C_TC1_CMR = *AT91C_TC1_CMR | AT91C_TC_CLKS_TIMER_DIV5_CLOCK; /* Set clock for timer to Clock5 = div 1024*/\
+ *AT91C_TC1_CMR = *AT91C_TC1_CMR | AT91C_TC_ABETRG; /* Use external trigger for TIO1*/\
+ *AT91C_TC1_CMR = *AT91C_TC1_CMR | AT91C_TC_EEVTEDG_BOTH; /* Trigger on both edges */\
+ *AT91C_TC1_CMR = *AT91C_TC1_CMR | AT91C_TC_LDRA_RISING; /* RA loading register set */\
+ *AT91C_AIC_IDCR = TIMER_1_ID13; /* Irq controller setup */\
+ AT91C_AIC_SVR[13] = (unsigned int)CaptureAInt; \
+ AT91C_AIC_SMR[13] = 0x05; /* Enable trigger on level */\
+ *AT91C_AIC_ICCR = TIMER_1_ID13; /* Clear interrupt register PID13*/\
+ *AT91C_TC1_IDR = 0xFF; /* Disable all interrupt from TC1 */\
+ *AT91C_TC1_IER = 0x80; /* Enable interrupt from external trigger */\
+ *AT91C_AIC_IECR = TIMER_1_ID13; /* Enable interrupt from TC1 */\
+ *AT91C_TC1_CCR = 0x00; /* Clear registers before setting */\
+ *AT91C_TC1_CCR = AT91C_TC_CLKEN; /* Enable clock */\
+ }
+
+#define ENABLECaptureMotorB {\
+ *AT91C_PIOA_PDR = MOTOR_B_INT; /* Disable PIO on PA26 */\
+ *AT91C_PIOA_BSR = MOTOR_B_INT; /* Enable Peripheral B on PA26 */\
+ *AT91C_PIOA_PER = MOTOR_B_DIR; /* Enable PIO on PA09 */\
+ *AT91C_PIOA_PPUDR = MOTOR_B_INT | MOTOR_B_DIR; /* Disable Pull Up resistor on PA26 & PA09 */\
+ *AT91C_PIOA_ODR = MOTOR_B_DIR; /* PA09 set to input */\
+ *AT91C_PIOA_IFER = MOTOR_B_INT | MOTOR_B_DIR; /* Enable filter on PA26 & PA09 */\
+ *AT91C_PMC_PCER = TIMER_2_ID14; /* Enable clock for TC2*/\
+ *AT91C_TCB_BMR = AT91C_TCB_TC2XC2S_NONE; /* No external clock signal */\
+ *AT91C_TCB_BCR = 0x0; /* Clear SYNC */\
+ *AT91C_TC2_CMR = *AT91C_TC2_CMR & 0X00000000; /* Clear all bits in TC1_CMR */\
+ *AT91C_TC2_CMR = *AT91C_TC2_CMR & 0xFFFF7FFF; /* Enable capture mode */\
+ *AT91C_TC2_CMR = *AT91C_TC2_CMR | AT91C_TC_CLKS_TIMER_DIV5_CLOCK; /* Set clock for timer to Clock5 = div 1024*/\
+ *AT91C_TC2_CMR = *AT91C_TC2_CMR | AT91C_TC_ABETRG; /* Use external trigger for TIO2*/\
+ *AT91C_TC2_CMR = *AT91C_TC2_CMR | AT91C_TC_EEVTEDG_BOTH; /* Trigger on both edges */\
+ *AT91C_TC2_CMR = *AT91C_TC2_CMR | AT91C_TC_LDRA_RISING; /* RA loading register set */\
+ *AT91C_AIC_IDCR = TIMER_2_ID14; /* Irq controller setup */\
+ AT91C_AIC_SVR[14] = (unsigned int)CaptureBInt; \
+ AT91C_AIC_SMR[14] = 0x05; /* Enable trigger on level */\
+ *AT91C_AIC_ICCR = TIMER_2_ID14; /* Clear interrupt register PID14*/\
+ *AT91C_TC2_IDR = 0xFF; /* Disable all interrupt from TC2 */\
+ *AT91C_TC2_IER = 0x80; /* Enable interrupts from external trigger */\
+ *AT91C_AIC_IECR = TIMER_2_ID14; /* Enable interrupt from TC2 */\
+ *AT91C_TC2_CCR = 0x00; /* Clear registers before setting */\
+ *AT91C_TC2_CCR = AT91C_TC_CLKEN; /* Enable clock */\
+ }
+
+ #define ENABLECaptureMotorC {\
+ *AT91C_PIOA_PDR = MOTOR_C_INT; /* Disable PIO on PA0 */\
+ *AT91C_PIOA_BSR = MOTOR_C_INT; /* Enable Peripheral B on PA0 */\
+ *AT91C_PIOA_PER = MOTOR_C_DIR; /* Enable PIO on PA08 */\
+ *AT91C_PIOA_PPUDR = MOTOR_C_INT | MOTOR_C_DIR; /* Disable Pull Up resistor on PA0 & PA08 */\
+ *AT91C_PIOA_ODR = MOTOR_C_DIR; /* PA08 set to input */\
+ *AT91C_PIOA_IFER = MOTOR_C_INT | MOTOR_C_DIR; /* Enable filter on PA26 & PA09 */\
+ *AT91C_PMC_PCER = TIMER_0_ID12; /* Enable clock for TC0*/\
+ *AT91C_TCB_BMR = AT91C_TCB_TC0XC0S_NONE; /* No external clock signal */\
+ *AT91C_TC0_CMR = *AT91C_TC0_CMR & 0X00000000; /* Clear all bits in TC0_CMR */\
+ *AT91C_TC0_CMR = *AT91C_TC0_CMR & 0xFFFF7FFF; /* Enable capture mode */\
+ *AT91C_TC0_CMR = *AT91C_TC0_CMR | AT91C_TC_CLKS_TIMER_DIV5_CLOCK; /* Set clock for timer to Clock5 = div 1024*/\
+ *AT91C_TC0_CMR = *AT91C_TC0_CMR | AT91C_TC_ABETRG; /* Use external trigger for TI0*/\
+ *AT91C_TC0_CMR = *AT91C_TC0_CMR | AT91C_TC_EEVTEDG_BOTH; /* Trigger on both edges */\
+ *AT91C_TC0_CMR = *AT91C_TC0_CMR | AT91C_TC_LDRA_RISING; /* RA loading register set */\
+ *AT91C_AIC_IDCR = TIMER_0_ID12; /* Disable interrupt */\
+ AT91C_AIC_SVR[12] = (unsigned int)CaptureCInt; \
+ AT91C_AIC_SMR[12] = 0x05; /* Enable trigger on level */\
+ *AT91C_AIC_ICCR = TIMER_0_ID12; /* Clear interrupt register PID12*/\
+ *AT91C_TC0_IDR = 0xFF; /* Disable all interrupt from TC0 */\
+ *AT91C_TC0_IER = 0x80; /* Enable interrupts from external trigger */\
+ *AT91C_AIC_IECR = TIMER_0_ID12; /* Enable interrupt from TC0 */\
+ *AT91C_TC0_CCR = 0x00; /* Clear registers before setting */\
+ *AT91C_TC0_CCR = AT91C_TC_CLKEN; /* Enable clock */\
+ }
+
+__ramfunc void CaptureAInt(void)
+{
+ if (*AT91C_TC1_SR & AT91C_TC_MTIOA)
+ {
+ if (*AT91C_PIOA_PDSR & MOTOR_A_DIR)
+ {
+ MotorTachoValue[0].MotorDirection = REVERSE; //Motor is running reverse
+ MotorTachoValue[0].TachoCountTable--;
+ }
+ else
+ {
+ MotorTachoValue[0].MotorDirection = FORWARD; //Motor is running forward
+ MotorTachoValue[0].TachoCountTable++;
+ }
+ }
+ else
+ {
+ if (*AT91C_PIOA_PDSR & MOTOR_A_DIR)
+ {
+ MotorTachoValue[0].MotorDirection = FORWARD;
+ MotorTachoValue[0].TachoCountTable++;
+ }
+ else
+ {
+ MotorTachoValue[0].MotorDirection = REVERSE;
+ MotorTachoValue[0].TachoCountTable--;
+ }
+ }
+}
+
+__ramfunc void CaptureBInt(void)
+{
+ if (*AT91C_TC2_SR & AT91C_TC_MTIOA)
+ {
+ if (*AT91C_PIOA_PDSR & MOTOR_B_DIR)
+ {
+ MotorTachoValue[1].MotorDirection = REVERSE; //Motor is running reverse
+ MotorTachoValue[1].TachoCountTable--;
+ }
+ else
+ {
+ MotorTachoValue[1].MotorDirection = FORWARD; //Motor is running forward
+ MotorTachoValue[1].TachoCountTable++;
+ }
+ }
+ else
+ {
+ if (*AT91C_PIOA_PDSR & MOTOR_B_DIR)
+ {
+ MotorTachoValue[1].MotorDirection = FORWARD;
+ MotorTachoValue[1].TachoCountTable++;
+ }
+ else
+ {
+ MotorTachoValue[1].MotorDirection = REVERSE;
+ MotorTachoValue[1].TachoCountTable--;
+ }
+ }
+}
+
+
+//__ramfunc void CaptureBInt(void)
+//{
+// if (((bool)(*AT91C_TC2_SR & AT91C_TC_MTIOA))==((bool)(*AT91C_PIOA_PDSR & MOTOR_B_DIR)))
+// {
+// MotorTachoValue[1].MotorDirection = REVERSE; //Motor is running reverse
+// MotorTachoValue[1].TachoCountTable--;
+// }
+// else
+// {
+// MotorTachoValue[1].MotorDirection = FORWARD; //Motor is running reverse
+// MotorTachoValue[1].TachoCountTable++;
+// }
+//}
+
+
+__ramfunc void CaptureCInt(void)
+{
+ if (*AT91C_TC0_SR & AT91C_TC_MTIOA)
+ {
+ if (*AT91C_PIOA_PDSR & MOTOR_C_DIR)
+ {
+ MotorTachoValue[2].MotorDirection = REVERSE; //Motor is running reverse
+ MotorTachoValue[2].TachoCountTable--;
+ }
+ else
+ {
+ MotorTachoValue[2].MotorDirection = FORWARD; //Motor is running forward
+ MotorTachoValue[2].TachoCountTable++;
+ }
+ }
+ else
+ {
+ if (*AT91C_PIOA_PDSR & MOTOR_C_DIR)
+ {
+ MotorTachoValue[2].MotorDirection = FORWARD;
+ MotorTachoValue[2].TachoCountTable++;
+ }
+ else
+ {
+ MotorTachoValue[2].MotorDirection = REVERSE;
+ MotorTachoValue[2].TachoCountTable--;
+ }
+ }
+}
+
+#define OUTPUTExit {\
+ *AT91C_AIC_IDCR = TIMER_0_ID12 | TIMER_1_ID13 | TIMER_2_ID14; /* Disable interrupts for the timers */\
+ *AT91C_AIC_ICCR = TIMER_0_ID12 | TIMER_1_ID13 | TIMER_2_ID14; /* Clear penting interrupt register for timers*/\
+ *AT91C_PMC_PCDR = TIMER_0_ID12 | TIMER_1_ID13 | TIMER_2_ID14; /* Disable the clock for each of the timers*/\
+ *AT91C_PIOA_PER = MOTOR_A_DIR | MOTOR_A_INT | MOTOR_B_DIR | MOTOR_B_INT | MOTOR_C_DIR | MOTOR_C_INT; /* Enable PIO on PA15, PA11, PA26, PA09, PA27 & PA08 */\
+ *AT91C_PIOA_ODR = MOTOR_A_DIR | MOTOR_A_INT | MOTOR_B_DIR | MOTOR_B_INT | MOTOR_C_DIR | MOTOR_C_INT; /* Set to input PA15, PA11, PA26, PA09, PA27 & PA08 */\
+ *AT91C_PIOA_PPUDR = MOTOR_A_DIR | MOTOR_A_INT | MOTOR_B_DIR | MOTOR_B_INT | MOTOR_C_DIR | MOTOR_C_INT; /* Enable Pullup on PA15, PA11, PA26, PA09, PA27 & PA08 */\
+ }
+
+
+#define TACHOCountReset(MotorNr) {\
+ MotorTachoValue[MotorNr].TachoCountTable = 0;\
+ MotorTachoValue[MotorNr].TachoCountTableOld = 0;\
+ }
+
+#define TACHOCaptureReadResetAll(MotorDataA,MotorDataB,MotorDataC){\
+ MotorDataA = (MotorTachoValue[MOTOR_A].TachoCountTable - MotorTachoValue[MOTOR_A].TachoCountTableOld);\
+ MotorTachoValue[MOTOR_A].TachoCountTableOld = MotorTachoValue[MOTOR_A].TachoCountTable;\
+ MotorDataB = (MotorTachoValue[MOTOR_B].TachoCountTable - MotorTachoValue[MOTOR_B].TachoCountTableOld);\
+ MotorTachoValue[MOTOR_B].TachoCountTableOld = MotorTachoValue[MOTOR_B].TachoCountTable;\
+ MotorDataC = (MotorTachoValue[MOTOR_C].TachoCountTable - MotorTachoValue[MOTOR_C].TachoCountTableOld);\
+ MotorTachoValue[MOTOR_C].TachoCountTableOld = MotorTachoValue[MOTOR_C].TachoCountTable;\
+ }
+
+
+
+
+#define GetMotorDirection(MotorNr) MotorTachoValue[MotorNr].MotorDirection
+
+#endif
+
+#ifdef PCWIN
+
+#endif
diff --git a/AT91SAM7S256/Source/d_sound.c b/AT91SAM7S256/Source/d_sound.c
new file mode 100644
index 0000000..66745d3
--- /dev/null
+++ b/AT91SAM7S256/Source/d_sound.c
@@ -0,0 +1,70 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dkflebun $
+//
+// Revision date $Date:: 5-02-07 13:36 $
+//
+// Filename $Workfile:: d_sound.c $
+//
+// Version $Revision:: 11 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_sound.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "m_sched.h"
+#include "d_sound.h"
+#include "d_sound.r"
+
+
+void dSoundInit(void)
+{
+ SOUNDInit;
+}
+
+
+void dSoundVolume(UBYTE Step)
+{
+ SOUNDVolume(Step);
+}
+
+
+UBYTE dSoundReady(void)
+{
+ return (SOUNDReady);
+}
+
+
+UBYTE dSoundStart(UBYTE *pSound,UWORD Length,UWORD SampleRate, UBYTE FileType)
+{
+ return (SOUNDStart(pSound,Length,SampleRate,FileType));
+}
+
+
+UBYTE dSoundStop(void)
+{
+ return (SOUNDStop);
+}
+
+
+UBYTE dSoundTone(UBYTE *pMelody,UWORD Length,UBYTE Volume)
+{
+ return (SOUNDTone(pMelody,Length,Volume));
+}
+
+
+void dSoundFreq(UWORD Hz,UWORD mS,UBYTE Volume)
+{
+ SOUNDFreq(Hz,mS,Volume);
+}
+
+
+void dSoundExit(void)
+{
+ SOUNDExit;
+}
diff --git a/AT91SAM7S256/Source/d_sound.h b/AT91SAM7S256/Source/d_sound.h
new file mode 100644
index 0000000..8cef028
--- /dev/null
+++ b/AT91SAM7S256/Source/d_sound.h
@@ -0,0 +1,42 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dkflebun $
+//
+// Revision date $Date:: 5-02-07 13:36 $
+//
+// Filename $Workfile:: d_sound.h $
+//
+// Version $Revision:: 10 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_sound.h $
+//
+// Platform C
+//
+
+
+#ifndef D_SOUND
+#define D_SOUND
+
+void dSoundInit(void);
+void dSoundVolume(UBYTE Step);
+UBYTE dSoundReady(void);
+UBYTE dSoundStart(UBYTE *pSound,UWORD Length,UWORD SampleRate, UBYTE FileFormat);
+UBYTE dSoundStop(void);
+UBYTE dSoundTone(UBYTE *pMelody,UWORD Length,UBYTE Volume);
+void dSoundFreq(UWORD Hz,UWORD mS,UBYTE Volume);
+void dSoundExit(void);
+
+#define SOUNDVOLUMESTEPS 4
+
+#define DURATION_MIN 10 // [mS]
+#define FREQUENCY_MIN 220 // [Hz]
+#define FREQUENCY_MAX 14080 // [Hz]
+
+#define SAMPLERATE_MIN 2000 // Min sample rate [sps]
+#define SAMPLERATE_DEFAULT 8000 // Default sample rate [sps]
+#define SAMPLERATE_MAX 16000 // Max sample rate [sps]
+
+#endif
diff --git a/AT91SAM7S256/Source/d_sound.r b/AT91SAM7S256/Source/d_sound.r
new file mode 100644
index 0000000..00c7511
--- /dev/null
+++ b/AT91SAM7S256/Source/d_sound.r
@@ -0,0 +1,514 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dkflebun $
+//
+// Revision date $Date:: 5-02-07 13:36 $
+//
+// Filename $Workfile:: d_sound.r $
+//
+// Version $Revision:: 34 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_sound.r $
+//
+// Platform C
+//
+
+#include "d_sound_adpcm.r"
+
+#ifdef SAM7S256
+
+#define SAMPLEMIN 0 // Must be zero (no pwm/interrupt)
+#define SAMPLEMAX 256 // Must be 256 (8 bit wave format)
+#define SAMPLECENTER (((SAMPLEMAX - SAMPLEMIN) / 2) + SAMPLEMIN)
+
+#define SAMPLEWORD ULONG
+#define SAMPLEWORDS 8
+#define SAMPLEWORDBITS (sizeof(SAMPLEWORD) * 8)
+#define SAMPLEBITS (SAMPLEWORDS * SAMPLEWORDBITS)
+#define SAMPLECONSTANT 3 // >> == (SAMPLEMAX / SAMPLEWORDBITS)
+
+#define SAMPLETONENO 16 // No of tone samples
+
+#define SAMPLEBUFFERS 2
+
+#define INIT_PREV_VAL_ADPCM 0x7F
+#define INIT_INDEX_ADPCM 20
+
+SAMPLEWORD SampleBuffer[SAMPLEBUFFERS][SAMPLEWORDS];
+SAMPLEWORD ToneBuffer[SAMPLETONENO];
+
+const SAMPLEWORD TonePattern[SOUNDVOLUMESTEPS + 1][SAMPLETONENO] =
+{
+ {
+ 0xF0F0F0F0,0xF0F0F0F0, // Step 0 = silence
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0
+ },
+ {
+ 0xF0F0F0F0,0xF0F0F0F0, // Step 1 = 1/512
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F8,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0
+ },
+ {
+ 0xF0F0F0F0,0xF0F0F0F0, // Step 2 = 0,+3,+4,+3,0,-3,-4,-3
+ 0xF0F0F0F0,0xF0F8F8F8,
+ 0xF0F0F8F8,0xF8F8F0F0,
+ 0xF8F8F8F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xF0F0F0F0,0xF0E0E0E0,
+ 0xF0F0E0E0,0xE0E0F0F0,
+ 0xE0E0E0F0,0xF0F0F0F0
+ },
+ {
+ 0xF0F0F0F0,0xF0F0F0F0, // Step 3 = 0,+10,+14,+10,0,-10,-14,-10
+ 0xF8F8F8F8,0xF8F8FCFC,
+ 0xF8F8FCFC,0xFCFCFCFC,
+ 0xFCFCF8F8,0xF8F8F8F8,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xE0E0E0E0,0xE0E0C0C0,
+ 0xE0E0C0C0,0xC0C0C0C0,
+ 0xC0C0E0E0,0xE0E0E0E0
+ },
+ {
+ 0xF0F0F0F0,0xF0F0F0F0, // Step 4 = 0,+22,+32,+22,0,-22,-32,-22
+ 0xFCFCFCFC,0xFCFCFDFD,
+ 0xFFFFFFFF,0xFFFFFFFF,
+ 0xFDFDFCFC,0xFCFCFCFC,
+ 0xF0F0F0F0,0xF0F0F0F0,
+ 0xC0C0C0C0,0xC0C08080,
+ 0x00000000,0x00000000,
+ 0x8080C0C0,0xC0C0C0C0
+ }
+};
+
+UBYTE FractionPattern[SAMPLEWORDS] =
+{
+ 0x00, // 0 -> 00000000
+ 0x10, // 1 -> 00010000
+ 0x22, // 2 -> 00100010
+ 0x4A, // 3 -> 01001010
+ 0x55, // 4 -> 01010101
+ 0x6D, // 5 -> 01101101
+ 0x77, // 6 -> 01110111
+ 0x7F, // 7 -> 01111111
+};
+
+typedef struct
+{
+ SWORD Valprev; // Previous output value
+ SWORD Index; // Index into stepsize table
+}ADPCM_State;
+
+ULONG ToneCycles; // No of tone cycles
+ULONG ToneCyclesReady; // No of tone cycles for ready
+ULONG ClockNext; // Serial clock for next buffer
+
+UBYTE *pSoundPointer; // Pointer to sample in actual sound buffer
+UBYTE *pSoundPointerNext; // Pointer to sample in next sound buffer
+
+UWORD SoundSamplesLeft; // Number of samples left on actual sound buffer
+UWORD SoundSamplesLeftNext; // Number of samples left on next sound buffer
+
+UBYTE SampleBufferNo; // Sample buffer no in use
+
+UBYTE SoundReady; // Sound channel ready (idle)
+UBYTE SoundDivider; // Volume
+
+UWORD MelodyPointer;
+UBYTE CurrentFileFormat; // Hold current playing file type
+
+UBYTE Outdata[2]; // Output buffer used within the ADPCM algorithm
+ADPCM_State State; // Struct holding ADPCM state
+
+#define SOUNDIntEnable {\
+ *AT91C_SSC_IER = AT91C_SSC_ENDTX;\
+ }
+
+#define SOUNDIntDisable {\
+ *AT91C_SSC_IDR = AT91C_SSC_ENDTX;\
+ }
+
+#define SOUNDEnable {\
+ *AT91C_PIOA_PDR = AT91C_PA17_TD; /* Enable TD on PA17 */\
+ }
+
+#define SOUNDDisable {\
+ *AT91C_PIOA_PER = AT91C_PA17_TD; /* Disable TD on PA17 */\
+ }
+
+ULONG SoundSampleRate(UWORD Rate)
+{
+ ULONG Result;
+
+ if (Rate > SAMPLERATE_MAX)
+ {
+ Rate = SAMPLERATE_MAX;
+ }
+ if (Rate < SAMPLERATE_MIN)
+ {
+ Rate = SAMPLERATE_MIN;
+ }
+ Result = ((OSC / (2 * SAMPLEBITS)) / Rate) + 1;
+
+ return (Result);
+}
+
+__ramfunc void CalculateBitstream(SAMPLEWORD *pSampleBuffer,UBYTE Sample)
+{
+ ULONG IntegerMask;
+ ULONG FractionMask;
+ UBYTE Integer;
+ UBYTE Fraction;
+ UBYTE Mask;
+ UBYTE Tmp;
+ SWORD STmp;
+
+ if (SoundDivider)
+ {
+ STmp = Sample;
+ STmp &= 0xFF;
+ STmp -= SAMPLECENTER;
+ STmp >>= (SOUNDVOLUMESTEPS - SoundDivider);
+ STmp += SAMPLECENTER;
+ Sample = (UBYTE)STmp;
+ SOUNDEnable;
+ }
+ else
+ {
+ SOUNDDisable;
+ }
+
+ Tmp = 0;
+ IntegerMask = 0xFFFF0000;
+ Integer = Sample >> SAMPLECONSTANT;
+ Fraction = Sample - (Integer << SAMPLECONSTANT);
+ IntegerMask = 0xFFFFFFFF << (SAMPLEWORDBITS - Integer);
+ FractionMask = (IntegerMask >> 1) | IntegerMask;
+ Mask = FractionPattern[Fraction];
+ while (Tmp < SAMPLEWORDS)
+ {
+ if ((Mask & (0x01 << Tmp)))
+ {
+ *pSampleBuffer = FractionMask;
+ }
+ else
+ {
+ *pSampleBuffer = IntegerMask;
+ }
+ pSampleBuffer++;
+ Tmp++;
+ }
+}
+
+__ramfunc void SscHandler(void)
+{
+ static UBYTE ByteCnt = 0;
+
+ if (SoundSamplesLeft)
+ {
+ if (0 == CurrentFileFormat)
+ {
+ CalculateBitstream(SampleBuffer[SampleBufferNo],*pSoundPointer);
+ *AT91C_SSC_TNPR = (unsigned int)SampleBuffer[SampleBufferNo];
+ *AT91C_SSC_TNCR = SAMPLEWORDS;
+
+ pSoundPointer++;
+ SoundSamplesLeft--;
+ if (!SoundSamplesLeft)
+ {
+ pSoundPointer = pSoundPointerNext;
+ SoundSamplesLeft = SoundSamplesLeftNext;
+ *AT91C_SSC_CMR = ClockNext;
+ SoundSamplesLeftNext = 0;
+ }
+
+ if (++SampleBufferNo >= SAMPLEBUFFERS)
+ {
+ SampleBufferNo = 0;
+ }
+ }
+ else
+ {
+ if (0 == ByteCnt)
+ {
+ SoundADPCMDecoder(*pSoundPointer, Outdata, &State.Valprev, &State.Index);
+ CalculateBitstream(SampleBuffer[SampleBufferNo],Outdata[0]);
+ *AT91C_SSC_TNPR = (unsigned int)SampleBuffer[SampleBufferNo];
+ *AT91C_SSC_TNCR = SAMPLEWORDS;
+
+ if (++SampleBufferNo >= SAMPLEBUFFERS)
+ {
+ SampleBufferNo = 0;
+ }
+
+ ByteCnt++;
+ }
+ else
+ {
+ CalculateBitstream(SampleBuffer[SampleBufferNo],Outdata[1]);
+ *AT91C_SSC_TNPR = (unsigned int)SampleBuffer[SampleBufferNo];
+ *AT91C_SSC_TNCR = SAMPLEWORDS;
+
+ pSoundPointer++;
+ SoundSamplesLeft--;
+ if (!SoundSamplesLeft)
+ {
+ pSoundPointer = pSoundPointerNext;
+ SoundSamplesLeft = SoundSamplesLeftNext;
+ *AT91C_SSC_CMR = ClockNext;
+ SoundSamplesLeftNext = 0;
+ }
+
+ if (++SampleBufferNo >= SAMPLEBUFFERS)
+ {
+ SampleBufferNo = 0;
+ }
+ ByteCnt = 0;
+ }
+ }
+ }
+ else
+ {
+ if (ToneCycles)
+ {
+ ToneCycles--;
+ if (ToneCycles < ToneCyclesReady)
+ {
+ SoundReady = TRUE;
+ }
+ *AT91C_SSC_TNPR = (unsigned int)ToneBuffer;
+ *AT91C_SSC_TNCR = SAMPLETONENO;
+ if (SoundDivider)
+ {
+ SOUNDEnable;
+ }
+ else
+ {
+ SOUNDDisable;
+ }
+ }
+ else
+ {
+ SoundReady = TRUE;
+ SOUNDDisable;
+ SOUNDIntDisable;
+ }
+ }
+}
+
+UBYTE SoundStart(UBYTE *Sound,UWORD Length,UWORD SampleRate, UBYTE NewFileFormat)
+{
+ UBYTE Result = FALSE;
+
+ if (SoundReady == TRUE)
+ {
+ if (Length > 1)
+ {
+ CurrentFileFormat = NewFileFormat;
+ *AT91C_SSC_CMR = SoundSampleRate(SampleRate);
+ pSoundPointer = Sound;
+ SoundSamplesLeft = Length;
+
+ if (0 == CurrentFileFormat)
+ {
+ CalculateBitstream(SampleBuffer[0],*pSoundPointer);
+ *AT91C_SSC_TPR = (unsigned int)SampleBuffer[0];
+ *AT91C_SSC_TCR = SAMPLEWORDS;
+ pSoundPointer++;
+ SoundSamplesLeft--;
+ CalculateBitstream(SampleBuffer[1],*pSoundPointer);
+ *AT91C_SSC_TNPR = (unsigned int)SampleBuffer[1];
+ *AT91C_SSC_TNCR = SAMPLEWORDS;
+ pSoundPointer++;
+ SoundSamplesLeft--;
+ }
+ else
+ {
+ State.Valprev = INIT_PREV_VAL_ADPCM;
+ State.Index = INIT_INDEX_ADPCM;
+ SoundADPCMDecoder(*pSoundPointer, Outdata, &State.Valprev, &State.Index);
+ CalculateBitstream(SampleBuffer[0],Outdata[0]);
+ *AT91C_SSC_TPR = (unsigned int)SampleBuffer[0];
+ *AT91C_SSC_TCR = SAMPLEWORDS;
+ pSoundPointer++;
+ SoundSamplesLeft--;
+ CalculateBitstream(SampleBuffer[1],Outdata[1]);
+ *AT91C_SSC_TNPR = (unsigned int)SampleBuffer[1];
+ *AT91C_SSC_TNCR = SAMPLEWORDS;
+ }
+ SampleBufferNo = 0;
+ SoundReady = FALSE;
+ SOUNDIntEnable;
+ *AT91C_SSC_PTCR = AT91C_PDC_TXTEN;
+ }
+ Result = TRUE;
+ }
+ else
+ {
+ if (!ToneCycles)
+ {
+ if (!SoundSamplesLeftNext)
+ {
+ CurrentFileFormat = NewFileFormat;
+ ClockNext = SoundSampleRate(SampleRate);
+ pSoundPointerNext = Sound;
+ SoundSamplesLeftNext = Length;
+ Result = TRUE;
+ }
+ }
+ }
+
+ return (Result);
+}
+
+UBYTE SoundStop(void)
+{
+ ToneCycles = 0;
+ SOUNDIntDisable;
+ SOUNDDisable;
+ SoundReady = TRUE;
+ SoundSamplesLeft = 0;
+ SoundSamplesLeftNext = 0;
+ MelodyPointer = 0;
+
+ return (TRUE);
+}
+
+void SoundVolume(UBYTE Step)
+{
+ if (Step > SOUNDVOLUMESTEPS)
+ {
+ Step = SOUNDVOLUMESTEPS;
+ }
+ SoundDivider = Step;
+}
+
+void SoundFreq(UWORD Freq,UWORD mS,UBYTE Step)
+{
+ UBYTE Tmp;
+
+ if (mS < DURATION_MIN)
+ {
+ mS = DURATION_MIN;
+ }
+ if (Freq)
+ {
+ if (Freq < FREQUENCY_MIN)
+ {
+ Freq = FREQUENCY_MIN;
+ }
+ if (Freq > FREQUENCY_MAX)
+ {
+ Freq = FREQUENCY_MAX;
+ }
+ if (Step > SOUNDVOLUMESTEPS)
+ {
+ Step = SOUNDVOLUMESTEPS;
+ }
+ }
+ else
+ {
+ Step = 0;
+ Freq = 1000;
+ }
+ SoundDivider = Step;
+ SoundSamplesLeft = 0;
+ SoundSamplesLeftNext = 0;
+ for (Tmp = 0;Tmp < SAMPLETONENO;Tmp++)
+ {
+ ToneBuffer[Tmp] = TonePattern[Step][Tmp];
+ }
+
+ *AT91C_SSC_CMR = (((ULONG)OSC / (2L * 512L)) / ((ULONG)Freq)) + 1L;
+ ToneCycles = ((ULONG)Freq * (ULONG)mS) / 1000L - 1L;
+ ToneCyclesReady = ((ULONG)Freq * (ULONG)2L) / 1000L + 1L;
+
+ *AT91C_SSC_TNPR = (unsigned int)ToneBuffer;
+ *AT91C_SSC_TNCR = SAMPLETONENO;
+ *AT91C_SSC_PTCR = AT91C_PDC_TXTEN;
+ SoundReady = FALSE;
+ SOUNDIntEnable;
+}
+
+UBYTE SoundTone(UBYTE *pMel,UWORD Length,UBYTE Step)
+{
+ UBYTE Result = FALSE;
+ UWORD Freq;
+ UWORD mS;
+
+ if ((SoundReady == TRUE))
+ {
+ if (MelodyPointer <= (Length - 4))
+ {
+ Freq = (UWORD)pMel[MelodyPointer++] << 8;
+ Freq += (UWORD)pMel[MelodyPointer++];
+ mS = (UWORD)pMel[MelodyPointer++] << 8;
+ mS += (UWORD)pMel[MelodyPointer++];
+ SoundFreq(Freq,mS,Step);
+ }
+ else
+ {
+ MelodyPointer = 0;
+ Result = TRUE;
+ }
+ }
+
+ return (Result);
+}
+
+#define SOUNDInit {\
+ SOUNDIntDisable;\
+ SoundReady = TRUE;\
+ MelodyPointer = 0;\
+ *AT91C_PMC_PCER = (1L << AT91C_ID_SSC); /* Enable MCK clock */\
+ *AT91C_PIOA_PER = AT91C_PA17_TD; /* Disable TD on PA17 */\
+ *AT91C_PIOA_ODR = AT91C_PA17_TD;\
+ *AT91C_PIOA_OWDR = AT91C_PA17_TD;\
+ *AT91C_PIOA_MDDR = AT91C_PA17_TD;\
+ *AT91C_PIOA_PPUDR = AT91C_PA17_TD;\
+ *AT91C_PIOA_IFDR = AT91C_PA17_TD;\
+ *AT91C_PIOA_CODR = AT91C_PA17_TD;\
+ *AT91C_PIOA_IDR = AT91C_PA17_TD;\
+ *AT91C_SSC_CR = AT91C_SSC_SWRST;\
+ AT91C_AIC_SVR[AT91C_ID_SSC] = (unsigned int)SscHandler;\
+ AT91C_AIC_SMR[AT91C_ID_SSC] = AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED; /* Set priority */\
+ *AT91C_SSC_TCMR = AT91C_SSC_CKS_DIV + AT91C_SSC_CKO_CONTINOUS + AT91C_SSC_START_CONTINOUS;\
+ *AT91C_SSC_TFMR = (SAMPLEWORDBITS - 1) + ((SAMPLEWORDS & 0xF) << 8) + AT91C_SSC_MSBF;\
+ *AT91C_SSC_CR = AT91C_SSC_TXEN; /* TX enable */\
+ *AT91C_AIC_ICCR = (1L << AT91C_ID_SSC); /* Clear interrupt */\
+ *AT91C_AIC_IECR = (1L << AT91C_ID_SSC); /* Enable int. controller */\
+ }
+
+#define SOUNDVolume(V) SoundVolume((UBYTE)V)
+
+#define SOUNDReady SoundReady
+
+#define SOUNDStart(pSnd,Lng,SR,FT) SoundStart(pSnd,Lng,SR,FT)
+
+#define SOUNDStop SoundStop()
+
+#define SOUNDTone(pMel,Lng,Vol) SoundTone(pMel,Lng,Vol)
+
+#define SOUNDFreq(Freq,Duration,Vol) SoundFreq(Freq,Duration,Vol)
+
+#define SOUNDExit {\
+ SOUNDIntDisable;\
+ SOUNDDisable;\
+ *AT91C_AIC_IDCR = (1L << AT91C_ID_SSC);\
+ }
+
+
+#endif
diff --git a/AT91SAM7S256/Source/d_sound_adpcm.r b/AT91SAM7S256/Source/d_sound_adpcm.r
new file mode 100644
index 0000000..03e16b7
--- /dev/null
+++ b/AT91SAM7S256/Source/d_sound_adpcm.r
@@ -0,0 +1,156 @@
+//Playback of compressed sound files. This additional feature is being brought to you under the following license.
+//Please adhere to its terms.
+//The original code includes minor changes to function correctly within the LEGO MINDSTORMS NXT embedded system,
+//but the main architecture are implemented as within the original code.
+
+//***********************************************************
+//Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
+//Netherlands.
+//
+// All Rights Reserved
+//
+//Permission to use, copy, modify, and distribute this software and its
+//documentation for any purpose and without fee is hereby granted,
+//provided that the above copyright notice appear in all copies and that
+//both that copyright notice and this permission notice appear in
+//supporting documentation, and that the names of Stichting Mathematisch
+//Centrum or CWI not be used in advertising or publicity pertaining to
+//distribution of the software without specific, written prior permission.
+//
+//STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+//THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+//FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+//FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+//WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+//ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+//OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+//******************************************************************/
+
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dkflebun $
+//
+// Revision date $Date:: 5-02-07 13:36 $
+//
+// Filename $Workfile:: d_sound_adpcm.r $
+//
+// Version $Revision:: 1 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_sound_adpcm.r $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+static SWORD IndexTable[16] =
+{
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8,
+};
+
+static SWORD StepsizeTable[89] =
+{
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+__ramfunc void SoundADPCMDecoder(UBYTE Indata, UBYTE *Outdata, SWORD *pStateValprev, SWORD *pStateIndex)
+{
+ SWORD Step; // Stepsize
+ SWORD Valprev; // Virtual previous output value
+ SWORD Vpdiff; // Current change to valprev
+ SWORD Index; // Current step change index
+ UBYTE *pOut; // Output buffer pointer
+ UBYTE Sign; // Current adpcm sign bit
+ UBYTE Delta; // Current adpcm output value
+ UBYTE Bufferstep; // Toggle between High og Low nibble
+ UBYTE Len; // Nibble Counter
+
+ pOut = Outdata;
+
+ Valprev = *pStateValprev;
+ Index = *pStateIndex;
+ Step = StepsizeTable[Index];
+
+ Bufferstep = 0;
+ Len = 2;
+
+ for (; Len > 0 ; Len--) //Step 1 - get the delta value and compute next index
+ {
+ if(Bufferstep)
+ {
+ Delta = Indata & 0x0F;
+ }
+ else
+ {
+ Delta = (Indata >> 4) & 0x0F;
+ }
+ Bufferstep = !Bufferstep;
+
+ Index += IndexTable[Delta]; //Step 2 - Find new index value (for later)
+ if (Index < 0)
+ {
+ Index = 0;
+ }
+ else
+ {
+ if (Index > 88)
+ {
+ Index = 88;
+ }
+ }
+
+ Sign = Delta & 8; //Step 3 - Separate sign and magnitude
+ Delta = Delta & 7;
+
+ Vpdiff = Step >> 3; //Step 4 - Compute difference and new predicted value
+
+ if (Delta & 4)
+ {
+ Vpdiff += Step;
+ }
+ if (Delta & 2)
+ {
+ Vpdiff += Step>>1;
+ }
+ if (Delta & 1)
+ {
+ Vpdiff += Step>>2;
+ }
+
+ if (Sign)
+ Valprev -= Vpdiff;
+ else
+ Valprev += Vpdiff;
+
+ if (Valprev > 255) //Step 5 - clamp output value
+ {
+ Valprev = 255;
+ }
+ else
+ {
+ if (Valprev < 0)
+ {
+ Valprev = 0;
+ }
+ }
+ Step = StepsizeTable[Index]; //Step 6 - Update step value
+ *pOut++ = (UBYTE)Valprev; //Step 7 - Output value
+ }
+ *pStateValprev = Valprev; //State.Valprev = Valprev;
+ *pStateIndex = Index; //State.Index = Index;
+}
+
+#endif
diff --git a/AT91SAM7S256/Source/d_timer.c b/AT91SAM7S256/Source/d_timer.c
new file mode 100644
index 0000000..7c38aed
--- /dev/null
+++ b/AT91SAM7S256/Source/d_timer.c
@@ -0,0 +1,42 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:18 $
+//
+// Filename $Workfile:: d_timer.c $
+//
+// Version $Revision:: 3 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_timer.c $
+//
+// Platform C
+//
+
+
+#include "stdconst.h"
+#include "m_sched.h"
+#include "d_timer.h"
+#include "d_timer.r"
+
+
+void dTimerInit(void)
+{
+ TIMERInit;
+}
+
+
+ULONG dTimerRead(void)
+{
+ ULONG Tmp;
+
+ TIMERRead(Tmp);
+
+ return (Tmp);
+}
+
+
+void dTimerExit(void)
+{
+ TIMERExit;
+}
+
diff --git a/AT91SAM7S256/Source/d_timer.h b/AT91SAM7S256/Source/d_timer.h
new file mode 100644
index 0000000..bf01b25
--- /dev/null
+++ b/AT91SAM7S256/Source/d_timer.h
@@ -0,0 +1,26 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:18 $
+//
+// Filename $Workfile:: d_timer.h $
+//
+// Version $Revision:: 2 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_timer.h $
+//
+// Platform C
+//
+
+
+#ifndef D_TIMER
+#define D_TIMER
+
+void dTimerInit(void);
+ULONG dTimerRead(void);
+void dTimerExit(void);
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/d_timer.r b/AT91SAM7S256/Source/d_timer.r
new file mode 100644
index 0000000..91e9f7b
--- /dev/null
+++ b/AT91SAM7S256/Source/d_timer.r
@@ -0,0 +1,56 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:18 $
+//
+// Filename $Workfile:: d_timer.r $
+//
+// Version $Revision:: 11 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_timer.r $
+//
+// Platform C
+//
+
+
+#ifdef SAM7S256
+
+
+#define MS_1_TIME ((OSC/16)/1000)
+
+static ULONG TimerValue;
+static ULONG Timer1mS;
+
+/* PIT timer is used as main timer - timer interval is 1mS */
+
+#define TIMERInit TimerValue = ((*AT91C_PITC_PIIR) & AT91C_PITC_CPIV);\
+ Timer1mS = 0
+
+#define TIMERRead(V) if (MS_1_TIME < ((((*AT91C_PITC_PIIR) & AT91C_PITC_CPIV) - TimerValue) & AT91C_PITC_CPIV))\
+ {\
+ TimerValue += MS_1_TIME;\
+ TimerValue &= AT91C_PITC_CPIV;\
+ Timer1mS++;\
+ }\
+ V = Timer1mS
+
+#define TIMERExit
+
+
+
+#endif //SAM7S256
+
+
+
+#ifdef _WINDOWS
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#define TIMERInit timeBeginPeriod(1);
+
+#define TIMERRead(V) (V) = timeGetTime();
+
+#define TIMERExit timeEndPeriod(1);
+
+#endif //_WINDOWS
diff --git a/AT91SAM7S256/Source/d_usb.c b/AT91SAM7S256/Source/d_usb.c
new file mode 100644
index 0000000..b4b92f4
--- /dev/null
+++ b/AT91SAM7S256/Source/d_usb.c
@@ -0,0 +1,946 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dkpechri $
+//
+// Revision date $Date:: 19-07-06 10:02 $
+//
+// Filename $Workfile:: d_usb.c $
+//
+// Version $Revision:: 32 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_usb.c $
+//
+// Platform C
+//
+
+#include "stdconst.h"
+#include "m_sched.h"
+#include "d_usb.h"
+#include "d_usb.r"
+
+#define ENDPOINT_OUT 1 // HOST write
+#define ENDPOINT_OUT_SIZE 64
+#define ENDPOINT_IN 2 // HOST read
+#define ENDPOINT_IN_SIZE 64
+
+#define AT91C_UDP_ISR ((AT91_REG *) 0xFFFB001C) // (UDP) Interrupt Status Register
+#define AT91C_RSTC_URSTEN ((unsigned int) 0x1 << 0) // (RSTC) User Reset Enable
+
+ // Endpoint Control and Status Registers
+#define AT91C_UDP_CSR0 ((AT91_REG *) 0xFFFB0030) // Endpoint 0 Control and Status Register
+#define AT91C_UDP_CSR1 ((AT91_REG *) 0xFFFB0034) // Endpoint 1 Control and Status Register
+#define AT91C_UDP_CSR2 ((AT91_REG *) 0xFFFB0038) // Endpoint 2 Control and Status Register
+#define AT91C_UDP_CSR3 ((AT91_REG *) 0xFFFB003C) // Endpoint 3 Control and Status Register
+
+ // Endpoint FIFO Data Registers
+#define AT91C_UDP_FDR0 ((AT91_REG *) 0xFFFB0050) // Endpoint 0 FIFO Data Register
+#define AT91C_UDP_FDR1 ((AT91_REG *) 0xFFFB0054) // Endpoint 1 FIFO Data Register
+#define AT91C_UDP_FDR2 ((AT91_REG *) 0xFFFB0058) // Endpoint 2 FIFO Data Register
+#define AT91C_UDP_FDR3 ((AT91_REG *) 0xFFFB005C) // Endpoint 3 FIFO Data Register
+
+const UBYTE DeviceDescriptor[] = {
+ /* Device descriptor */
+ 0x12, // bLength, size of this descriptor = 18 entries
+ 0x01, // bDescriptorType = 1 = DEVICE
+ 0x00, // bcdUSBL, USB spec. vers. 2.0
+ 0x02, // bcdUSBH, -
+ 0x00, // bDeviceClass
+ 0x00, // bDeviceSubclass
+ 0x00, // bDeviceProtocol
+ 0x08, // bMaxPacketSize0, EndPointZero packet size = 8
+ 0x94, // idVendorL, LEGO Group
+ 0x06, // idVendorH, -
+ 0x02, // idProductL, LEGO USB IR Tower = 0x01
+ 0x00, // idProductH, -
+ 0x00, // bcdDeviceL, device is version (zero)
+ 0x00, // bcdDeviceH, -
+ 0x00, // iManufacturer, index of string descriptor describing manufacturer
+ 0x00, // iProduct, index of string descriptor describing product
+ 0x01, // iSerialNumber, index of string descriptor describing the device's
+ // serial no.
+ 0x01 // bNumConfigs, number of possible configurations (only one)
+};
+
+/* USB standard request codes */
+
+#define STD_GET_STATUS_ZERO 0x0080
+#define STD_GET_STATUS_INTERFACE 0x0081
+#define STD_GET_STATUS_ENDPOINT 0x0082
+
+#define STD_CLEAR_FEATURE_ZERO 0x0100
+#define STD_CLEAR_FEATURE_INTERFACE 0x0101
+#define STD_CLEAR_FEATURE_ENDPOINT 0x0102
+
+#define STD_SET_FEATURE_ZERO 0x0300
+#define STD_SET_FEATURE_INTERFACE 0x0301
+#define STD_SET_FEATURE_ENDPOINT 0x0302
+
+#define STD_SET_ADDRESS 0x0500
+#define STD_GET_DESCRIPTOR 0x0680
+#define STD_SET_DESCRIPTOR 0x0700
+#define STD_GET_CONFIGURATION 0x0880
+#define STD_SET_CONFIGURATION 0x0900
+#define STD_GET_INTERFACE 0x0A81
+#define STD_SET_INTERFACE 0x0B01
+#define STD_SYNCH_FRAME 0x0C82
+
+/* USB constants, masks etc. */
+
+#define END_OF_BUS_RESET ((unsigned int) 0x1 << 12)
+#define SUSPEND_INT ((unsigned int) 0x1 << 8)
+#define SUSPEND_RESUME ((unsigned int) 0x1 << 9)
+#define WAKEUP ((unsigned int) 0x1 << 13)
+
+//USB spec allows 500ms for control transfers
+#define USB_MAX_TIMEOUT 500
+
+static UBYTE UsbHandleList[MAX_HANDLES];
+static UBYTE UsbHandleCnt;
+static UWORD RequestedData;
+static UBYTE BrickNameKnown;
+enum
+{
+ USB_NOT_CONFIGURED,
+ USB_CONFIGURED,
+ USB_CONFIGURED_BUT_SUSPENDED
+};
+static UBYTE UsbConnectionStates;
+
+
+const UBYTE ConfigurationDescriptor[] = {
+ /* ============== CONFIGURATION 1 =========== */
+ /* Configuration 1 descriptor */
+ 0x09, // bLength, descriptor size in bytes
+ 0x02, // bDescriptorType, The constant Configuration
+ 0x20, // wTotalLengthL for 2 EP + Control
+ 0x00, // wTotalLengthH -
+ 0x01, // bNumInterfaces, Number of interfaces in the configuration
+ 0x01, // bConfigurationValue, Identifier for
+ // Set_Configuration and Get_Configuration requests
+ 0x00, // iConfiguration, Index of string descriptor for the configuration
+ 0xC0, // bmAttributes, Bit 7 shall always be set. See e.g. page 108 in the book:
+ // "USB Complete" by Jan Axelson. June 2001
+ // Self powered only bit 6 = 1 (zero = buspowered USB 1.1 and up)
+ 0x00, // MaxPower, power required (mA./2) We're SELF-POWERED, so ZERO
+
+ /* Interface Descriptor */
+ 0x09, // bLength, descriptor size in bytes
+ 0x04, // bDescriptorType, the constant 0x04 = "INTERFACE"
+ 0x00, // bInterfaceNumber, No. identifying this interface
+ 0x00, // bAlternateSetting, value used to get an alternative interface
+ 0x02, // bNumEndpoints, No. of supported endpoints in addition to endpoint 0
+ 0xFF, // bInterfaceClass, Specifies the class code = VENDOR Specific
+ 0xFF, // bInterfaceSubclass, Specifies the subclass code = VENDOR Specific
+ 0xFF, // bInterfaceProtocol, protocol code = VENDOR Specific
+ 0x00, // iInterface, index of string descriptor for the interface
+
+ /* Endpoint 1 descriptor */
+ 0x07, // bLength, descriptor length incl. this = 7
+ 0x05, // bDescriptorType
+ 0x01, // bEndpointAddress, Endpoint 01 - OUT
+ 0x02, // bmAttributes BULK
+ ENDPOINT_OUT_SIZE, // wMaxPacketSize
+ 0x00, // -
+ 0x00, // bInterval
+
+ /* Endpoint 2 descriptor */
+ 0x07, // bLength, descriptor length incl. this = 7
+ 0x05, // bDescriptorType
+ 0x82, // bEndpointAddress, Endpoint 02 - IN
+ 0x02, // bmAttributes BULK
+ ENDPOINT_IN_SIZE, // wMaxPacketSize
+ 0x00, // -
+ 0x00 // bInterval
+};
+
+UBYTE SerialNumberDescriptor[] =
+{
+ 0x1A, // bLength, descriptor length incl. this = 16 bytes
+ 0x03, // bDescriptorType
+
+ 0x31, 0x00, // MSD of Lap (Lap[2,3]) in UNICode
+ 0x32, 0x00, // Lap[4,5]
+ 0x33, 0x00, // Lap[6,7]
+ 0x34, 0x00, // Lap[8,9]
+ 0x35, 0x00, // Lap[10,11]
+ 0x36, 0x00, // Lap[12,13]
+ 0x37, 0x00, // Lap[14,15]
+ 0x38, 0x00, // LSD of Lap (Lap[16,17]) in UNICode
+
+ 0x30, 0x00, // MSD of Nap (Nap[18,19]) in UNICode
+ 0x30, 0x00, // LSD of Nap (Nap[20,21]) in UNICode
+
+ 0x39, 0x00, // MSD of Uap in UNICode
+ 0x30, 0x00 // LSD of Uap in UNICode
+};
+
+const UBYTE LangIdDescriptor[] =
+{
+ 0x04, // Length
+ 0x03, // Type, 3 = CONSTANT String
+ 0x09, // English
+ 0x04 // subcode = U.S. English
+};
+
+static UCHAR CurrentConfiguration; // Configured or not. We've only 1 conf. so... Boolean
+static ULONG CurrentReceiveBank; // Used for keep track of the PING-PONG buffers
+
+ULONG g_UsbTimeoutCounter;
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+void dUsbDisconnect(void)
+{
+ USBDisconnect;
+}
+
+void dUsbConnect(void)
+{
+ USBConnect;
+}
+
+void dUsbStartTimeoutTimer(void)
+{
+ g_UsbTimeoutCounter = 0;
+
+ USBGetActualTime;
+}
+
+// A longer version of the USB timer.
+// Table 7-14 of the USB 2.0 spec allows up to 500ms for standard request completion.
+UBYTE dUsbTimedOut(void)
+{
+ if(USBTimedOut)
+ {
+ g_UsbTimeoutCounter++;
+
+ USBGetActualTime;
+ }
+
+ return (g_UsbTimeoutCounter >= USB_MAX_TIMEOUT) ? TRUE : FALSE;
+}
+
+
+UBYTE ConvertHighToHex(UBYTE TempChar)
+{
+ TempChar = (TempChar >> 4) & 0x0F;
+ if (TempChar > 0x09)
+ TempChar += 0x37;
+ else
+ TempChar += 0x30;
+ return TempChar;
+}
+
+UBYTE ConvertLowToHex(UBYTE TempChar)
+{
+ TempChar &= 0x0F;
+ if (TempChar > 0x09)
+ TempChar += 0x37;
+ else
+ TempChar += 0x30;
+ return TempChar;
+}
+
+void dUsbStoreBtAddress(UBYTE *pBtAddress)
+{
+ UBYTE NoToConvert;
+
+ // make the Lap human readable (hmmm Hexadecimal)
+ NoToConvert = *pBtAddress++;
+ SerialNumberDescriptor[2] = ConvertHighToHex(NoToConvert);
+ SerialNumberDescriptor[4] = ConvertLowToHex(NoToConvert);
+
+ NoToConvert = *pBtAddress++;
+ SerialNumberDescriptor[6] = ConvertHighToHex(NoToConvert);
+ SerialNumberDescriptor[8] = ConvertLowToHex(NoToConvert);
+
+ NoToConvert = *pBtAddress++;
+ SerialNumberDescriptor[10] = ConvertHighToHex(NoToConvert);
+ SerialNumberDescriptor[12] = ConvertLowToHex(NoToConvert);
+
+ NoToConvert = *pBtAddress++;
+ SerialNumberDescriptor[14] = ConvertHighToHex(NoToConvert);
+ SerialNumberDescriptor[16] = ConvertLowToHex(NoToConvert);
+
+ // make the Uap human readable (hmmm Hexadecimal)
+ NoToConvert = *pBtAddress++;
+ SerialNumberDescriptor[18] = ConvertHighToHex(NoToConvert);
+ SerialNumberDescriptor[20] = ConvertLowToHex(NoToConvert);
+
+ // make the Nap human readable (hmmm Hexadecimal)
+ NoToConvert = *pBtAddress++;
+ SerialNumberDescriptor[22] = ConvertHighToHex(NoToConvert);
+ SerialNumberDescriptor[24] = ConvertLowToHex(NoToConvert);
+
+ USBConnect; // We're ready to participate in the real world
+ BrickNameKnown = TRUE; // OK for referencing :-)
+}
+
+
+ULONG dUsbRead(UBYTE *pData, ULONG Length)
+{
+ ULONG PacketSize, NumberOfBytesReceived;
+
+ NumberOfBytesReceived = 0;
+
+ while (Length) // Wished read size from user (Max length)
+ {
+ if ( !(BrickNameKnown)) // Right Brick???
+ break;
+
+ if ( !(dUsbIsConfigured()) )
+ break; // Not configured - no time to waste
+
+ if ( (*AT91C_UDP_CSR1) & CurrentReceiveBank ) // Data packet rx'ed in Current bank?
+ {
+
+ PacketSize = MIN((*AT91C_UDP_CSR1) >> 16, Length); // Normalize number of bytes available in FIFO
+ Length -= PacketSize; // Rest of data to receive
+
+ if (PacketSize < ENDPOINT_OUT_SIZE) // If data less, we only have one loop
+ Length = 0;
+
+ while(PacketSize--) // While more data in this very packet...
+ pData[NumberOfBytesReceived++] = *AT91C_UDP_FDR1; // Fill in buffer
+
+ *AT91C_UDP_CSR1 &= ~(CurrentReceiveBank); // Reset current bank pointer
+
+ if (CurrentReceiveBank == AT91C_UDP_RX_DATA_BK0) // Current Receive Bank 0?
+ CurrentReceiveBank = AT91C_UDP_RX_DATA_BK1; // We better use Bank 1
+ else
+ CurrentReceiveBank = AT91C_UDP_RX_DATA_BK0; // Okay, go for Bank 0 :-)
+
+ }
+
+ else Length = 0; // Leave and let's use the CPU cycles in a better way
+
+ }
+
+ return NumberOfBytesReceived; // Size of actually received stuff
+
+}
+
+ULONG dUsbWrite( const UBYTE *pData, ULONG Length)
+{
+ ULONG CharsEachTx = 0;
+
+ // Send the very first (or only) packet
+ CharsEachTx = MIN(Length, ENDPOINT_IN_SIZE); // First transmission size
+ Length -= CharsEachTx; // Adjust the rest of transmission size
+
+ while (CharsEachTx--) // While more chars in this chunk
+ *AT91C_UDP_FDR2 = *pData++; // Get rid off it one by one
+ // Pushing the data into the UDP TX-fifo
+ *AT91C_UDP_CSR2 |= AT91C_UDP_TXPKTRDY; // Signal "DO THE TX" the stuff is delivered...
+
+ while (Length) // While more bytes (I.e. packets) ín total transmission
+ { // Start filling the second bank
+
+ CharsEachTx = MIN(Length, ENDPOINT_IN_SIZE);
+ Length -= CharsEachTx; // Adjust total length
+
+ while (CharsEachTx--) // While more chars in this chunk
+ *AT91C_UDP_FDR2 = *pData++;
+
+ dUsbStartTimeoutTimer();
+ while ( !((*AT91C_UDP_CSR2) & AT91C_UDP_TXCOMP) ) // Wait for the the first bank to be sent
+ if (dUsbTimedOut() || !(dUsbIsConfigured()) ) // Communication down..... Bail out
+ return Length; // Invalid function - return job length not done
+
+ (*AT91C_UDP_CSR2) &= ~(AT91C_UDP_TXCOMP); // Reset transmit interrupt flag
+
+ while ((*AT91C_UDP_CSR2) & AT91C_UDP_TXCOMP); // Wait until flag (H/W) is reset
+
+ (*AT91C_UDP_CSR2) |= AT91C_UDP_TXPKTRDY; // We're ready to send next bank
+
+ } // Loop while bytes to tx
+
+ dUsbStartTimeoutTimer(); // Arm the timeout timing
+ while ( !((*AT91C_UDP_CSR2) & AT91C_UDP_TXCOMP) ) // Wait for transmission to complete
+ if ( !(dUsbIsConfigured()) || dUsbTimedOut()) // Communication down..... Bail out
+ return Length; // Invalid function - return job length not done
+
+ (*AT91C_UDP_CSR2) &= ~(AT91C_UDP_TXCOMP); // Reset Interrupt flag
+
+ while ((*AT91C_UDP_CSR2) & AT91C_UDP_TXCOMP); // Wait for H/W to settle.....
+
+ return Length; // Return byte count NOT x-ferred
+
+}
+
+static void dUsbSendStall(void)
+{
+ (*AT91C_UDP_CSR0) |= AT91C_UDP_FORCESTALL; // Set STALL condition
+ while ( !((*AT91C_UDP_CSR0) & AT91C_UDP_ISOERROR) ); // Wait until stall ack'ed
+
+ (*AT91C_UDP_CSR0) &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR); // Reset again
+ while ((*AT91C_UDP_CSR0) & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)); // Wait until H/W really reset
+}
+
+static void dUsbSendZeroLengthPackage(void)
+{
+ // Signal that buffer is ready to send
+ (*AT91C_UDP_CSR0) |= AT91C_UDP_TXPKTRDY;
+
+ dUsbStartTimeoutTimer();
+
+ // Wait for ACK handshake from host
+ while ( !((*AT91C_UDP_CSR0) & AT91C_UDP_TXCOMP) && !dUsbTimedOut());
+ // Clear handshake flag
+ (*AT91C_UDP_CSR0) &= ~(AT91C_UDP_TXCOMP);
+ while ((*AT91C_UDP_CSR0) & AT91C_UDP_TXCOMP);
+}
+
+static void dUsbSendViaControl(const UBYTE *pData, ULONG Length)
+{
+ ULONG BytesToTx = 0;
+ AT91_REG Temp_Csr;
+ UBYTE HaveToTxZeroLength = FALSE;
+ UBYTE ZeroCouldBeNeeded = FALSE;
+
+ // If the amount of data requested is more than what can be sent, a 0-length
+ // packet may be required
+ if (RequestedData > Length)
+ {
+ ZeroCouldBeNeeded = TRUE; // Exact same size would be interpreted as EOP @ host
+ }
+
+ do
+ {
+ // The endpoint size is 8 bytes. Limit each data phase to 8 bytes.
+
+ BytesToTx = MIN(Length, 8);
+ Length -= BytesToTx;
+
+ // If this is the last data phase containing data, but the host requested
+ // more, a 0-byte packet will be needed to terminate the data phase.
+ if(ZeroCouldBeNeeded && (Length == 0) && (BytesToTx == 8))
+ {
+ HaveToTxZeroLength = TRUE;
+ }
+
+ // Copy data to endpoint buffer
+ while (BytesToTx--)
+ {
+ (*AT91C_UDP_FDR0) = *pData++;
+ }
+
+ // Signal that buffer is ready to send
+ (*AT91C_UDP_CSR0) |= AT91C_UDP_TXPKTRDY;
+
+ dUsbStartTimeoutTimer();
+
+ // Wait for ACK handshake from host
+ do
+ {
+ Temp_Csr = (*AT91C_UDP_CSR0);
+
+ // Return if the status phase occurs before the packet is accepted
+ if (Temp_Csr & AT91C_UDP_RX_DATA_BK0)
+ {
+ // Clear the PKTRDY flag
+ (*AT91C_UDP_CSR0) &= ~(AT91C_UDP_TXPKTRDY);
+ // Clear the status phase flag
+ (*AT91C_UDP_CSR0) &= ~(AT91C_UDP_RX_DATA_BK0);
+ return;
+ }
+ }
+ while (!(Temp_Csr & AT91C_UDP_TXCOMP) && !dUsbTimedOut());
+
+ // Clear handshake flag
+ (*AT91C_UDP_CSR0) &= ~(AT91C_UDP_TXCOMP);
+
+ while ((*AT91C_UDP_CSR0) & AT91C_UDP_TXCOMP);
+
+ } while (Length);
+
+ if(HaveToTxZeroLength)
+ {
+ dUsbSendZeroLengthPackage();
+ }
+
+ dUsbStartTimeoutTimer();
+
+ // Wait for Status Phase
+ while(!((*AT91C_UDP_CSR0) & AT91C_UDP_RX_DATA_BK0) && !dUsbTimedOut());
+ // Clear flag
+ (*AT91C_UDP_CSR0) &= ~(AT91C_UDP_RX_DATA_BK0);
+}
+
+static void dUsbEnumerate(void)
+{
+ UBYTE bmRequestType, bRequest;
+ UWORD wValue, wIndex, wLength, wStatus;
+
+ if ( !((*AT91C_UDP_CSR0) & AT91C_UDP_RXSETUP) ) // No setup package available
+ return;
+ // Bytes are popped from the FIFO one by one
+
+ bmRequestType = *AT91C_UDP_FDR0;
+ bRequest = *AT91C_UDP_FDR0;
+ wValue = ((*AT91C_UDP_FDR0) & 0xFF);
+ wValue |= ((*AT91C_UDP_FDR0) << 8);
+ wIndex = ((*AT91C_UDP_FDR0) & 0xFF);
+ wIndex |= ((*AT91C_UDP_FDR0) << 8);
+ wLength = ((*AT91C_UDP_FDR0) & 0xFF);
+ wLength |= ((*AT91C_UDP_FDR0) << 8);
+
+ if (bmRequestType & 0x80) // If a DEVICE-TO-HOST request
+ {
+ *AT91C_UDP_CSR0 |= AT91C_UDP_DIR; // Enables data IN transaction in the control data stage
+ while ( !((*AT91C_UDP_CSR0) & AT91C_UDP_DIR) ); // Repeat until the DIR bit is set
+ }
+
+ *AT91C_UDP_CSR0 &= ~AT91C_UDP_RXSETUP; // Device firmware has read the setup data in FIFO
+ while ( ((*AT91C_UDP_CSR0) & AT91C_UDP_RXSETUP) ); // Wait until bit cleared
+
+ // Handle supported standard device request from Table 9-3 in USB specification Rev 2.0
+
+ switch ((bRequest << 8) | bmRequestType)
+ {
+ case STD_GET_DESCRIPTOR:
+
+ RequestedData = wLength;
+
+ if (wValue == 0x100) // Return Device Descriptor
+ {
+ if (sizeof(DeviceDescriptor) > wLength)
+ {
+ dUsbSendViaControl(DeviceDescriptor, wLength);
+ }
+ else
+ {
+ dUsbSendViaControl(DeviceDescriptor, sizeof(DeviceDescriptor));
+ }
+ }
+ else if (wValue == 0x200) // Return Configuration Descriptor
+ {
+ if (sizeof(ConfigurationDescriptor) > wLength)
+ {
+ dUsbSendViaControl(ConfigurationDescriptor, wLength);
+ }
+ else
+ {
+ dUsbSendViaControl(ConfigurationDescriptor, sizeof(ConfigurationDescriptor));
+ }
+ }
+ else if ((wValue & 0xF00) == 0x300)
+ {
+ switch(wValue & 0xFF)
+ {
+ case 0x00:
+ if ((sizeof(LangIdDescriptor)) > wLength)
+ {
+ dUsbSendViaControl(LangIdDescriptor, wLength);
+ }
+ else
+ {
+ dUsbSendViaControl(LangIdDescriptor, sizeof(LangIdDescriptor));
+ }
+ break;
+
+ case 0x01:
+ if ((sizeof(SerialNumberDescriptor)) > wLength)
+ {
+ dUsbSendViaControl(SerialNumberDescriptor, wLength);
+ }
+ else
+ {
+ dUsbSendViaControl(SerialNumberDescriptor, sizeof(SerialNumberDescriptor));
+ }
+ break;
+
+ default:
+ dUsbSendStall(); // Illegal request :-(
+ break;
+ }
+ }
+ else
+ dUsbSendStall(); // Illegal request :-(
+
+ break;
+
+ case STD_SET_ADDRESS:
+
+ // Status IN transfer
+ (*AT91C_UDP_CSR0) |= AT91C_UDP_TXPKTRDY;
+
+ dUsbStartTimeoutTimer();
+
+ while((*AT91C_UDP_CSR0) & AT91C_UDP_TXPKTRDY && !dUsbTimedOut());
+
+ *AT91C_UDP_FADDR = (AT91C_UDP_FEN | wValue); // Set device address. No check for invalid address.
+ // Function endpoint enabled.
+ *AT91C_UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0; // If Device address != 0 then flag device
+ // in ADDRESS STATE
+ break;
+
+ case STD_SET_CONFIGURATION:
+
+ CurrentConfiguration = wValue; // Low byte of wValue = wanted configuration
+ UsbConnectionStates = USB_CONFIGURED;
+ dUsbSendZeroLengthPackage(); // Signal request processed OK
+
+ *AT91C_UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; // If wanted configuration != 0
+
+ *AT91C_UDP_CSR1 = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0; // Endpoint 1 enabled and set as BULK OUT
+ *AT91C_UDP_CSR2 = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0; // Endpoint 2 enabled and set as BULK IN
+ *AT91C_UDP_CSR3 = (wValue) ? (AT91C_UDP_EPTYPE_INT_IN) : 0; // Endpoint 3 disabled and set as INTERRUPT IN
+
+ break;
+
+ case STD_GET_CONFIGURATION: // The actual configuration value is sent to HOST
+
+ RequestedData = sizeof(CurrentConfiguration);
+
+ dUsbSendViaControl((UBYTE *) &(CurrentConfiguration), sizeof(CurrentConfiguration));
+
+ break;
+
+ case STD_GET_STATUS_ZERO:
+
+ wStatus = 0x01; // Atmel has a 0x00, but we're not BUS-powered
+ RequestedData = sizeof(wStatus);
+
+ dUsbSendViaControl((UBYTE *) &wStatus, sizeof(wStatus));
+
+ break;
+
+ case STD_GET_STATUS_INTERFACE: // Everything reset to zero (reserved)
+
+ wStatus = 0;
+ RequestedData = sizeof(wStatus);
+
+ dUsbSendViaControl((UBYTE *) &wStatus, sizeof(wStatus));
+
+ break;
+
+ case STD_GET_STATUS_ENDPOINT:
+
+ wStatus = 0;
+ RequestedData = sizeof(wStatus);
+ wIndex &= 0x0F; // Mask the endpoint #
+
+ if (((*AT91C_UDP_GLBSTATE) & AT91C_UDP_CONFG) && (wIndex <= 3)) // If device in CONFIGURED state
+ { // and ENDPOINT selected in valid range
+
+ switch (wIndex)
+ {
+
+ case 1: wStatus = ((*AT91C_UDP_CSR1) & AT91C_UDP_EPEDS) ? 0 : 1; // If an endpoint is halted, the HALT
+ // feature is set to 1, else reset
+ break;
+
+ case 2: wStatus = ((*AT91C_UDP_CSR2) & AT91C_UDP_EPEDS) ? 0 : 1;
+
+ break;
+
+ case 3: wStatus = ((*AT91C_UDP_CSR3) & AT91C_UDP_EPEDS) ? 0 : 1;
+
+ break;
+ default:
+ // We'll never come here, but we'll never say never.......
+ break;
+ }
+
+ dUsbSendViaControl((UBYTE *) &wStatus, sizeof(wStatus));
+
+ }
+
+ else if (((*AT91C_UDP_GLBSTATE) & AT91C_UDP_FADDEN) && (wIndex == 0))
+ {
+ wStatus = ((*AT91C_UDP_CSR0) & AT91C_UDP_EPEDS) ? 0 : 1; // Return 1 if device in ADRESSED state
+
+ dUsbSendViaControl((UBYTE *) &wStatus, sizeof(wStatus));
+ }
+ else
+
+ dUsbSendStall(); // Illegal request :-(
+
+ break;
+
+ case STD_SET_FEATURE_ZERO:
+
+ dUsbSendStall(); // Illegal request :-(
+
+ break;
+
+ case STD_SET_FEATURE_INTERFACE:
+
+ dUsbSendZeroLengthPackage(); // TextBook
+
+ break;
+
+ case STD_SET_FEATURE_ENDPOINT:
+
+ wIndex &= 0x0F;
+
+ if ((wValue == 0) && wIndex && (wIndex <= 3)) // Feature Selector = 0 ENDPOINT HALT and
+ { // endpoint isolated and validated
+
+ switch (wIndex)
+ {
+
+ case 1: (*AT91C_UDP_CSR1) = 0;
+
+ break;
+
+ case 2: (*AT91C_UDP_CSR2) = 0;
+
+ break;
+
+ case 3: (*AT91C_UDP_CSR3) = 0;
+
+ break;
+
+ default:
+ // We'll never come here, but we'll never say never.......
+ break;
+
+ }
+
+ dUsbSendZeroLengthPackage();
+
+ }
+ else
+
+ dUsbSendStall(); // Illegal request :-(
+
+ break;
+
+ case STD_CLEAR_FEATURE_ZERO:
+
+ dUsbSendStall(); // Illegal request :-(
+
+ break;
+
+ case STD_CLEAR_FEATURE_INTERFACE:
+
+ dUsbSendZeroLengthPackage(); // No special
+
+ break;
+
+ case STD_CLEAR_FEATURE_ENDPOINT:
+
+ wIndex &= 0x0F;
+
+ if ((wValue == 0) && wIndex && (wIndex <= 3)) // Feature Selector = 0 => ENABLE A HALTED endpoint
+ { // and endpoint isolated and validated
+
+ if (wIndex == 1)
+ (*AT91C_UDP_CSR1) = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT); // On duty again
+ else if (wIndex == 2)
+ (*AT91C_UDP_CSR2) = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN); // -
+ else if (wIndex == 3)
+ (*AT91C_UDP_CSR3) = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN); // -
+
+ dUsbSendZeroLengthPackage();
+
+ }
+ else
+
+ dUsbSendStall(); // Illegal request :-(
+
+ break;
+
+ default:
+
+ dUsbSendStall(); // Illegal request :-(
+
+ break;
+ }
+}
+
+UBYTE dUsbIsConfigured(void)
+{
+
+ if (*AT91C_UDP_ISR & END_OF_BUS_RESET) // If "End Of Bus Reset Interrupt"
+ { // Somebody fallen in the wire? ;-)
+
+
+ *AT91C_UDP_ICR = END_OF_BUS_RESET; // Reset "End Of Bus Reset Interrupt"
+ *AT91C_UDP_ICR = SUSPEND_RESUME; // State unknown after reset, so we better clear
+ *AT91C_UDP_ICR = WAKEUP; // As above
+
+ CurrentConfiguration = 0; // We're new and ready
+ UsbConnectionStates = USB_NOT_CONFIGURED;
+
+ *AT91C_UDP_RSTEP = 0xFFFFFFFF; // Reset all implemented endpoints "and a few more"
+ *AT91C_UDP_RSTEP = 0x0; // Restored as zeroes
+ // Below our main crash thing, if it is missing ;-)
+ CurrentReceiveBank = AT91C_UDP_RX_DATA_BK0; // Start the PING-PONG buffers at a known state and order
+
+ *AT91C_UDP_FADDR = AT91C_UDP_FEN; // Set FEN in the Function Address Register
+ // USB device is able to receive and transfer data
+
+ *AT91C_UDP_CSR0 = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); // Configure endpoint 0
+ // AT91C_UDP_EPEDS = Endpoint enable
+ // AT91C_UDP_EPTYPE_CTRL = Endpoint type CONTROL
+ }
+
+ else if (*AT91C_UDP_ISR & SUSPEND_INT)
+ {
+ if (UsbConnectionStates == USB_CONFIGURED)
+ {
+ UsbConnectionStates = USB_CONFIGURED_BUT_SUSPENDED;
+ }
+ else
+ {
+ UsbConnectionStates = USB_NOT_CONFIGURED;
+ }
+
+ *AT91C_UDP_ICR = SUSPEND_INT;
+ CurrentReceiveBank = AT91C_UDP_RX_DATA_BK0; // Start the PING-PONG buffers at a known state and order
+ }
+
+ else if (*AT91C_UDP_ISR & SUSPEND_RESUME)
+ {
+ if (UsbConnectionStates == USB_CONFIGURED_BUT_SUSPENDED)
+ {
+ UsbConnectionStates = USB_CONFIGURED;
+ }
+ else
+ {
+ UsbConnectionStates = USB_NOT_CONFIGURED;
+ }
+
+ *AT91C_UDP_ICR = WAKEUP;
+ *AT91C_UDP_ICR = SUSPEND_RESUME;
+ }
+
+ else if (*AT91C_UDP_ISR & AT91C_UDP_EPINT0) // If "Endpoint 0 Interrupt"
+ {
+ *AT91C_UDP_ICR = AT91C_UDP_EPINT0; // Reset "Endpoint 0 Interrupt"
+ if (BrickNameKnown)
+ dUsbEnumerate(); // Let's date & exchange "personal data"
+ }
+
+ if (UsbConnectionStates == USB_CONFIGURED)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+
+}
+
+
+void dUsbInsertHandle(UBYTE Handle)
+{
+ UBYTE Tmp;
+
+ Tmp = 0;
+ while((UsbHandleList[Tmp] != MAX_HANDLES) && (Tmp < MAX_HANDLES))
+ {
+ Tmp++;
+ }
+ UsbHandleList[Tmp] = Handle;
+}
+
+void dUsbRemoveHandle(UBYTE Handle)
+{
+ UBYTE Tmp;
+
+ Tmp = 0;
+ while (Tmp < MAX_HANDLES)
+ {
+ if (Handle == UsbHandleList[Tmp])
+ {
+ UsbHandleList[Tmp] = MAX_HANDLES;
+ }
+ Tmp++;
+ }
+}
+
+UWORD dUsbGetFirstHandle(void)
+{
+ UWORD RtnVal;
+
+ UsbHandleCnt = 0;
+ RtnVal = dUsbGetNextHandle();
+
+ return(RtnVal);
+}
+
+UWORD dUsbGetNextHandle(void)
+{
+ UBYTE Tmp;
+ UWORD RtnVal;
+
+ RtnVal = 0;
+ Tmp = UsbHandleCnt;
+ while((Tmp < MAX_HANDLES) && (MAX_HANDLES == UsbHandleList[Tmp]))
+ {
+ Tmp++;
+ }
+ UsbHandleCnt = Tmp + 1;
+
+ if (Tmp < MAX_HANDLES)
+ {
+ RtnVal |= UsbHandleList[Tmp];
+ }
+ else
+ {
+ RtnVal = 0x8100;
+ }
+
+ return(RtnVal);
+}
+
+UWORD dUsbCheckConnection(void)
+{
+ UWORD ADValue;
+ UWORD Return;
+
+ Return = FALSE;
+ USBReadADCValue(&ADValue);
+
+ if (ADValue > 512)
+ {
+ Return = TRUE;
+ }
+ return(Return);
+}
+
+void dUsbInit(void)
+{
+ UBYTE Tmp;
+
+ // We could come from a SAMBA session and then we need
+ // to "introduce ourself in a polite way for the PNP manager
+ // We will pull the carpet and start a new session by removing
+ // the pull up of the D+ wire
+
+ BrickNameKnown = FALSE;
+ dUsbStartTimeoutTimer(); // Let H/W settle
+ dUsbDisconnect(); // Pull the carpet
+ while(!USBTimedOut); // wait 1 mS.
+
+ USBHwInit; // New session
+
+ CurrentConfiguration = 0; // We're new born
+ UsbConnectionStates = USB_NOT_CONFIGURED;
+ CurrentReceiveBank = AT91C_UDP_RX_DATA_BK0; // Always start from Bank 0
+ RequestedData = 0;
+
+ for(Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
+ {
+ UsbHandleList[Tmp] = MAX_HANDLES;
+ }
+}
+
+void dUsbResetConfig(void)
+{
+ CurrentConfiguration = 0; // We've lost the connection
+ UsbConnectionStates = USB_NOT_CONFIGURED;
+}
+
+void dUsbExit(void)
+{
+// USBExit;
+}
diff --git a/AT91SAM7S256/Source/d_usb.h b/AT91SAM7S256/Source/d_usb.h
new file mode 100644
index 0000000..3a176b3
--- /dev/null
+++ b/AT91SAM7S256/Source/d_usb.h
@@ -0,0 +1,51 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dkpechri $
+//
+// Revision date $Date:: 19-07-06 10:02 $
+//
+// Filename $Workfile:: d_usb.h $
+//
+// Version $Revision:: 10 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_usb.h $
+//
+// Platform C
+//
+
+#ifndef D_USB
+#define D_USB
+
+//* public constants
+
+// LOW level commands
+
+#define OPENFILEWRITE 0x01
+#define OPENFILEREAD 0x02
+#define WRITEFILE 0x03
+#define CLOSEFILE 0x04
+
+// Low level direct command escape
+
+#define DIRECTCOMMAND 0x80 // Escape sent to the Loader
+#define USB_TIMEOUT 0x0BB8 // Equals approx. 1 mS. Used for recover a "broken" cable situation
+
+//* external function description
+
+void dUsbInit(void);
+void dUsbExit(void);
+ULONG dUsbRead(UBYTE *pData, ULONG Length);
+ULONG dUsbWrite( const UBYTE *pData, ULONG Length);
+UBYTE dUsbIsConfigured(void);
+
+void dUsbInsertHandle(UBYTE Handle);
+void dUsbRemoveHandle(UBYTE Handle);
+UWORD dUsbGetFirstHandle(void);
+UWORD dUsbGetNextHandle(void);
+UWORD dUsbCheckConnection(void);
+void dUsbResetConfig(void);
+void dUsbStoreBtAddress(UBYTE *pBtAddress);
+#endif
diff --git a/AT91SAM7S256/Source/d_usb.r b/AT91SAM7S256/Source/d_usb.r
new file mode 100644
index 0000000..a3c3284
--- /dev/null
+++ b/AT91SAM7S256/Source/d_usb.r
@@ -0,0 +1,65 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dkpechri $
+//
+// Revision date $Date:: 19-07-06 10:02 $
+//
+// Filename $Workfile:: d_usb.r $
+//
+// Version $Revision:: 9 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_usb.r $
+//
+// Platform C
+//
+
+#ifdef SAM7S256
+
+#ifdef PROTOTYPE_PCB_3
+#define ENABLEUsbPU *AT91C_PIOA_PER = AT91C_PIO_PA16; /* PIO allowed to control bit 16 */\
+ *AT91C_PIOA_OER = AT91C_PIO_PA16; /* Output pin 16 enabled */\
+ *AT91C_PIOA_SODR = AT91C_PIO_PA16 /* Pin 16 set = enable USB pull-up */
+#endif
+
+#ifdef PROTOTYPE_PCB_4
+#define ENABLEUsbPU *AT91C_PIOA_PER = AT91C_PIO_PA16; /* PIO allowed to control bit 16 */\
+ *AT91C_PIOA_OER = AT91C_PIO_PA16; /* Output pin 16 enabled */\
+ *AT91C_PIOA_CODR = AT91C_PIO_PA16 /* Pin 16 clear = enable USB pull-up */
+
+#define DISABLEUsbPU *AT91C_PIOA_PER = AT91C_PIO_PA16; /* PIO allowed to control bit 16 */\
+ *AT91C_PIOA_OER = AT91C_PIO_PA16; /* Output pin 16 enabled */\
+ *AT91C_PIOA_SODR = AT91C_PIO_PA16 /* Pin 16 set = disable USB pull-up */
+#endif
+
+
+#define USBHwInit *AT91C_CKGR_PLLR |= AT91C_CKGR_USBDIV_1; /* Set the PLL USB Divider (96MHz/2) */\
+ *AT91C_PMC_SCER = AT91C_PMC_UDP; /* WRITE-ONLY REG! Enables the 48MHz USB clock UDPCK (SysClk) */\
+ *AT91C_PMC_PCER = (1 << AT91C_ID_UDP); /* WRITE-ONLY REG! Enable USB clock (Peripheral Clock) */\
+ \
+ /* Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO */ \
+ \
+ /* Removed 22022006 14:20 pc ENABLEUsbPU BlueCore delay , No pull up before OK serial-no rec. from B.C.*/
+
+
+static ULONG USBTimeOut;
+
+#define USBTimedOut (USB_TIMEOUT < ((((*AT91C_PITC_PIIR) & AT91C_PITC_CPIV) - USBTimeOut) & AT91C_PITC_CPIV))
+
+#define USBGetActualTime USBTimeOut = ((*AT91C_PITC_PIIR) & AT91C_PITC_CPIV)
+
+#define USBReadADCValue(ADValue) *ADValue = *AT91C_ADC_CDR4
+
+#define USBExit
+
+#define USBDisconnect DISABLEUsbPU
+
+#define USBConnect ENABLEUsbPU
+
+#endif
+
+#ifdef PCWIN
+
+#endif
diff --git a/AT91SAM7S256/Source/m_sched.c b/AT91SAM7S256/Source/m_sched.c
new file mode 100644
index 0000000..bc394a5
--- /dev/null
+++ b/AT91SAM7S256/Source/m_sched.c
@@ -0,0 +1,94 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:15 $
+//
+// Filename $Workfile:: m_sched.c $
+//
+// Version $Revision:: 14 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/m_sched.c $
+//
+// Platform C
+//
+
+
+#define INCLUDE_OS
+
+#define MODULEHEADERS 32
+
+#include "stdconst.h"
+#include "modules.h"
+#include "m_sched.h"
+
+#include "c_comm.h"
+#include "c_input.h"
+#include "c_button.h"
+#include "c_loader.h"
+#include "c_sound.h"
+#include "c_display.h"
+#include "c_lowspeed.h"
+#include "c_output.h"
+#include "c_cmd.h"
+#include "c_cmd.iom"
+#include "c_ioctrl.h"
+#include "c_ui.h"
+
+
+static const HEADER* pModuleHeaders[MODULEHEADERS] =
+{
+ &cComm,
+ &cInput,
+ &cButton,
+ &cDisplay,
+ &cLoader,
+ &cLowSpeed,
+ &cOutput,
+ &cSound,
+ &cIOCtrl,
+ &cCmd,
+ &cUi,
+ 0
+};
+
+
+void mSchedInit(void)
+{
+ UWORD Tmp;
+
+ Tmp = 0;
+ while(pModuleHeaders[Tmp])
+ {
+ (*pModuleHeaders[Tmp]).cInit((void*) pModuleHeaders);
+ Tmp++;
+ }
+}
+
+
+UBYTE mSchedCtrl(void)
+{
+ UWORD Tmp;
+
+ Tmp = 0;
+ while(pModuleHeaders[Tmp])
+ {
+ (*pModuleHeaders[Tmp]).cCtrl();
+ Tmp++;
+ }
+
+ return(((IOMAPCMD*)(pModuleHeaders[ENTRY_CMD]->pIOMap))->Awake);
+}
+
+
+void mSchedExit(void)
+{
+ UWORD Tmp;
+
+ Tmp = 0;
+ while(pModuleHeaders[Tmp])
+ {
+ (*pModuleHeaders[Tmp]).cExit();
+ Tmp++;
+ }
+}
+
diff --git a/AT91SAM7S256/Source/m_sched.h b/AT91SAM7S256/Source/m_sched.h
new file mode 100644
index 0000000..6bf5a07
--- /dev/null
+++ b/AT91SAM7S256/Source/m_sched.h
@@ -0,0 +1,135 @@
+//
+// Date init 14.12.2004
+//
+// Revision date $Date:: 16-05-06 10:15 $
+//
+// Filename $Workfile:: m_sched.h $
+//
+// Version $Revision:: 20 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/m_sched.h $
+//
+// Platform C
+//
+
+
+
+#define APPNAME "LMS01"
+
+#define COPYRIGHTSTRING "Let's samba nxt arm in arm, (c)LEGO System A/S"
+
+#define COPYRIGHTSTRINGLENGTH 46 /* Number of bytes checked in COPYRIGHTSTRING */
+
+
+#ifndef _WINDOWS
+
+#define SAM7SXX
+
+#ifdef SAM7SXX
+
+ //
+ // Platform ATMEL ARM7
+ //
+ //
+
+#define OSC 48054850L
+#define SYSFREQ 1000
+
+
+#include "..\SAM7S256\include\sam7s256.h"
+
+#if defined (PROTOTYPE_PCB_3) || (PROTOTYPE_PCB_4)
+
+#define TSTPin AT91C_PIO_PA27
+
+#else
+
+#define TSTPin AT91C_PIO_PA31
+
+#endif
+
+#define TSTInit {\
+ *AT91C_PIOA_PER = TSTPin;\
+ *AT91C_PIOA_OER = TSTPin;\
+ }
+
+#define TSTOn {\
+ *AT91C_PIOA_SODR = TSTPin;\
+ }
+
+#define TSTOff {\
+ *AT91C_PIOA_CODR = TSTPin;\
+ }
+
+#define TSTExit {\
+ *AT91C_PIOA_ODR = TSTPin;\
+ *AT91C_PIOA_CODR = TSTPin;\
+ }
+
+/* Defines related to loader */
+#define MAX_HANDLES 16
+
+
+/* Defines related to I2c */
+#define BYTES_TO_TX 8
+#define BYTES_TO_RX 12
+
+enum
+{
+ NOS_OF_AVR_OUTPUTS = 4,
+ NOS_OF_AVR_BTNS = 4,
+ NOS_OF_AVR_INPUTS = 4
+};
+
+typedef struct
+{
+ UWORD AdValue[NOS_OF_AVR_INPUTS];
+ UWORD Buttons;
+ UWORD Battery;
+}IOFROMAVR;
+
+typedef struct
+{
+ UBYTE Power;
+ UBYTE PwmFreq;
+ SBYTE PwmValue[NOS_OF_AVR_OUTPUTS];
+ UBYTE OutputMode;
+ UBYTE InputPower;
+}IOTOAVR;
+
+extern IOTOAVR IoToAvr;
+extern IOFROMAVR IoFromAvr;
+
+#ifdef INCLUDE_OS
+
+#include "..\SAM7S256\include\sam7s256.c"
+
+IOTOAVR IoToAvr;
+IOFROMAVR IoFromAvr;
+
+#endif
+
+#endif
+
+#else
+
+ //
+ // Platform PCWIN
+ //
+ //
+
+#define OSC 1192000L
+#define SYSFREQ 1000
+
+#include "Pcwin.h"
+
+#ifdef INCLUDE_OS
+
+#include "Pcwin.c"
+
+#endif
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/modules.h b/AT91SAM7S256/Source/modules.h
new file mode 100644
index 0000000..6060800
--- /dev/null
+++ b/AT91SAM7S256/Source/modules.h
@@ -0,0 +1,343 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Dkflebun $
+//
+// Revision date $Date:: 5-02-07 13:36 $
+//
+// Filename $Workfile:: modules.h $
+//
+// Version $Revision:: 49 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/modules.h $
+//
+// Platform C
+//
+
+#ifndef MODULE_HEADER
+#define MODULE_HEADER
+
+#define FILENAME_LENGTH 19 // zero termination not included
+#define FILEHEADER_LENGTH 8 // all simple file headers
+#define DISPLAYLINE_LENGTH 16 // zero termination not included
+#define ON_BRICK_PROGRAMSTEPS 5 // no of on brick program steps
+#define STATUSTEXT_SIZE 8 // zero termination not included
+
+#define TXT_SOUND_EXT "rso" // Sound filename extension
+#define TXT_LMS_EXT "rxe" // Mindstorms program filename extension
+#define TXT_NXT_EXT "rpg" // Program filename extension
+#define TXT_TRYME_EXT "rtm" // Try me program filename extension
+#define TXT_DATA_EXT "rdt" // Datalog filename extension
+#define TXT_MENU_EXT "rms" // Menu system filename extension (hidden)
+#define TXT_SYS_EXT "sys" // System filename extension (hidden)
+#define TXT_TMP_EXT "tmp" // Temporary filename extension (hidden)
+
+
+/* Error codes from then Loader */
+enum
+{
+ SUCCESS = 0x0000,
+ INPROGRESS = 0x0001,
+ REQPIN = 0x0002,
+ NOMOREHANDLES = 0x8100,
+ NOSPACE = 0x8200,
+ NOMOREFILES = 0x8300,
+ EOFEXSPECTED = 0x8400,
+ ENDOFFILE = 0x8500,
+ NOTLINEARFILE = 0x8600,
+ FILENOTFOUND = 0x8700,
+ HANDLEALREADYCLOSED = 0x8800,
+ NOLINEARSPACE = 0x8900,
+ UNDEFINEDERROR = 0x8A00,
+ FILEISBUSY = 0x8B00,
+ NOWRITEBUFFERS = 0x8C00,
+ APPENDNOTPOSSIBLE = 0x8D00,
+ FILEISFULL = 0x8E00,
+ FILEEXISTS = 0x8F00,
+ MODULENOTFOUND = 0x9000,
+ OUTOFBOUNDERY = 0x9100,
+ ILLEGALFILENAME = 0x9200,
+ ILLEGALHANDLE = 0x9300,
+ BTBUSY = 0x9400,
+ BTCONNECTFAIL = 0x9500,
+ BTTIMEOUT = 0x9600,
+ FILETX_TIMEOUT = 0x9700,
+ FILETX_DSTEXISTS = 0x9800,
+ FILETX_SRCMISSING = 0x9900,
+ FILETX_STREAMERROR = 0x9A00,
+ FILETX_CLOSEERROR = 0x9B00
+};
+
+
+/* interface between comm and BC4 */
+enum
+{
+ MSG_BEGIN_INQUIRY,
+ MSG_CANCEL_INQUIRY,
+ MSG_CONNECT,
+ MSG_OPEN_PORT,
+ MSG_LOOKUP_NAME,
+ MSG_ADD_DEVICE,
+ MSG_REMOVE_DEVICE,
+ MSG_DUMP_LIST,
+ MSG_CLOSE_CONNECTION,
+ MSG_ACCEPT_CONNECTION,
+ MSG_PIN_CODE,
+ MSG_OPEN_STREAM,
+ MSG_START_HEART,
+ MSG_HEARTBEAT,
+ MSG_INQUIRY_RUNNING,
+ MSG_INQUIRY_RESULT,
+ MSG_INQUIRY_STOPPED,
+ MSG_LOOKUP_NAME_RESULT,
+ MSG_LOOKUP_NAME_FAILURE,
+ MSG_CONNECT_RESULT,
+ MSG_RESET_INDICATION,
+ MSG_REQUEST_PIN_CODE,
+ MSG_REQUEST_CONNECTION,
+ MSG_LIST_RESULT,
+ MSG_LIST_ITEM,
+ MSG_LIST_DUMP_STOPPED,
+ MSG_CLOSE_CONNECTION_RESULT,
+ MSG_PORT_OPEN_RESULT,
+ MSG_SET_DISCOVERABLE,
+ MSG_CLOSE_PORT,
+ MSG_CLOSE_PORT_RESULT,
+ MSG_PIN_CODE_ACK,
+ MSG_DISCOVERABLE_ACK,
+ MSG_SET_FRIENDLY_NAME,
+ MSG_SET_FRIENDLY_NAME_ACK,
+ MSG_GET_LINK_QUALITY,
+ MSG_LINK_QUALITY_RESULT,
+ MSG_SET_FACTORY_SETTINGS,
+ MSG_SET_FACTORY_SETTINGS_ACK,
+ MSG_GET_LOCAL_ADDR,
+ MSG_GET_LOCAL_ADDR_RESULT,
+ MSG_GET_FRIENDLY_NAME,
+ MSG_GET_DISCOVERABLE,
+ MSG_GET_PORT_OPEN,
+ MSG_GET_FRIENDLY_NAME_RESULT,
+ MSG_GET_DISCOVERABLE_RESULT,
+ MSG_GET_PORT_OPEN_RESULT,
+ MSG_GET_VERSION,
+ MSG_GET_VERSION_RESULT,
+ MSG_GET_BRICK_STATUSBYTE_RESULT,
+ MSG_SET_BRICK_STATUSBYTE_RESULT,
+ MSG_GET_BRICK_STATUSBYTE,
+ MSG_SET_BRICK_STATUSBYTE
+};
+
+#define SIZE_OF_BT_NAME 16
+#define SIZE_OF_BRICK_NAME 8
+#define SIZE_OF_CLASS_OF_DEVICE 4
+#define SIZE_OF_BT_PINCODE 16
+#define SIZE_OF_BDADDR 7
+
+
+enum
+{
+ ENTRY_COMM,
+ ENTRY_INPUT,
+ ENTRY_BUTTON,
+ ENTRY_DISPLAY,
+ ENTRY_LOADER,
+ ENTRY_LOWSPEED,
+ ENTRY_OUTPUT,
+ ENTRY_SOUND,
+ ENTRY_IOCTRL,
+ ENTRY_CMD,
+ ENTRY_UI,
+ ENTRY_FREE2,
+ ENTRY_FREE3,
+ ENTRY_FREE4,
+ ENTRY_FREE5
+};
+
+typedef struct
+{
+ ULONG ModuleID;
+ UBYTE ModuleName[FILENAME_LENGTH + 1];
+ void (*cInit)(void* pHeader);
+ void (*cCtrl)(void);
+ void (*cExit)(void);
+ void *pIOMap;
+ void *pVars;
+ UWORD IOMapSize;
+ UWORD VarsSize;
+ UWORD ModuleSize;
+}HEADER;
+
+enum
+{
+ FILEFORMAT_SOUND = 0x0100, // rso
+ FILEFORMAT_SOUND_COMPRESSED = 0x0101, // rso
+ FILEFORMAT_BITMAP = 0x0200,
+ FILEFORMAT_FONT = 0x0300,
+ FILEFORMAT_ICON = 0x0400,
+ FILEFORMAT_TEXT = 0x0500,
+ FILEFORMAT_MELODY = 0x0600,
+ FILEFORMAT_MENU = 0x0700, // rms
+ FILEFORMAT_PROGRAM = 0x0800, // rpg
+ FILEFORMAT_DATALOG = 0x0900 // rdt
+};
+
+typedef struct
+{
+ UBYTE FormatMsb;
+ UBYTE FormatLsb;
+ UBYTE DateBytesMsb;
+ UBYTE DataBytesLsb;
+ UBYTE SampleRateMsb;
+ UBYTE SampleRateLsb;
+ UBYTE PlayModeMsb;
+ UBYTE PlayModeLsb;
+ UBYTE Data[];
+}
+SOUND;
+
+typedef struct
+{
+ UBYTE FormatMsb;
+ UBYTE FormatLsb;
+ UBYTE DateBytesMsb;
+ UBYTE DataBytesLsb;
+ UBYTE StartX;
+ UBYTE StartY;
+ UBYTE PixelsX;
+ UBYTE PixelsY;
+ UBYTE Data[];
+}
+BMPMAP;
+
+typedef struct
+{
+ UBYTE FormatMsb;
+ UBYTE FormatLsb;
+ UBYTE DataBytesMsb;
+ UBYTE DataBytesLsb;
+ UBYTE ItemsX;
+ UBYTE ItemsY;
+ UBYTE ItemPixelsX;
+ UBYTE ItemPixelsY;
+ UBYTE Data[];
+}
+FONT;
+
+typedef struct
+{
+ UBYTE FormatMsb;
+ UBYTE FormatLsb;
+ UBYTE DataBytesMsb;
+ UBYTE DataBytesLsb;
+ UBYTE ItemsX;
+ UBYTE ItemsY;
+ UBYTE ItemPixelsX;
+ UBYTE ItemPixelsY;
+ UBYTE Data[];
+}
+ICON;
+
+typedef struct
+{
+ UBYTE FormatMsb;
+ UBYTE FormatLsb;
+ UBYTE DataBytesMsb;
+ UBYTE DataBytesLsb;
+ UBYTE ItemsX;
+ UBYTE ItemsY;
+ UBYTE ItemCharsX;
+ UBYTE ItemCharsY;
+ UBYTE Data[];
+}
+TXT;
+
+typedef struct
+{
+ UBYTE FormatMsb;
+ UBYTE FormatLsb;
+ UBYTE DateBytesMsb;
+ UBYTE DataBytesLsb;
+ UBYTE TonesMsb;
+ UBYTE TonesLsb;
+ UBYTE PlayModeMsb;
+ UBYTE PlayModeLsb;
+ UBYTE Data[]; // Data[0] = FreqMsb, Data[1] = FreqLsb, Data[2] = DurationMsb, Data[3] = DurationLsb ....
+}
+MELODY;
+
+typedef struct
+{
+ UBYTE FormatMsb;
+ UBYTE FormatLsb;
+ UBYTE DataBytesMsb;
+ UBYTE DataBytesLsb;
+ UBYTE Steps;
+ UBYTE NotUsed1;
+ UBYTE NotUsed2;
+ UBYTE NotUsed3;
+ UBYTE Data[];
+}
+PROGRAM;
+
+typedef struct
+{
+ UBYTE FormatMsb;
+ UBYTE FormatLsb;
+ UBYTE DataBytesMsb;
+ UBYTE DataBytesLsb;
+ UBYTE TotalTime3;
+ UBYTE TotalTime2;
+ UBYTE TotalTime1;
+ UBYTE TotalTime0;
+ UBYTE Data[];
+}
+DATALOG;
+
+#define DATALOG_FILE_LENGTH 64000L// Max datalog file size
+#define DATALOG_HEADER_LENGTH 9 // Datalog sensor header length [Bytes]
+#define DATALOG_DATA_LENGTH 5 // Datalog sensor data length [Bytes]
+
+#define ICON_TEXTLNG 15 // 15 characters
+#define ICON_IMAGESIZE 72 // 24 x 24 pixels
+#define MAX_MENUITEMS 256
+
+typedef struct
+{
+ UBYTE ItemId67; // Menu item id
+ UBYTE ItemId45; // Menu item id
+ UBYTE ItemId23; // Menu item id
+ UBYTE ItemId01; // Menu item id
+ UBYTE SpecialMask3; // Menu item special mask (TBD)
+ UBYTE SpecialMask2; // Menu item special mask (TBD)
+ UBYTE SpecialMask1; // Menu item special mask (TBD)
+ UBYTE SpecialMask0; // Menu item special mask (TBD)
+ UBYTE FunctionIndex; // Menu item enter function call index
+ UBYTE FunctionParameter; // Menu item enter function parameter
+ UBYTE FileLoadNo; // Menu item enter menu file load no
+ UBYTE NextMenu; // Menu item enter next level menu no
+ UBYTE IconText[ICON_TEXTLNG + 1]; // Menu item icon text string
+ UBYTE IconImageNo; // Menu item icon image number
+}MENUITEM;
+
+typedef struct
+{
+ UBYTE FormatMsb;
+ UBYTE FormatLsb;
+ UBYTE DataBytesMsb;
+ UBYTE DataBytesLsb;
+ UBYTE ItemSize;
+ UBYTE Items;
+ UBYTE ItemPixelsX;
+ UBYTE ItemPixelsY;
+ MENUITEM Data[MAX_MENUITEMS];
+}
+MENU;
+
+typedef UBYTE (*FUNCTION)(UBYTE); // Menu function type
+
+#endif
+
+
+
diff --git a/AT91SAM7S256/Source/stdconst.h b/AT91SAM7S256/Source/stdconst.h
new file mode 100644
index 0000000..81bf972
--- /dev/null
+++ b/AT91SAM7S256/Source/stdconst.h
@@ -0,0 +1,48 @@
+//
+// Programmer
+//
+// Date init 14.12.2004
+//
+// Reviser $Author:: Us8jamlo $
+//
+// Revision date $Date:: 3/04/05 2:59p $
+//
+// Filename $Workfile:: stdconst.h $
+//
+// Version $Revision:: 3 $
+//
+// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/stdconst.h $
+//
+// Platform C
+//
+
+
+#ifndef STDCONST
+#define STDCONST
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+typedef unsigned char UCHAR;
+typedef unsigned short USHORT;
+
+typedef unsigned char UBYTE;
+typedef signed char SBYTE;
+typedef unsigned short int UWORD;
+typedef signed short int SWORD;
+typedef unsigned long ULONG;
+typedef signed long SLONG;
+
+typedef ULONG* PULONG;
+typedef USHORT* PUSHORT;
+typedef UCHAR* PUCHAR;
+typedef char* PSZ;
+
+#define BASETYPES
+
+
+#endif