Modified for compatibility with Rev.E. hardware
Fork of AkmSensor by
akmsensormanager.cpp
- Committer:
- tkstreet
- Date:
- 2017-03-24
- Revision:
- 21:966724730ce6
- Parent:
- 15:1238993fd75f
- Child:
- 23:50c98b286e41
File content as of revision 21:966724730ce6:
#include "ble/services/UARTService.h" #include "akdphwinfo.h" #include "akmsensormanager.h" #include "akmhallswitch.h" #include "akmanalogsensor.h" #include "ak09970ctrl.h" #include "ak9750ctrl.h" #include "ak9752ctrl.h" #include "ak7451ctrl.h" #include "ak7401ctrl.h" #include "akmakd.h" #include "debug.h" #include "Message.h" #include "mcp342x.h" #include "I2CNano.h" #include "tca9554a.h" #define MAGNETOMETER_ID 0x0A #define CONV16I(high,low) ((int16_t)(((high) << 8) | (low))) const char* AKM_PRIMARY_ID_STR[] = { "AKD Daughter Cards(SPI)", "Switch, Unipolar", "Switch, Onmipolar", "Latch, Bipolar", "Switch, Dual Output", "Onechip Encoder", "TBD1", "TBD2", "Linear Sensor Legacy", "Current Sensor", "MISC(Analog)", "Linear Sensor", "TBD3", "IR Sensor", "Angle Sensor(SPI)", "AKD Daughter Cards(I2C)" }; AkmSensorManager::AkmSensorManager(SerialNano* com) { serial = com; isEnabledUsb = true; eventCommandReceived = false; eventConnected = false; eventDisconnected = false; } AkmSensorManager::Status AkmSensorManager::init(uint8_t id, uint8_t subid) { primaryId = id; subId = subid; sensor = AkmSensorManager::getAkmSensor(); if(sensor == NULL) return AkmSensorManager::ERROR; return AkmSensorManager::SUCCESS; } void AkmSensorManager::setBleUartService(UARTService* service) { uartService = service; isEnabledBle = true; } void AkmSensorManager::setEventConnected() { eventConnected = true; } void AkmSensorManager::setEventDisconnected() { eventDisconnected = true; } AkmSensor* AkmSensorManager::getAkmSensor() { AkmSensor* sensor = NULL; switch(primaryId){ case AkmSensor::AKM_PRIMARY_ID_AKD_SPI: case AkmSensor::AKM_PRIMARY_ID_AKD_I2C: { if(subId != Ak09970Ctrl::SUB_ID_AK09970){ AkmAkd* akd = new AkmAkd(); sensor = akd; } else{ Ak09970Ctrl* ak09970 = new Ak09970Ctrl(); sensor = ak09970; } break; } case AkmSensor::AKM_PRIMARY_ID_ANGLE_SENSOR: { if(subId == Ak7451Ctrl::SUB_ID_AK7451){ Ak7451Ctrl* ak7451ctrl = new Ak7451Ctrl(); sensor = ak7451ctrl; break; } else if(subId == Ak7401Ctrl::SUB_ID_AK7401){ Ak7401Ctrl* ak7401ctrl = new Ak7401Ctrl(); sensor = ak7401ctrl; break; } break; } case AkmSensor::AKM_PRIMARY_ID_UNIPOLAR: case AkmSensor::AKM_PRIMARY_ID_OMNIPOLAR: case AkmSensor::AKM_PRIMARY_ID_LATCH: case AkmSensor::AKM_PRIMARY_ID_DUAL_OUTPUT: case AkmSensor::AKM_PRIMARY_ID_ONECHIP_ENCODER: { AkmHallSwitch* hallswitch = new AkmHallSwitch(); sensor = hallswitch; break; } case AkmSensor::AKM_PRIMARY_ID_LINEAR_SENSOR_LEGACY: case AkmSensor::AKM_PRIMARY_ID_LINEAR_SENSOR: case AkmSensor::AKM_PRIMARY_ID_CURRENT_SENSOR: case AkmSensor::AKM_PRIMARY_ID_MISC_ANALOG: { AkmAnalogSensor* analogsensor = new AkmAnalogSensor(); sensor = analogsensor; break; } case AkmSensor::AKM_PRIMARY_ID_IR_SENSOR: { if(subId == Ak9750Ctrl::SUB_ID_AK9750){ Ak9750Ctrl* ak9750ctrl = new Ak9750Ctrl(); sensor = ak9750ctrl; }else if(subId == Ak9750Ctrl::SUB_ID_AK9753){ Ak9750Ctrl* ak9753ctrl = new Ak9750Ctrl(); sensor = ak9753ctrl; }else if(subId == Ak9752Ctrl::SUB_ID_AK9752){ Ak9752Ctrl* ak9752ctrl = new Ak9752Ctrl(); sensor = ak9752ctrl; }else{ return NULL; // couldn't find } break; } default: { MSG("#Can't find ID=%d SubID=%d %s\r\n", primaryId, subId, AKM_PRIMARY_ID_STR[primaryId]); return NULL; // couldn't find } } if(sensor->init(primaryId, subId) != AkmSensor::SUCCESS){ MSG("#sensor->init failed. ID=%d SubID=%d %s\r\n", primaryId, subId, AKM_PRIMARY_ID_STR[primaryId]); return NULL; // couldn't find } MSG("#ID=%d SubID=%d %s\r\n", primaryId, subId, AKM_PRIMARY_ID_STR[primaryId]); return sensor; } AkmSensorManager::Status AkmSensorManager::commandReceived(char* buf){ // Construct message Status status = SUCCESS; if ((Message::parse(&msg, buf)) != Message::SUCCESS) { MSG("#Failed to parse message. %s\r\n", buf); status = ERROR; eventCommandReceived = false; }else{ eventCommandReceived = true; } return status; } int16_t AkmSensorManager::getAdcData(MCP342X *mcp3428, MCP342X::AdcChannel ch, MCP342X::SampleSetting s) { const int WAIT_ADC_MS = 1; // Configure channel and trigger. mcp3428->setChannel(ch); mcp3428->setSampleSetting(s); mcp3428->trigger(); // polling data (!blocking) MCP342X::Data data; do { wait_ms(WAIT_ADC_MS); mcp3428->getData(&data); } while(data.st == MCP342X::DATA_NOT_UPDATED); return data.value; } uint8_t AkmSensorManager::getId(PinName pin, uint8_t bits) { MSG("#GetID\r\n"); I2C i2c(I2C_SDA, I2C_SCL); // establish I2C to read ID // ADC MCP342X mcp342x(&i2c, MCP342X::SLAVE_ADDRESS_6EH); // ADC to convert voltage mcp342x.setConversionMode(MCP342X::ONE_SHOT); // Set to single sample MCP342X::AdcChannel ch; if (pin == ANALOG_SENSOR_ID) { // Primary ID ch = MCP342X::ADC_CH1; } else { // pin == ANALOG_SENSOR_ID_SUB ch = MCP342X::ADC_CH2; // Secondary ID } int16_t val = getAdcData(&mcp342x, ch, MCP342X::SAMPLE_240HZ_12BIT); MSG("#12bit ADC Val = %d.\r\n", val); // Voltage boundaries for ID voltage divider system const int16_t VAL_MAX = 3000-2048; // Corresponds to 3V const int16_t VAL_MIN = -2048; // Corresponds to 0V // Convert voltage to ID value uint8_t value = (uint8_t)((val - VAL_MIN)/(float)(VAL_MAX - VAL_MIN) * (1 << bits) + 0.5); MSG("#ID = %d.\r\n", value); return value; } bool AkmSensorManager::isEvent() { return (sensor->isEvent() || eventCommandReceived || eventConnected || eventDisconnected); } void AkmSensorManager::processCommand() { // Gets command contained in the message Message::Command cmd = msg.getCommand(); // Creates a message object to return Message resMsg; // Return message contains the same command resMsg.setCommand(cmd); switch(cmd) { case Message::CMD_GET_FW_VERSION: { resMsg.setArgument(0, FIRMWARE_VERSION); throwMessage(&resMsg); MSG("#FW version is reported.\r\n"); break; } case Message::CMD_GET_MAG_PART: { resMsg.setArgument(0, MAGNETOMETER_ID); throwMessage(&resMsg); MSG("#Mag ID is reported.\r\n"); break; } case Message::CMD_SET_SERIAL_TARGET: { isEnabledBle = msg.getArgument(0)==Message::SW_ON ? true : false; isEnabledUsb = msg.getArgument(1)==Message::SW_ON ? true : false; break; } case Message::CMD_GET_ID: // return Primary ID and Sub ID { resMsg.setArgument(0, primaryId); resMsg.setArgument(1, subId); throwMessage(&resMsg); MSG("#Mag ID is reported.\r\n"); break; } case Message::CMD_STOP_MEASUREMENT: { if( sensor->stopSensor() != AkmSensor::SUCCESS){ resMsg.setArgument(0, 1); }else{ resMsg.setArgument(0, 0); } throwMessage(&resMsg); MSG("#Stop measurement.\r\n"); break; } case Message::CMD_START_MEASUREMENT: { int error_code = AkmSensor::SUCCESS; if(msg.getArgNum() == 0){ error_code = sensor->startSensor(); if( error_code != AkmSensor::SUCCESS ){ MSG("#StartSensor Error. Code=%d\r\n",error_code); } else{ MSG("#Start measurement.\r\n"); } }else if(msg.getArgNum() == 1){ float interval = (float)(1.0 / (float)msg.getArgument(0)); error_code = sensor->startSensor(interval); if( error_code != AkmSensor::SUCCESS ){ MSG("#StartSensor Error. Code=%d\r\n",error_code); } else{ MSG("#Start measurement.\r\n"); } }else{ MSG("#StartSensor Error. Wrong Argument num.\r\n"); } if(error_code == AkmSensor::SUCCESS){ // get initial sensor state for switch type sensors if( primaryId == AkmSensor::AKM_PRIMARY_ID_UNIPOLAR || primaryId == AkmSensor::AKM_PRIMARY_ID_OMNIPOLAR || primaryId == AkmSensor::AKM_PRIMARY_ID_LATCH || primaryId == AkmSensor::AKM_PRIMARY_ID_DUAL_OUTPUT || primaryId == AkmSensor::AKM_PRIMARY_ID_ONECHIP_ENCODER ){ Message temp; sensor->readSensorData(&temp); throwMessage(&temp); } } break; } case Message::CMD_PROGSW_GET_THRESHOLD: case Message::CMD_PROGSW_SET_THRESHOLD: case Message::CMD_PROGSW_GET_READ_COFIGURATION: case Message::CMD_PROGSW_SET_READ_COFIGURATION: case Message::CMD_PROGSW_GET_SWITCH_COFIGURATION: case Message::CMD_PROGSW_SET_SWITCH_COFIGURATION: case Message::CMD_PROGSW_GET_OPERATION_MODE: case Message::CMD_PROGSW_SET_OPERATION_MODE: case Message::CMD_IR_GET_THRESHOLD: case Message::CMD_IR_SET_THRESHOLD: case Message::CMD_IR_GET_HYSTERESIS: case Message::CMD_IR_SET_HYSTERESIS: case Message::CMD_IR_GET_INTERRUPT: case Message::CMD_IR_SET_INTERRUPT: case Message::CMD_IR_GET_OPERATION_MODE: case Message::CMD_IR_SET_OPERATION_MODE: case Message::CMD_IR_GET_THRESHOLD_EEPROM: case Message::CMD_IR_SET_THRESHOLD_EEPROM: case Message::CMD_IR_GET_HYSTERESIS_EEPROM: case Message::CMD_IR_SET_HYSTERESIS_EEPROM: case Message::CMD_IR_GET_INTERRUPT_EEPROM: case Message::CMD_IR_SET_INTERRUPT_EEPROM: case Message::CMD_IR_GET_OPERATION_MODE_EEPROM: case Message::CMD_IR_SET_OPERATION_MODE_EEPROM: case Message::CMD_ANGLE_ZERO_RESET: case Message::CMD_REG_WRITE: case Message::CMD_REG_WRITEN: case Message::CMD_REG_READ: case Message::CMD_REG_READN: case Message::CMD_COMPASS_GET_OPERATION_MODE: case Message::CMD_COMPASS_SET_OPERATION_MODE: { AkmSensor::Status st = sensor->requestCommand(&msg,&resMsg); if( (resMsg.getArgNum() == 0) && (st != AkmSensor::SUCCESS) ) { MSG("#Command failed.\r\n"); }else{ throwMessage(&resMsg); } break; } default: { MSG("#Can't find command.\r\n"); break; } } } AkmSensorManager::Status AkmSensorManager::processEvent() { AkmSensorManager::Status status = AkmSensorManager::SUCCESS; // command received from the host if(eventCommandReceived) { processCommand(); eventCommandReceived = false; // clear the flag } if(sensor->isEvent()) // sensor read data event { Message msg; if( sensor->readSensorData(&msg) != AkmSensor::SUCCESS) status = AkmSensorManager::ERROR; throwMessage(&msg); } if(eventConnected) // BLE connected. Start sensor. { eventConnected = false; // clear the flag MSG("#BLE connected.\r\n"); } if(eventDisconnected) // BLE dis-connected. Stop sensor. { MSG("#BLE dis-connected.\r\n"); if( sensor->stopSensor() != AkmSensor::SUCCESS) status = AkmSensorManager::ERROR; eventDisconnected = false; // clear the flag } return status; } AkmSensorManager::Status AkmSensorManager::throwMessage(const Message *msg) { int len = Message::getMaxMessageLength(); char buf[len]; buf[0] = '$'; // Processes command char cmd = (char)msg->getCommand(); Message::charToAscii(&buf[1], &cmd); // Processes arguments for (int i=0; i < msg->getArgNum(); i++) { char arg = msg->getArgument(i); Message::charToAscii(&buf[3+2*i], &arg); } // Add termination characters, 0x0D(\r), \n and \0, to the end of string int tIdx = 3 + 2 * (msg->getArgNum()); int bufSize = sizeof(buf)/sizeof(buf[0]); if ((tIdx + 3) > (bufSize - 1)) { MSG("#Error: Message data exceeds the buffer.\r\n"); return ERROR; } buf[tIdx++] = CR; // '\r' buf[tIdx++] = LF; // '\n' buf[tIdx] = '\0'; if(isEnabledBle) uartService->writeString(buf); if(isEnabledUsb) serial->printf(buf); return SUCCESS; } char* AkmSensorManager::getSensorName(){ return sensor->getSensorName(); }