Andy K
/
Roomba
Roomba robot class
Diff: Roomba/Roomba.cpp
- Revision:
- 0:b26b94a6a065
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Roomba/Roomba.cpp Wed Dec 01 19:20:43 2010 +0000 @@ -0,0 +1,127 @@ +/* + Copyright (c) 2010 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + @file Roomba.cpp + @purpose http://mbed.org/forum/mbed/topic/1476 + @version 0.1 (untested) + @date Dec 2010 + @author Andy Kirkham + @see http://mbed.org/forum/mbed/topic/1476 +*/ + +#include "Roomba.h" + +void +Roomba::init(PinName tx, PinName rx) +{ + state = Idle; + uart = new MODSERIAL(tx, rx); + tick = new Ticker; + uart->attach(this, &Roomba::cbSerial, MODSERIAL::RxIrq); + tick->attach(this, &Roomba::cbTicker, 0.1); +} + +int +Roomba::command(RoombaState cmd, int opts, char *opt, bool block) { + if (state != Idle) return (int)NotIdle; + + // Impose our state on teh system. Use a loop to + // make sure no interrupt "nips in" and alters + // the state machine. + while (state != cmd) { + state = cmd; + } + + // Send command. + uart->putc(cmd); + + // Send any additional option bytes. + if (opts > 0) { + for (int i = 0; i < opts; i++) { + uart->putc(opt[i]); + } + } + + // Wait until the serial characters have left the Mbed. + // Only do this is arg block is true (which is the default). + if (block) while (uart->txIsBusy() || uart->txBufferGetCount() != 0); + + // Return state back to idle + state = Idle; + + return cmd; +} + +int +Roomba::cmdSensors(CallType type) +{ + if (type == Invoke) { + if (state != Idle) { + return (int)NotIdle; + } + + // We are already in interrupt context + // so no need to loop here, nothing is + // going to interrupt us. + state = CmdSensors; + + // Flush the buffers and send teh command+opt + uart->rxBufferFlush(); + uart->putc(CmdSensors); + uart->putc(0); + + // Leave state in CmdSensors so nothing else can use the + // serial port until the CmdSensors has completed. See + // below where the command end is detected and terminated. + } + + if (type == SerialCallback) { + if (state == CmdSensors && uart->rxBufferGetCount() == 26) { + sensors8bit[bumpsWheeldrops] = uart->getc(); + sensors8bit[wall] = uart->getc(); + sensors8bit[cliffLeft] = uart->getc(); + sensors8bit[cliffFrontLeft] = uart->getc(); + sensors8bit[cliffFrontRight] = uart->getc(); + sensors8bit[cliffRight] = uart->getc(); + sensors8bit[virtualWall] = uart->getc(); + sensors8bit[motorOvercurrents] = uart->getc(); + sensors8bit[dirtDetectorLeft] = uart->getc(); + sensors8bit[dirtDetectorRight] = uart->getc(); + sensors8bit[remoteControlCommand] = uart->getc(); + sensors8bit[buttons] = uart->getc(); + sensors16bit[distance] = (uart->getc() << 8) | uart->getc(); + sensors16bit[angle] = (uart->getc() << 8) | uart->getc(); + sensors8bit[chargingState] = uart->getc(); + sensors16bit[voltage] = (uart->getc() << 8) | uart->getc(); + sensors16bit[current] = (uart->getc() << 8) | uart->getc(); + sensors8bit[temperature] = uart->getc(); + sensors16bit[charge] = (uart->getc() << 8) | uart->getc(); + sensors16bit[capacity] = (uart->getc() << 8) | uart->getc(); + + // All done, release teh serial port back to idle. + state = Idle; + } + } + + return Ok; +} + +