the firmware for xadow smartstrap for pebble
Dependencies: BufferedSerial USBDevice XadowGPS XadowNFC mbed mbedPebbleSerial IAP
main.cpp
- Committer:
- KillingJacky
- Date:
- 2015-11-06
- Revision:
- 2:281fa9ce92c0
- Parent:
- 1:8d2e8f504ba3
- Child:
- 3:40e13433d193
File content as of revision 2:281fa9ce92c0:
#include "mbed.h" #include "USBSerial.h" #include "BufferedSerial.h" #include "XadowGPS.h" #include "XadowNFC.h" #include "mbedPebbleSerial.h" #include "IAP.h" #define EEP_BLOCK_SIZE 256 #define TARGET_SECTOR 7 // use sector 7 as target sector if it is on LPC11U24 #define TARGET_EEPROM_ADDRESS 64 #define TARGET_EEPROM_ADDRESS 64 #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) #define SERVICE_BAT 0x2003 #define ATTR_BAT_V 0x1001 #define ATTR_BAT_CHG 0x1002 #define SERVICE_GPS 0x2001 //SPEC #define ATTR_GPS_LOCATION 0x0001 //SPEC #define ATTR_GPS_SPEED 0x0003 //spec #define ATTR_GPS_ALTITUDE 0x1001 #define ATTR_GPS_FIX_QUALITY 0x0102 //SPEC #define ATTR_GPS_SATELLITES 0x0101 //spec #define SERVICE_NFC 0x1E01 //NFC is not in spec now, we chose id from experimentation range #define ATTR_NFC_GET_UID 0x1001 #define ATTR_NFC_READ_NDEF 0x1002 #define ATTR_NFC_WRITE_NDEF 0x1003 #define ATTR_NFC_ERASE_NDEF 0x1004 uint8_t nfc_online, gps_online; char eep_block[ EEP_BLOCK_SIZE ]; static uint16_t SUPPORTED_SERVICES[20] = {0}; #define BUFFER_SIZE 200 static uint8_t s_pebble_buffer[GET_PAYLOAD_BUFFER_SIZE(BUFFER_SIZE)]; DigitalOut pin_chg_led_on(P0_2); DigitalOut pin_5v_en(P1_19); AnalogIn ain(P0_11); USBSerial dbg_serial; BufferedSerial serial(P0_19, P0_18); //(tx,rx) I2C i2c(P0_5, P0_4); Timer timer_notify; Timer timer_service; IAP iap; static uint8_t last_tagid[10] = {0}; static uint8_t last_tagid_len = 0; float get_vbat() { return 3.3f*ain*2.25; } void add_services() { int i = 0; /* Raw data service */ SUPPORTED_SERVICES[i++] = 0x0000; /* battery service */ SUPPORTED_SERVICES[i++] = SERVICE_BAT; /* GPS service */ if (gps_online) { SUPPORTED_SERVICES[i++] = SERVICE_GPS; } /* NFC Service*/ if (nfc_online) { SUPPORTED_SERVICES[i++] = SERVICE_NFC; nfc_adapter_init(); } mbedPebbleSerial::begin(s_pebble_buffer, sizeof(s_pebble_buffer), Baud9600, SUPPORTED_SERVICES, i); } int main() { /* init io */ pin_chg_led_on = 0; //pull low to enable charge led //pin_5v_en = 1; //pull high to enable battery to charge pebble /* init uart */ serial.baud(9600); wait(1); dbg_serial.printf("Detecting connected device...\r\n"); /* GPS service */ gps_online = gps_check_online(); dbg_serial.printf("gps online: %d\r\n", gps_online); /* NFC Service*/ nfc_online = nfc_check_online(); dbg_serial.printf("nfc online: %d\r\n", nfc_online); dbg_serial.printf("Service self detecting done!\r\n"); add_services(); /* init i2c */ i2c.frequency(100000); //100khz /* start a timer_notify */ timer_notify.start(); timer_service.start(); /* reload the last configure for charging pebble or not */ int r; r = iap.blank_check( TARGET_SECTOR, TARGET_SECTOR ); dbg_serial.printf( "blank check result = 0x%08X\r\n", r ); iap.prepare( TARGET_SECTOR, TARGET_SECTOR ); if ( r == SECTOR_NOT_BLANK ) { r = iap.read_eeprom( (char*)TARGET_EEPROM_ADDRESS, eep_block, EEP_BLOCK_SIZE ); dbg_serial.printf( "read eep result = 0x%08X, var: %d\r\n", r, eep_block[0] ); pin_5v_en = eep_block[0] > 0?1:0; }else { eep_block[0] = 1; pin_5v_en = 1; r = iap.write_eeprom( eep_block, (char*)TARGET_EEPROM_ADDRESS, EEP_BLOCK_SIZE ); dbg_serial.printf( "write eep result = 0x%08X\r\n", r ); } size_t length; uint16_t service_id; uint16_t attribute_id; RequestType type; while(1) { if(mbedPebbleSerial::feed(&service_id, &attribute_id, &length, &type)) { // we have a raw data frame to process if ((service_id == 0) && (attribute_id == 0)) { ; } else if (service_id == SERVICE_BAT) { if ((attribute_id == ATTR_BAT_V) && (type == RequestTypeRead)) { float vbat_f = get_vbat(); uint16_t vbat = (uint16_t)(vbat_f * 100); dbg_serial.printf("ATTR_BAT_V, vbat: %f, %d\r\n", vbat_f, vbat); memcpy(s_pebble_buffer, &vbat, sizeof(vbat)); mbedPebbleSerial::write(true, s_pebble_buffer, sizeof(vbat)); } else if((attribute_id == ATTR_BAT_CHG) && (type == RequestTypeWrite)) { uint8_t enable_charge; memcpy(&enable_charge, s_pebble_buffer, sizeof(enable_charge)); dbg_serial.printf("ATTR_BAT_CHG: %d\r\n", enable_charge); pin_5v_en = enable_charge; mbedPebbleSerial::write(true, NULL, 0); eep_block[0] = enable_charge; r = iap.write_eeprom( eep_block, (char*)TARGET_EEPROM_ADDRESS, EEP_BLOCK_SIZE ); dbg_serial.printf( "write %d to eep result = 0x%08X\r\n", enable_charge, r ); } else { mbedPebbleSerial::write(false, NULL, 0); } } else if (service_id == SERVICE_GPS && gps_online) { if (attribute_id == ATTR_GPS_LOCATION && type == RequestTypeRead) { float lat_f, lon_f; lat_f = gps_get_latitude(); lon_f = gps_get_longitude(); int32_t lat = (int32_t)(lat_f * (10000000)); int32_t lon = (int32_t)(lon_f * (10000000)); dbg_serial.printf("ATTR_GPS_LOCATION: %f, %f ---- %d, %d\r\n", lat_f,lon_f,lat,lon); memcpy(s_pebble_buffer, &lat, sizeof(lat)); memcpy(s_pebble_buffer+sizeof(lat), &lon, sizeof(lon)); mbedPebbleSerial::write(true, s_pebble_buffer, sizeof(lat)*2); } else if (attribute_id == ATTR_GPS_SPEED && type == RequestTypeRead) { float v = gps_get_speed(); uint16_t speed = (uint16_t)(v * 100); dbg_serial.printf("ATTR_GPS_SPEED: %f, %d\r\n", v,speed); memcpy(s_pebble_buffer, &speed, sizeof(speed)); mbedPebbleSerial::write(true, s_pebble_buffer, sizeof(speed)); } else if (attribute_id == ATTR_GPS_ALTITUDE && type == RequestTypeRead) { float alt_f = gps_get_altitude(); uint16_t alt = (uint16_t)(alt_f * 100); dbg_serial.printf("ATTR_GPS_ALTITUDE: %f, %d\r\n", alt_f,alt); memcpy(s_pebble_buffer, &alt, sizeof(alt)); mbedPebbleSerial::write(true, s_pebble_buffer, sizeof(alt)); } else if (attribute_id == ATTR_GPS_FIX_QUALITY && type == RequestTypeRead) { uint8_t fixq = gps_get_position_fix(); fixq = (fixq>8)?0:fixq; dbg_serial.printf("ATTR_GPS_FIX_QUALITY: %d\r\n", fixq); memcpy(s_pebble_buffer, &fixq, sizeof(fixq)); mbedPebbleSerial::write(true, s_pebble_buffer, sizeof(fixq)); } else if (attribute_id == ATTR_GPS_SATELLITES && type == RequestTypeRead) { uint8_t sat = gps_get_sate_in_veiw(); dbg_serial.printf("ATTR_GPS_SATELLITES: %d\r\n", sat); memcpy(s_pebble_buffer, &sat, sizeof(sat)); mbedPebbleSerial::write(true, s_pebble_buffer, sizeof(sat)); }else { mbedPebbleSerial::write(false, NULL, 0); } } else if (service_id == SERVICE_NFC && nfc_online) { if (attribute_id == ATTR_NFC_GET_UID && type == RequestTypeRead) { /*uint8_t *uid = nfc_adapter_get_uid(); uint8_t len = uid[1]; dbg_serial.printf("GET_NFC_TAGID: "); for(int i=2; i<2+len; i++) { dbg_serial.printf("%02X ", uid[i]); } dbg_serial.printf("\r\n"); memcpy((char *)s_pebble_buffer, (char *)(uid+2), len); mbedPebbleSerial::write(true, s_pebble_buffer, len);*/ dbg_serial.printf("GET_NFC_TAGID: "); for(int i=0; i<last_tagid_len; i++) { dbg_serial.printf("%02X ", last_tagid[i]); } dbg_serial.printf("\r\n"); memcpy((char *)s_pebble_buffer, (char *)last_tagid, last_tagid_len); mbedPebbleSerial::write(true, s_pebble_buffer, last_tagid_len); } else if (attribute_id == ATTR_NFC_READ_NDEF && type == RequestTypeRead) { memset(s_pebble_buffer, 0, sizeof(s_pebble_buffer)); uint8_t *ndef = nfc_adapter_read(); uint8_t len = ndef[1]; len = min(len, BUFFER_SIZE); dbg_serial.printf("GET_NFC_NDEF: "); for(int i=2; i<2+len; i++) { dbg_serial.printf("%02X ", ndef[i]); } dbg_serial.printf("\r\n"); memcpy((char *)s_pebble_buffer, (char *)(ndef+2), len); mbedPebbleSerial::write(true, s_pebble_buffer, len); } else if((attribute_id == ATTR_NFC_WRITE_NDEF) && (type == RequestTypeWrite)) { if (*(s_pebble_buffer + length) != '\0' && length < BUFFER_SIZE) *(s_pebble_buffer + length) = '\0'; dbg_serial.printf("ATTR_NFC_WRITE_NDEF: "); for(int i=0; i<length; i++) { dbg_serial.printf("%02X ", s_pebble_buffer[i]); } dbg_serial.printf("\r\n"); nfc_adapter_write(s_pebble_buffer, length); mbedPebbleSerial::write(true, NULL, 0); } else if((attribute_id == ATTR_NFC_ERASE_NDEF) && (type == RequestTypeWrite)) { dbg_serial.printf("ATTR_NFC_ERASE_NDEF\r\n"); nfc_adapter_erase(); mbedPebbleSerial::write(true, NULL, 0); } else { mbedPebbleSerial::write(false, NULL, 0); } }else { mbedPebbleSerial::write(false, NULL, 0); } } //check if nfc tagid changed if (timer_notify.read_ms() > 1000 && nfc_online) { timer_notify.reset(); uint8_t *uid = nfc_adapter_get_uid(); uint8_t len = uid[1]; dbg_serial.printf("Check NFC: "); if (len > 0) { for(int i=2; i<2+len; i++) { dbg_serial.printf("%02X ", uid[i]); } } dbg_serial.printf("\r\n"); len = min(len, 10); if (memcmp(last_tagid, uid+2, len) != 0 || len != last_tagid_len) { mbedPebbleSerial::notify(SERVICE_NFC, ATTR_NFC_GET_UID); if (len == 0) { memset(last_tagid, 0, sizeof(last_tagid)); }else { memcpy(last_tagid, uid+2, len); } last_tagid_len = len; //changed, notify } } //check services' availability if (timer_service.read() > 5) { timer_service.reset(); uint8_t state_gps = gps_check_online(); uint8_t state_nfc = nfc_check_online(); uint8_t mark = 0; if (state_gps != gps_online) { gps_online = state_gps; mark = 1; dbg_serial.printf("gps state: %d \r\n", gps_online); } if (state_nfc != nfc_online) { nfc_online = state_nfc; mark = 1; dbg_serial.printf("nfc state: %d \r\n", nfc_online); } if (mark) { add_services(); } dbg_serial.printf("check services --- %d, %d \r\n", gps_online, nfc_online); } } //while 1 }