TinyCHR6dm is a simplified interface for the CH Robotics CHR-6dm AHRS
TinyCHR6dm.cpp
- Committer:
- shimniok
- Date:
- 2011-04-13
- Revision:
- 0:983f66650cd5
File content as of revision 0:983f66650cd5:
#include <mbed.h> #include "TinyCHR6dm.h" #include "string.h" int chksum(uint8 pt, uint8 n, char data[]) { int sum = pt + n; for (int i=0; i < n; i++) { sum += data[i]; } return sum; } //////////////////////////////////////////////////////////////////////////////// // PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////// TinyCHR6dm::TinyCHR6dm(): _dataReady(false), _statusReady(false), _state(WAIT_S) { _state = WAIT_S; } void TinyCHR6dm::parse(char c) { switch (_state) { case WAIT_S : if (debug) debug->printf("WAIT_S\n"); if (c == 's') _state = WAIT_N; break; case WAIT_N : if (debug) debug->printf("WAIT_N\n"); _state = (c == 'n') ? WAIT_P : WAIT_S; break; case WAIT_P : if (debug) debug->printf("WAIT_P\n"); _state = (c == 'p') ? RX_TYPE : WAIT_S; break; case RX_TYPE : pt = c; _state = RX_N; if (debug) debug->printf("PT = %02x\n", pt); break; case RX_N : n = (uint8) c; d = 0; _state = (n < MAX_BYTES) ? RX_PACKET : WAIT_S; if (debug) debug->printf("N = %d\n", n); break; case RX_PACKET : if (debug) debug->printf("RX_PACKET\n"); if (d >= n || d >= MAX_BYTES) { _state = PROCESS_PACKET; } else { if (debug) debug->printf("data[%d] = %02x\n", d, c); data[d++] = c; } break; case PROCESS_PACKET : if (debug) debug->printf("PROCESS_PACKET\n"); process_packet(); _state = WAIT_S; break; default : _state = WAIT_S; break; } return; } float TinyCHR6dm::readYaw(void) { return TinyCHR6dm::_yaw; } bool TinyCHR6dm::dataReady(void) { return TinyCHR6dm::_dataReady; } void TinyCHR6dm::resetReady(void) { TinyCHR6dm::_dataReady = false; } void TinyCHR6dm::send_packet(Serial *serial, uint8 pt, uint8 n, char data[]) { uint checksum; char p[MAX_BYTES]; p[0] = 's'; p[1] = 'n'; p[2] = 'p'; p[3] = (char) pt; p[4] = (char) n; /** Checksum * Datasheet: * After the CHR6-dm receives a full acket, it checks to ensure that the checksum * given in the last two bytes matches the sum of all preceding bytes in the packet. */ checksum = 's'+'n'+'p'+pt+n; for (int i=0; i < n; i++) { p[i+5] = data[i]; checksum += data[i]; } if (debug) debug->printf("Checksum: %04x\n", checksum); p[5+n] = (checksum >> 8); // checksum MSB p[5+n+1] = (checksum & 0x0ff); // checksum LSB if (debug) debug->printf("Checksum: %02x %02x\n", p[5+n], p[5+n+1]); if (serial) { for (int i=0; i < 5+n+2; i++) { serial->putc((int) p[i]); if (debug) debug->printf("%02x\n", p[i]); } } } int TinyCHR6dm::status(void) { _statusReady = false; return _status; } bool TinyCHR6dm::statusReady(void) { return _statusReady; } char *TinyCHR6dm::statusString(int status) { char *s[7] = { "unknown", "PT_COMMAND_COMPLETE", "PT_COMMAND_FAILED", "PT_BAD_CHECKSUM", "PT_BAD_DATA_LENGTH", "PT_UNRECOGNIZED_PACKET", "PT_BUFFER_OVERFLOW" }; return (status >= PT_COMMAND_COMPLETE && status <= PT_BUFFER_OVERFLOW ) ? s[status - PT_COMMAND_COMPLETE + 1] : s[0]; } //////////////////////////////////////////////////////////////////////////////// // PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////// void TinyCHR6dm::process_packet(void) { switch (pt) { /** SENSOR_DATA * Datasheet: * If all channels are active, then data is given in the following order: { yaw, pitch, roll, yaw_rate, * pitch_rate, roll_rate, mag_z, mag_y, mag_x, gyro_z, gyro_y, gyro_x, accel_z, accel_y, accel_x }. * Data bytes D3 and D4 correspond to the yaw angle, D5 and D6 to the pitch angle, etc. Data is * returned as 16-bit two's complement integers. * * When one or more channel is inactive, then the data is returned in the same order, but skipping the * inactive channels. For example, if all magnetic field and rate gyro channels are disabled, then the * data is given in the following order: { yaw, pitch, roll, accel_z, accel_y, accel_x } */ case PT_SENSOR_DATA : if (debug) debug->printf("SENSOR_DATA, YAW FLAG: %02x\n", data[0]&YAW_FLAG); if ((data[0] & YAW_FLAG) == YAW_FLAG) { int yaw = (int) (data[2] << 8 | data[3]); float yawf = 360.0 * (float) yaw / 32768.0; while (yawf < 0) yawf += 360.0; while (yawf >= 360.0) yawf -= 360.0; TinyCHR6dm::_yaw = yawf; if (debug) debug->printf("Yaw: %.2f\n", yawf); } _dataReady = true; break; case PT_COMMAND_COMPLETE : case PT_COMMAND_FAILED : case PT_BAD_CHECKSUM : case PT_BAD_DATA_LENGTH : if (debug) debug->printf("PT = %02x\n", pt); _status = pt; _statusReady = true; break; default : if (debug) debug->printf("Packet type %02x was not processed\n", pt); break; } }