/* traxx05.nqc ------------------------------------------------------------- Developed by Gray Mack 2/10/2004 Go Robots http://www.robotgroup.org/ Support The Robot Group http://www.robotgroup.net/ This program developed using 'Not Quite C' nqc version 2.5 r3 (built Nov 8 2003, 22:10:36) Copyright (C) 1998-2002 David Baum. All Rights Reserved. To load use: nqc -d -TSpy traxx05.nqc The user is to accept all liability for the use of this software and any harm it may do within any given dimension that it affects. This is free software. */ /* Big Traxx? -------------------------------------------------------------- Does anyone remember a toy called Big Traxx? It was a tank that you could program to do a number of moves. It had a 12 button keyboard on the back for entering commands. It had a light up "laser" on the front. There was an accessory that hooked on the back. It turned the big trax into a dump truck. Anyway, I cant even find a picture of this on google, but the idea is to turn a spybot into a programmable robot. By using the controller in program mode (switch to right) you punch in sequences of moves, when done hit the bumper and it acts out the programmed sequences. You can make it a game by trying to guess the distances and sequences you need to maneuver an obstacle course. */ /* buttons: ----------- [2] [1] [3] [4] [5] O \ ----------- actions: 1st 2nd 3rd 4th 5th 6th 7th** [1]left 45 turn 90 turn 180 turn 45 rot 90 rot 180 rot [3]right 45 turn 90 turn 180 turn 45 rot 90 rot 180 rot [4]foreward .5ft slow 1ft slow 2ft slow .5ft fast 1ft fast 2ft fast [5]backward .5ft slow 1ft slow 2ft slow .5ft fast 1ft fast 2ft fast [2]action NOP/RPT 1sec pause 2sec pause 5sec pause lazer shake random! **[2]action first press is special so it has seven options [bumper switch] while programming= programming done wait 5 sec then run while running= stop running the sequence while stopped= wait 5 sec then run again [run button] startup and let me program [power button] shutdown and forget my sequences NOP is used to separate commands of same button example: turn 90degree then go forward 4ft you press: [1] [1] [4] [4] [4] [2] [4] [4] [4] You cant use NOP to separate two [2]action commands since its the same key so you cant pause 2sec twice If you want the sequences to run continuously in a loop then hit [2] (RPT) just before hitting the [bumper switch] (assuming your last action was not a [2] action command) As you press buttons the tone increases 6 times to indicate the action. If you hit [1] 7 times the tone will be the lowest again (back to 45 turn) The first press of [2] (NOP/RPT) will have a higher tone */ /* notes: Command angles/distances are time based estimates made on Gigamesh spybot with averagely used batteries. 5x6 possible commands = 30 thus 5 bits. using 20 16bit vars = 60 programmed actions */ ////#include "spy.nqh" /* ----------- cut outs from spy.nqh ----------------------*/ __nolist void SendMessage(const int &v) { asm { 0xb2, &v : __ASM_SMALL_VALUE + __ASM_SRC_BASIC}; } __nolist void ClearMessage() { asm { 0x90 }; } #define RxIRMessage(n) @(0x21001c + (n)) // 4 bytes #define CONTROLLER_BUTTON1 0x0100 #define CONTROLLER_BUTTON2 0x0200 #define CONTROLLER_BUTTON3 0x0001 #define CONTROLLER_BUTTON4 0x0101 #define CONTROLLER_BUTTON5 0x0201 #define MSG_INDEX 0 #define MSG_COMMAND 1 #define MSG_HI_BYTE 2 #define MSG_LO_BYTE 3 #define LED_MODE_ON 0 #define LED_MODE_BLINK 1 #define LED(n) @(0x160000 + (n)) // LED control registers // LED's may be set/checked manually __nolist void SetLED(const int mode, const int &v) { Set(LED(mode), v); } //-------- //-- This seems to interfeer with program, affect global var? //#define FX_SHUDDER 0 // #define FX_SHOCKED 1 // #define FX_FIRE_AT_BOT 2 //#define FX_TWITTER 3 // //__nolist void Fx_Bead(const int nFx, const int nTimes) //{ // asm { 0xe3, &nFx }; // asm { 0xe3, &nTimes }; // asm { 0x17, 68 }; // asm { 0x01, 2 }; //} //------- //-- This seems to interfeer with program, affect global var? // It is only for eeprom sounds 64-79 //__nolist void PlaySound_Bead(const int nSound, const int nTime) //{ // asm { 0xe3, &nSound }; // asm { 0xe3, &nTime }; // asm { 0x17, 94 }; // asm { 0x01, 2 }; //} //------- // cant use, seems to affect memory behind state machine //#define nSoundFireLaser 7 //__nolist void PlayTone_Bead(const int nTone) //{ // asm { 0xe3, &nTone }; // asm { 0x17, 93 }; // asm { 0x01, 1 }; //} //-------- #define OUT_LEFT OUT_B #define OUT_RIGHT OUT_A //-------- //// defines for move //#define moveZigZag 0x0301 //#define moveShake 0x0302 //#define moveScan 0x0303 //#define moveStep 0x0304 //#define moveStepBack 0x0305 //#define moveSearch 0x0306 //#define moveFakeLeft 0x0307 //#define moveRakeRight 0x0308 //#define moveBugForward 0x0309 //#define moveLazy 0x030a //#define moveWalk 0x030b //#define moveWalkBack 0x030c //#define moveDance 0x030d //// time is in 10ms steps //__nolist void FancyMove (const int move, const int time) //{ // asm { 0xe3, &move }; // asm { 0xe3, &time }; // asm { 0x17, 47 }; // asm { 0x01, 2 }; //} // defines for move #define moveRandomForward 0x0201 #define moveRandomBackward 0x0202 #define moveRandomSpinLeft 0x0203 #define moveRandomSpinRight 0x0204 #define moveRandomTurnLeft 0x0205 #define moveRandomTurnRight 0x0206 #define moveRandomRest 0x0207 // time is in 10ms steps __nolist void RandomMove (const int move, const int time) { asm { 0xe3, &move }; asm { 0xe3, &time }; asm { 0x17, 46 }; asm { 0x01, 2 }; } //-------- // Defines direction Led count #define nDirDown 0 #define nDirUp 1 __nolist void CountDown_Bead(const int nCount,const int nDir,const int nStep) { asm { 0xe3, &nCount } ; asm { 0xe3, &nDir } ; asm { 0xe3, &nStep } ; asm { 0x17, 97 }; asm { 0x01, 3 }; } //-------- /* ----------- end cut outs from spy.nqh ------------------*/ int cmdLoc = 0; int cmdSubLoc = 0; int currentCmd = 0; #define CMD_ARRAY_SIZE 10 // this*3= num commands storable // not sure how big this can be, could try // up to 20, rom says 25global there are 3 // used here plus several local vars int cmds[CMD_ARRAY_SIZE]; // a packed storage array of 5 bit commands task main() { SetEvent(3, SENSOR_1, EVENT_TYPE_PRESSED); SetEvent(4, SENSOR_1, EVENT_TYPE_RELEASED); start programMe; // wait for the sensor to be pressed while(true) { monitor( EVENT_MASK(3) ) { Wait(1000); } catch { break; } } PlaySound(SOUND_CLICK); // wait for sensor to be released while(true) { monitor( EVENT_MASK(4) ) { Wait(1000); } catch { break; } } stop programMe; // put the last shift item correctly if(cmdSubLoc == 0) { cmds[cmdLoc] = cmds[cmdLoc] << 10; } else if (cmdSubLoc == 1) { cmds[cmdLoc] = cmds[cmdLoc] << 5; } // advance loc pointers save last used location cmdSubLoc++; if(cmdSubLoc > 2) { cmdLoc++; cmdSubLoc = 0; } while(true) { CountDown_Bead(6, nDirDown, 40); start lightsCameraAction; // wait for the sensor to be pressed while(true) { monitor( EVENT_MASK(3) ) { Wait(1000); } catch { break; } } PlaySound(SOUND_CLICK); // wait for sensor to be released while(true) { monitor( EVENT_MASK(4) ) { Wait(1000); } catch { break; } } stop lightsCameraAction; Off(OUT_RIGHT+OUT_LEFT); // wait for the sensor to be pressed while(true) { monitor( EVENT_MASK(3) ) { Wait(1000); } catch { break; } } PlaySound(SOUND_CLICK); // wait for sensor to be released while(true) { monitor( EVENT_MASK(4) ) { Wait(1000); } catch { break; } } } } // allow for the bot to be programmed from the 5 function remote task programMe() { int msg = 1000; int lastMsg; int pressCount = 0; SetEvent(2, VLL(), EVENT_TYPE_MSG_RECEIVED); while(true) { ClearMessage(); monitor( EVENT_MASK(2) ) { Wait(100); } catch { lastMsg = msg; msg = RxIRMessage(MSG_HI_BYTE) << 8 | RxIRMessage(MSG_LO_BYTE); // update pressCount if (msg == lastMsg) { pressCount++; if (pressCount > 6) { pressCount = 1; } } else { // a new type of action if(msg == CONTROLLER_BUTTON2) { pressCount = 0; } else { pressCount = 1; // the first press } if(currentCmd != 0) { // advance loc pointers to the next entry in packed array // unless the last cmd was NOP cmdSubLoc++; if(cmdSubLoc > 2) { // move to next in in packed array cmdLoc++; cmdSubLoc = 0; // check if storage array full if(cmdLoc == CMD_ARRAY_SIZE) { SetLED(LED_MODE_ON, 0x2A); // on-off-on-off-on-off stop programMe; // self terminate this task } } else { // move to next 5bit in packed array cmds[cmdLoc] = cmds[cmdLoc] << 5; } } // end if cmds } // end else action // play tone/light lights for pressCount pressFeedback(pressCount); // figure out what the command is switch (msg) { case CONTROLLER_BUTTON1: currentCmd = 6 + pressCount; break; case CONTROLLER_BUTTON2: currentCmd = pressCount; break; case CONTROLLER_BUTTON3: currentCmd = 12 + pressCount; break; case CONTROLLER_BUTTON4: currentCmd = 18 + pressCount; break; case CONTROLLER_BUTTON5: currentCmd = 24 + pressCount; break; default: // should never get here PlaySound(SOUND_CLICK); } // end switch // queue the current action to array cmds[cmdLoc] = (cmds[cmdLoc] & 0x7fe0) | currentCmd; } // end catch } // end while } // end task programMe void PlaySoundLoop(const int &val) { // make laser sound without using PlaySound_Bead int repeater = val; while(repeater > 0) { int lpi = 5000; SendVLL(4); while(lpi > 2000) { PlayTone(lpi, 2); Wait(1); lpi= lpi-150; } repeater--; } } void FxShutterLoop(const int &val) { // shutter the motors rapidly without using Fx_Bead int repeater = val; SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_RIGHT); Rev(OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); while(repeater > 0) { Toggle(OUT_RIGHT+OUT_LEFT); Wait(5); repeater--; } } void pressFeedback(const int &val) { switch (val) { case 0: PlayTone(4699, 30); SetLED(LED_MODE_ON, 0x00); break; case 1: PlayTone(73, 50); SetLED(LED_MODE_ON, 0x01); break; case 2: PlayTone(147, 50); SetLED(LED_MODE_ON, 0x03); break; case 3: PlayTone(294, 50); SetLED(LED_MODE_ON, 0x07); break; case 4: PlayTone(587, 50); SetLED(LED_MODE_ON, 0x27); break; case 5: PlayTone(1175, 50); SetLED(LED_MODE_ON, 0x37); break; case 6: PlayTone(2349, 50); SetLED(LED_MODE_ON, 0x3f); break; default: // should never get here PlaySound(SOUND_DOUBLE_BEEP); SetLED(LED_MODE_ON, 0x10); } // end switch } // Here are the possible commands #define REPEAT_FOREVER 0 #define PAUSE1SEC 1 #define PAUSE3SEC 2 #define PAUSE5SEC 3 #define FIRE_LAZER 4 #define SHAKE 5 #define RANDOM 6 #define LTURN45 7 #define LTURN90 8 #define LTURN180 9 #define LROTATE45 10 #define LROTATE90 11 #define LROTATE180 12 #define RTURN45 13 #define RTURN90 14 #define RTURN180 15 #define RROTATE45 16 #define RROTATE90 17 #define RROTATE180 18 #define FOREWARD_S6IN 19 #define FOREWARD_S1FT 20 #define FOREWARD_S2FT 21 #define FOREWARD_F6IN 22 #define FOREWARD_F1FT 23 #define FOREWARD_F2FT 24 #define BACKWARD_S6IN 25 #define BACKWARD_S1FT 26 #define BACKWARD_S2FT 27 #define BACKWARD_F6IN 28 #define BACKWARD_F1FT 29 #define BACKWARD_F2FT 30 // Here are the tuning params to make distances and turns #define TIME_TURN45 50 #define TIME_TURN90 100 #define TIME_TURN180 150 #define TIME_ROTATE45 50 #define TIME_ROTATE90 100 #define TIME_ROTATE180 150 #define TIME_6IN 50 #define TIME_1FT 100 #define TIME_2FT 200 #define TIME_6IN_SL 100 #define TIME_1FT_SL 200 #define TIME_2FT_SL 400 task lightsCameraAction() { int runLoc = 0; int runSubLoc = 0; SetLED(LED_MODE_ON, 0x3d); while (runLoc < cmdLoc || runSubLoc < cmdSubLoc) { int actualLoc = runSubLoc; int i; for(i=0; i> 10) & 0x1f; } else if(runSubLoc ==1) { currentCmd = (currentCmd >> 5) & 0x1f; } else { currentCmd &= 0x1f; } switch (currentCmd) { // rules of the switch // if dont need motors then make sure they are off // if need one or both, make sure direction and speed set for it/them case REPEAT_FOREVER: Off(OUT_RIGHT+OUT_LEFT); PlayTone(50, 200); Wait(200); runLoc = 0; runSubLoc = -1; // since will increment at bottom of loop break; case PAUSE1SEC: Off(OUT_RIGHT+OUT_LEFT); Wait(100); break; case PAUSE3SEC: Off(OUT_RIGHT+OUT_LEFT); Wait(300); break; case PAUSE5SEC: Off(OUT_RIGHT+OUT_LEFT); Wait(500); break; case FIRE_LAZER: Off(OUT_RIGHT+OUT_LEFT); PlaySoundLoop(6); break; case SHAKE: FxShutterLoop(20); Off(OUT_RIGHT+OUT_LEFT); break; case RANDOM: Off(OUT_RIGHT+OUT_LEFT); switch(Random(6)) { case 0: RandomMove(moveRandomForward,10); break; case 1: RandomMove(moveRandomBackward,10); break; case 2: RandomMove(moveRandomSpinLeft,10); break; case 3: RandomMove(moveRandomSpinRight,10); break; case 4: RandomMove(moveRandomTurnLeft,10); break; case 5: RandomMove(moveRandomTurnRight,10); break; default: RandomMove(moveRandomRest,10); } // end random switch Wait(100); break; case LTURN45: Float(OUT_LEFT); SetPower(OUT_RIGHT,OUT_FULL); Fwd(OUT_RIGHT); On(OUT_RIGHT); Wait(TIME_TURN45); break; case LTURN90: Float(OUT_LEFT); SetPower(OUT_RIGHT,OUT_FULL); Fwd(OUT_RIGHT); On(OUT_RIGHT); Wait(TIME_TURN90); break; case LTURN180: Float(OUT_LEFT); SetPower(OUT_RIGHT,OUT_FULL); Fwd(OUT_RIGHT); On(OUT_RIGHT); Wait(TIME_TURN180); break; case LROTATE45: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_RIGHT); Rev(OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_ROTATE45); break; case LROTATE90: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_RIGHT); Rev(OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_ROTATE90); break; case LROTATE180: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_RIGHT); Rev(OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_ROTATE180); break; case RTURN45: Float(OUT_RIGHT); SetPower(OUT_LEFT,OUT_FULL); Fwd(OUT_LEFT); On(OUT_LEFT); Wait(TIME_TURN45); break; case RTURN90: Float(OUT_RIGHT); SetPower(OUT_LEFT,OUT_FULL); Fwd(OUT_LEFT); On(OUT_LEFT); Wait(TIME_TURN90); break; case RTURN180: Float(OUT_RIGHT); SetPower(OUT_LEFT,OUT_FULL); Fwd(OUT_LEFT); On(OUT_LEFT); Wait(TIME_TURN180); break; case RROTATE45: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_LEFT); Rev(OUT_RIGHT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_ROTATE45); break; case RROTATE90: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_LEFT); Rev(OUT_RIGHT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_ROTATE90); break; case RROTATE180: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_LEFT); Rev(OUT_RIGHT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_ROTATE180); break; case FOREWARD_S6IN: SetPower(OUT_RIGHT+OUT_LEFT,OUT_HALF); Fwd(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_6IN_SL); break; case FOREWARD_S1FT: SetPower(OUT_RIGHT+OUT_LEFT,OUT_HALF); Fwd(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_1FT_SL); break; case FOREWARD_S2FT: SetPower(OUT_RIGHT+OUT_LEFT,OUT_HALF); Fwd(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_2FT_SL); break; case FOREWARD_F6IN: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_6IN); break; case FOREWARD_F1FT: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_1FT); break; case FOREWARD_F2FT: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Fwd(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_2FT); break; case BACKWARD_S6IN: SetPower(OUT_RIGHT+OUT_LEFT,OUT_HALF); Rev(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_6IN_SL); break; case BACKWARD_S1FT: SetPower(OUT_RIGHT+OUT_LEFT,OUT_HALF); Rev(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_1FT_SL); break; case BACKWARD_S2FT: SetPower(OUT_RIGHT+OUT_LEFT,OUT_HALF); Rev(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_2FT_SL); break; case BACKWARD_F6IN: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Rev(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_6IN); break; case BACKWARD_F1FT: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Rev(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_1FT); break; case BACKWARD_F2FT: SetPower(OUT_RIGHT+OUT_LEFT,OUT_FULL); Rev(OUT_RIGHT+OUT_LEFT); On(OUT_RIGHT+OUT_LEFT); Wait(TIME_2FT); break; default: // should never get here if all cmds are implemented Off(OUT_RIGHT+OUT_LEFT); PlaySound(SOUND_CLICK); } // end switch // advance run pointers to the next entry in packed storage array runSubLoc++; if(runSubLoc > 2) { runLoc++; runSubLoc = 0; } } // while run SetLED(LED_MODE_ON, 0x3e); // led pattern on-on-on-on-on-off Off(OUT_RIGHT+OUT_LEFT); PlaySound(SOUND_DOWN); } // end task lightsCameraAction // End program