Roomba robot class

Dependencies:   mbed

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;
+}
+
+