From ba78bd9ba834260d035a9830726afc34fdad2a15 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Sun, 18 Oct 2009 23:32:54 +0200 Subject: import firmware from LEGO v1.05 --- AT91SAM7S256/Source/BtTest.inc | 1642 +++++++++ AT91SAM7S256/Source/Connections.txt | 21 + AT91SAM7S256/Source/Cursor.txt | 10 + AT91SAM7S256/Source/Devices.txt | 21 + AT91SAM7S256/Source/Display.txt | 12 + AT91SAM7S256/Source/Fail.txt | 12 + AT91SAM7S256/Source/Font.txt | 15 + AT91SAM7S256/Source/Functions.inl | 3730 +++++++++++++++++++ AT91SAM7S256/Source/Icons.txt | 297 ++ AT91SAM7S256/Source/Info.txt | 12 + AT91SAM7S256/Source/LowBattery.txt | 16 + AT91SAM7S256/Source/Mainmenu.rms | 65 + AT91SAM7S256/Source/Ok.txt | 11 + AT91SAM7S256/Source/Port.txt | 10 + AT91SAM7S256/Source/RCXintro_1.txt | 17 + AT91SAM7S256/Source/RCXintro_10.txt | 11 + AT91SAM7S256/Source/RCXintro_11.txt | 11 + AT91SAM7S256/Source/RCXintro_12.txt | 11 + AT91SAM7S256/Source/RCXintro_13.txt | 11 + AT91SAM7S256/Source/RCXintro_14.txt | 11 + AT91SAM7S256/Source/RCXintro_15.txt | 11 + AT91SAM7S256/Source/RCXintro_16.txt | 11 + AT91SAM7S256/Source/RCXintro_2.txt | 17 + AT91SAM7S256/Source/RCXintro_3.txt | 17 + AT91SAM7S256/Source/RCXintro_4.txt | 17 + AT91SAM7S256/Source/RCXintro_5.txt | 17 + AT91SAM7S256/Source/RCXintro_6.txt | 15 + AT91SAM7S256/Source/RCXintro_7.txt | 14 + AT91SAM7S256/Source/RCXintro_8.txt | 12 + AT91SAM7S256/Source/RCXintro_9.txt | 12 + AT91SAM7S256/Source/Running.txt | 57 + AT91SAM7S256/Source/Status.txt | 15 + AT91SAM7S256/Source/Step.txt | 17 + AT91SAM7S256/Source/Submenu01.rms | 128 + AT91SAM7S256/Source/Submenu02.rms | 401 +++ AT91SAM7S256/Source/Submenu03.rms | 324 ++ AT91SAM7S256/Source/Submenu04.rms | 170 + AT91SAM7S256/Source/Submenu05.rms | 128 + AT91SAM7S256/Source/Submenu06.rms | 51 + AT91SAM7S256/Source/Submenu07.rms | 142 + AT91SAM7S256/Source/Test1.txt | 17 + AT91SAM7S256/Source/Test2.txt | 17 + AT91SAM7S256/Source/Ui.txt | 60 + AT91SAM7S256/Source/Wait.txt | 12 + AT91SAM7S256/Source/c_button.c | 134 + AT91SAM7S256/Source/c_button.h | 37 + AT91SAM7S256/Source/c_button.iom | 61 + AT91SAM7S256/Source/c_cmd.c | 6292 +++++++++++++++++++++++++++++++++ AT91SAM7S256/Source/c_cmd.h | 804 +++++ AT91SAM7S256/Source/c_cmd.iom | 178 + AT91SAM7S256/Source/c_cmd_alternate.c | 163 + AT91SAM7S256/Source/c_cmd_bytecodes.h | 115 + AT91SAM7S256/Source/c_cmd_drawing.inc | 894 +++++ AT91SAM7S256/Source/c_comm.c | 3658 +++++++++++++++++++ AT91SAM7S256/Source/c_comm.h | 151 + AT91SAM7S256/Source/c_comm.iom | 222 ++ AT91SAM7S256/Source/c_display.c | 859 +++++ AT91SAM7S256/Source/c_display.h | 43 + AT91SAM7S256/Source/c_display.iom | 177 + AT91SAM7S256/Source/c_input.c | 777 ++++ AT91SAM7S256/Source/c_input.h | 53 + AT91SAM7S256/Source/c_input.iom | 109 + AT91SAM7S256/Source/c_ioctrl.c | 78 + AT91SAM7S256/Source/c_ioctrl.h | 28 + AT91SAM7S256/Source/c_ioctrl.iom | 35 + AT91SAM7S256/Source/c_loader.c | 458 +++ AT91SAM7S256/Source/c_loader.h | 44 + AT91SAM7S256/Source/c_loader.iom | 83 + AT91SAM7S256/Source/c_lowspeed.c | 236 ++ AT91SAM7S256/Source/c_lowspeed.h | 61 + AT91SAM7S256/Source/c_lowspeed.iom | 95 + AT91SAM7S256/Source/c_output.c | 169 + AT91SAM7S256/Source/c_output.h | 31 + AT91SAM7S256/Source/c_output.iom | 92 + AT91SAM7S256/Source/c_sound.c | 309 ++ AT91SAM7S256/Source/c_sound.h | 44 + AT91SAM7S256/Source/c_sound.iom | 109 + AT91SAM7S256/Source/c_ui.c | 1982 +++++++++++ AT91SAM7S256/Source/c_ui.h | 352 ++ AT91SAM7S256/Source/c_ui.iom | 116 + AT91SAM7S256/Source/d_bt.c | 453 +++ AT91SAM7S256/Source/d_bt.h | 39 + AT91SAM7S256/Source/d_bt.r | 350 ++ AT91SAM7S256/Source/d_button.c | 36 + AT91SAM7S256/Source/d_button.h | 24 + AT91SAM7S256/Source/d_button.r | 189 + AT91SAM7S256/Source/d_display.c | 53 + AT91SAM7S256/Source/d_display.h | 39 + AT91SAM7S256/Source/d_display.r | 374 ++ AT91SAM7S256/Source/d_hispeed.c | 48 + AT91SAM7S256/Source/d_hispeed.h | 25 + AT91SAM7S256/Source/d_hispeed.r | 190 + AT91SAM7S256/Source/d_input.c | 104 + AT91SAM7S256/Source/d_input.h | 37 + AT91SAM7S256/Source/d_input.r | 99 + AT91SAM7S256/Source/d_ioctrl.c | 102 + AT91SAM7S256/Source/d_ioctrl.h | 25 + AT91SAM7S256/Source/d_ioctrl.r | 310 ++ AT91SAM7S256/Source/d_loader.c | 1437 ++++++++ AT91SAM7S256/Source/d_loader.h | 99 + AT91SAM7S256/Source/d_loader.r | 117 + AT91SAM7S256/Source/d_lowspeed.c | 77 + AT91SAM7S256/Source/d_lowspeed.h | 28 + AT91SAM7S256/Source/d_lowspeed.r | 932 +++++ AT91SAM7S256/Source/d_output.c | 1605 +++++++++ AT91SAM7S256/Source/d_output.h | 90 + AT91SAM7S256/Source/d_output.r | 306 ++ AT91SAM7S256/Source/d_sound.c | 70 + AT91SAM7S256/Source/d_sound.h | 42 + AT91SAM7S256/Source/d_sound.r | 514 +++ AT91SAM7S256/Source/d_sound_adpcm.r | 156 + AT91SAM7S256/Source/d_timer.c | 42 + AT91SAM7S256/Source/d_timer.h | 26 + AT91SAM7S256/Source/d_timer.r | 56 + AT91SAM7S256/Source/d_usb.c | 946 +++++ AT91SAM7S256/Source/d_usb.h | 51 + AT91SAM7S256/Source/d_usb.r | 65 + AT91SAM7S256/Source/m_sched.c | 94 + AT91SAM7S256/Source/m_sched.h | 135 + AT91SAM7S256/Source/modules.h | 343 ++ AT91SAM7S256/Source/stdconst.h | 48 + 121 files changed, 36453 insertions(+) create mode 100644 AT91SAM7S256/Source/BtTest.inc create mode 100644 AT91SAM7S256/Source/Connections.txt create mode 100644 AT91SAM7S256/Source/Cursor.txt create mode 100644 AT91SAM7S256/Source/Devices.txt create mode 100644 AT91SAM7S256/Source/Display.txt create mode 100644 AT91SAM7S256/Source/Fail.txt create mode 100644 AT91SAM7S256/Source/Font.txt create mode 100644 AT91SAM7S256/Source/Functions.inl create mode 100644 AT91SAM7S256/Source/Icons.txt create mode 100644 AT91SAM7S256/Source/Info.txt create mode 100644 AT91SAM7S256/Source/LowBattery.txt create mode 100644 AT91SAM7S256/Source/Mainmenu.rms create mode 100644 AT91SAM7S256/Source/Ok.txt create mode 100644 AT91SAM7S256/Source/Port.txt create mode 100644 AT91SAM7S256/Source/RCXintro_1.txt create mode 100644 AT91SAM7S256/Source/RCXintro_10.txt create mode 100644 AT91SAM7S256/Source/RCXintro_11.txt create mode 100644 AT91SAM7S256/Source/RCXintro_12.txt create mode 100644 AT91SAM7S256/Source/RCXintro_13.txt create mode 100644 AT91SAM7S256/Source/RCXintro_14.txt create mode 100644 AT91SAM7S256/Source/RCXintro_15.txt create mode 100644 AT91SAM7S256/Source/RCXintro_16.txt create mode 100644 AT91SAM7S256/Source/RCXintro_2.txt create mode 100644 AT91SAM7S256/Source/RCXintro_3.txt create mode 100644 AT91SAM7S256/Source/RCXintro_4.txt create mode 100644 AT91SAM7S256/Source/RCXintro_5.txt create mode 100644 AT91SAM7S256/Source/RCXintro_6.txt create mode 100644 AT91SAM7S256/Source/RCXintro_7.txt create mode 100644 AT91SAM7S256/Source/RCXintro_8.txt create mode 100644 AT91SAM7S256/Source/RCXintro_9.txt create mode 100644 AT91SAM7S256/Source/Running.txt create mode 100644 AT91SAM7S256/Source/Status.txt create mode 100644 AT91SAM7S256/Source/Step.txt create mode 100644 AT91SAM7S256/Source/Submenu01.rms create mode 100644 AT91SAM7S256/Source/Submenu02.rms create mode 100644 AT91SAM7S256/Source/Submenu03.rms create mode 100644 AT91SAM7S256/Source/Submenu04.rms create mode 100644 AT91SAM7S256/Source/Submenu05.rms create mode 100644 AT91SAM7S256/Source/Submenu06.rms create mode 100644 AT91SAM7S256/Source/Submenu07.rms create mode 100644 AT91SAM7S256/Source/Test1.txt create mode 100644 AT91SAM7S256/Source/Test2.txt create mode 100644 AT91SAM7S256/Source/Ui.txt create mode 100644 AT91SAM7S256/Source/Wait.txt create mode 100644 AT91SAM7S256/Source/c_button.c create mode 100644 AT91SAM7S256/Source/c_button.h create mode 100644 AT91SAM7S256/Source/c_button.iom create mode 100644 AT91SAM7S256/Source/c_cmd.c create mode 100644 AT91SAM7S256/Source/c_cmd.h create mode 100644 AT91SAM7S256/Source/c_cmd.iom create mode 100644 AT91SAM7S256/Source/c_cmd_alternate.c create mode 100644 AT91SAM7S256/Source/c_cmd_bytecodes.h create mode 100644 AT91SAM7S256/Source/c_cmd_drawing.inc create mode 100644 AT91SAM7S256/Source/c_comm.c create mode 100644 AT91SAM7S256/Source/c_comm.h create mode 100644 AT91SAM7S256/Source/c_comm.iom create mode 100644 AT91SAM7S256/Source/c_display.c create mode 100644 AT91SAM7S256/Source/c_display.h create mode 100644 AT91SAM7S256/Source/c_display.iom create mode 100644 AT91SAM7S256/Source/c_input.c create mode 100644 AT91SAM7S256/Source/c_input.h create mode 100644 AT91SAM7S256/Source/c_input.iom create mode 100644 AT91SAM7S256/Source/c_ioctrl.c create mode 100644 AT91SAM7S256/Source/c_ioctrl.h create mode 100644 AT91SAM7S256/Source/c_ioctrl.iom create mode 100644 AT91SAM7S256/Source/c_loader.c create mode 100644 AT91SAM7S256/Source/c_loader.h create mode 100644 AT91SAM7S256/Source/c_loader.iom create mode 100644 AT91SAM7S256/Source/c_lowspeed.c create mode 100644 AT91SAM7S256/Source/c_lowspeed.h create mode 100644 AT91SAM7S256/Source/c_lowspeed.iom create mode 100644 AT91SAM7S256/Source/c_output.c create mode 100644 AT91SAM7S256/Source/c_output.h create mode 100644 AT91SAM7S256/Source/c_output.iom create mode 100644 AT91SAM7S256/Source/c_sound.c create mode 100644 AT91SAM7S256/Source/c_sound.h create mode 100644 AT91SAM7S256/Source/c_sound.iom create mode 100644 AT91SAM7S256/Source/c_ui.c create mode 100644 AT91SAM7S256/Source/c_ui.h create mode 100644 AT91SAM7S256/Source/c_ui.iom create mode 100644 AT91SAM7S256/Source/d_bt.c create mode 100644 AT91SAM7S256/Source/d_bt.h create mode 100644 AT91SAM7S256/Source/d_bt.r create mode 100644 AT91SAM7S256/Source/d_button.c create mode 100644 AT91SAM7S256/Source/d_button.h create mode 100644 AT91SAM7S256/Source/d_button.r create mode 100644 AT91SAM7S256/Source/d_display.c create mode 100644 AT91SAM7S256/Source/d_display.h create mode 100644 AT91SAM7S256/Source/d_display.r create mode 100644 AT91SAM7S256/Source/d_hispeed.c create mode 100644 AT91SAM7S256/Source/d_hispeed.h create mode 100644 AT91SAM7S256/Source/d_hispeed.r create mode 100644 AT91SAM7S256/Source/d_input.c create mode 100644 AT91SAM7S256/Source/d_input.h create mode 100644 AT91SAM7S256/Source/d_input.r create mode 100644 AT91SAM7S256/Source/d_ioctrl.c create mode 100644 AT91SAM7S256/Source/d_ioctrl.h create mode 100644 AT91SAM7S256/Source/d_ioctrl.r create mode 100644 AT91SAM7S256/Source/d_loader.c create mode 100644 AT91SAM7S256/Source/d_loader.h create mode 100644 AT91SAM7S256/Source/d_loader.r create mode 100644 AT91SAM7S256/Source/d_lowspeed.c create mode 100644 AT91SAM7S256/Source/d_lowspeed.h create mode 100644 AT91SAM7S256/Source/d_lowspeed.r create mode 100644 AT91SAM7S256/Source/d_output.c create mode 100644 AT91SAM7S256/Source/d_output.h create mode 100644 AT91SAM7S256/Source/d_output.r create mode 100644 AT91SAM7S256/Source/d_sound.c create mode 100644 AT91SAM7S256/Source/d_sound.h create mode 100644 AT91SAM7S256/Source/d_sound.r create mode 100644 AT91SAM7S256/Source/d_sound_adpcm.r create mode 100644 AT91SAM7S256/Source/d_timer.c create mode 100644 AT91SAM7S256/Source/d_timer.h create mode 100644 AT91SAM7S256/Source/d_timer.r create mode 100644 AT91SAM7S256/Source/d_usb.c create mode 100644 AT91SAM7S256/Source/d_usb.h create mode 100644 AT91SAM7S256/Source/d_usb.r create mode 100644 AT91SAM7S256/Source/m_sched.c create mode 100644 AT91SAM7S256/Source/m_sched.h create mode 100644 AT91SAM7S256/Source/modules.h create mode 100644 AT91SAM7S256/Source/stdconst.h (limited to 'AT91SAM7S256/Source') 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 +#include +#include + + +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<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 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 +#include + +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<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 +#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 +#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 +#include +#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 + +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 +#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< +#include + +#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<>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<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<FileSectorTable[SectorTableIndex] = (SectorIndex << 5) + Tmp; + SectorTableIndex += (SECTORSIZE/2); + HeaderSectorSize--; + if (0 == HeaderSectorSize) + { + pHeader->FileStartAdr = (((SectorIndex << 5) + Tmp) << SECTORSIZESHIFT) + (HeaderByteSize - (TmpHSS<= (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<FileStartAdr = (((SectorIndex << 5) + Tmp) << SECTORSIZESHIFT) | FLASHOFFSET; + EvenHeader = FALSE; + } + else + { + + /* Sector is free you can have this one */ + SectorTable[SectorIndex] |= (0x01<>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<>5); + ErrorCode = SUCCESS; + } + } + + if (0x1F == Tmp) + { + SectorIndex++; + } + Tmp = (Tmp + 1) & 0x1F; + } + } + else + { + ErrorCode = UNDEFINEDERROR; + while(SectorIndex < (NOOFSECTORS>>5)) + { + if (!((SectorTable[SectorIndex]) & ((ULONG)0x01<>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 +#include + +#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 -- cgit v1.2.3