Fork of EnvoyNespressoEndpoint that uses ColorDetectorV2
Dependencies: ColorDetectorV2 ExternalFlashClient SNICInterface mbed-rtos mbed nsdl
Fork of EnvoyNespressoEndpoint by
Revision 0:0782597771bc, committed 2015-04-15
- Comitter:
- bridadan
- Date:
- Wed Apr 15 19:31:33 2015 +0000
- Child:
- 1:10534b1c83d4
- Commit message:
- Initial commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ColorDetector/ColorDetector.cpp Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,90 @@ +#include "ColorDetector.h" + +/** +* Constructor. +* +* @param sensor Pointer to instantiated and powered up Grove colour sensor. +* @param threshold Total change in channel values needed to trigger a "change" event. +* This will start to save samples for later use until the total change in channel values dips below this threshold. +* @param samplesPerReading Specifies the number of samples to take per sample() call. +*/ +ColorDetector::ColorDetector(GroveColourSensor *sensor, uint16_t threshold, uint16_t samplesPerReading) + :sensor(sensor), threshold(threshold), changeDetected(false), curBuffPointer(0), + samplesPerReading(samplesPerReading) { + // Empty +} + + +/** +* Takes the specified number of samples and returns the average channel values. +* +* @param numSamples Number of samples to take. +*/ +RGBC ColorDetector::takeSamples(uint16_t numSamples) { + uint32_t tot_r = 0; + uint32_t tot_g = 0; + uint32_t tot_b = 0; + uint32_t tot_c = 0; + + for (uint32_t i = curBuffPointer; (i < curBuffPointer + numSamples) && (i < CD_BUFF_LEN); i++) { + sensor->readBlock(sample_buf + i); + tot_r += sample_buf[i].ch.red; + tot_g += sample_buf[i].ch.green; + tot_b += sample_buf[i].ch.blue; + tot_c += sample_buf[i].ch.clear; + } + + curBuffPointer += numSamples; + + RGBC ret; + ret.ch.red = tot_r / numSamples; + ret.ch.green = tot_g / numSamples; + ret.ch.blue = tot_b / numSamples; + ret.ch.clear = tot_c / numSamples; + + return ret; +} + +/** +* This establishes the average "resting" channel values. This should be called before calling sample(). +*/ +void ColorDetector::setBaseline() { + baselineAvg = takeSamples(samplesPerReading); +} + +/** +* Takes samples from sensor, keeping track if the change in color rises above the threshold. +* If a change is detected and then returns to the baseline average or it reaches the max number of samples, +* this will return a value great than 0 that indicates how many samples are in the buffer. +* If no change is detected, 0 is returned. +*/ +int ColorDetector::sample() { + int retVal = 0; + RGBC avg = takeSamples(samplesPerReading); + + uint32_t totalDiff = 0; + + for (int i = 0; i < 4; i++) { + totalDiff += abs((int)avg.data[i] - baselineAvg.data[i]); + } + + if (totalDiff > threshold && curBuffPointer < CD_BUFF_LEN) { + changeDetected = true; + } else { + if (changeDetected) { + retVal = curBuffPointer; + } + + changeDetected = false; + curBuffPointer = 0; + } + + return retVal; +} + +/** +* Returns a pointer to the sample buffer (does not change). +*/ +RGBC* ColorDetector::getBuffer() { + return sample_buf; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ColorDetector/ColorDetector.h Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,29 @@ +#ifndef _COLOR_DETECTOR_H_ +#define _COLOR_DETECTOR_H_ + +#include "mbed.h" +#include "GroveColourSensor.h" + +#define CD_BUFF_LEN 512 + + +class ColorDetector { +public: + ColorDetector(GroveColourSensor *sensor, uint16_t threshold); + void setBaseline(); + int sample(); + RGBC* getBuffer(); + +private: + RGBC sample_buf[CD_BUFF_LEN]; + GroveColourSensor *sensor; + uint16_t threshold; + RGBC baselineAvg; + uint32_t curBuffPointer; + bool changeDetected; + uint16_t samplesPerReading; + + RGBC takeSamples(uint16_t numSamples); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ColorDetector/GroveColourSensor.lib Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/bridadan/code/GroveColourSensor/#50cb56828ab9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetInterface.lib Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,1 @@ +EthernetInterface#2fc406e2553f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dbg.h Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,17 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#include "nsdl_support.h" +#include "mbed.h" + +//Debug is disabled by default +#define DEBUG 1 + +#if (DEBUG) +extern Serial pc; +#define NSDL_DEBUG(x, ...) pc.printf("[NSDL_DEBUG: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__); +#else +#define NSDL_DEBUG(x, ...) +#endif + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,164 @@ +#include "mbed.h" +#include "EthernetInterface.h" +#include "nsdl_support.h" +#include "dbg.h" +#include "GroveColourSensor.h" +#include "ColorDetector.h" +#include "color_detector.h" + +Serial pc(USBTX, USBRX); // tx, rx + +// **************************************************************************** +// Configuration section + +// Ethernet configuration +/* Define this to enable DHCP, otherwise manual address configuration is used */ +#define DHCP + +/* Manual IP configurations, if DHCP not defined */ +#define IP "0.0.0.0" +#define MASK "255.255.255.0" +#define GW "0.0.0.0" + +// NSP configuration +/* Change this IP address to that of your mbed Device Server installation */ +static const char* NSP_ADDRESS = "10.112.30.70"; +static const int NSP_PORT = 5683; +char endpoint_name[] = "nespresso-client"; +uint8_t ep_type[] = {"mbed_device"}; +uint8_t lifetime_ptr[] = {"1200"}; + +// **************************************************************************** +// Ethernet initialization + +EthernetInterface eth; + +static void ethernet_init() +{ + // Initialize network +#ifdef DHCP + NSDL_DEBUG("DHCP in use\r\n"); + eth.init(); +#else + eth.init(IP, MASK, GW); +#endif + if(eth.connect(30000) == 0) + pc.printf("Connect OK\n\r"); + + NSDL_DEBUG("IP Address:%s ", eth.getIPAddress()); +} + +// **************************************************************************** +// NSP initialization + +UDPSocket server; +Endpoint nsp; + +static void nsp_init() +{ + server.init(); + server.bind(NSP_PORT); + + nsp.set_address(NSP_ADDRESS, NSP_PORT); + + NSDL_DEBUG("name: %s", endpoint_name); + NSDL_DEBUG("NSP=%s - port %d\n", NSP_ADDRESS, NSP_PORT); +} + +// **************************************************************************** +// Resource creation + +static int create_resources() +{ + sn_nsdl_resource_info_s *resource_ptr = NULL; + sn_nsdl_ep_parameters_s *endpoint_ptr = NULL; + + NSDL_DEBUG("Creating resources"); + + // Create resources + resource_ptr = (sn_nsdl_resource_info_s*)nsdl_alloc(sizeof(sn_nsdl_resource_info_s)); + if(!resource_ptr) + return 0; + memset(resource_ptr, 0, sizeof(sn_nsdl_resource_info_s)); + + resource_ptr->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)nsdl_alloc(sizeof(sn_nsdl_resource_parameters_s)); + if(!resource_ptr->resource_parameters_ptr) + { + nsdl_free(resource_ptr); + return 0; + } + memset(resource_ptr->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s)); + + // Dynamic resources + create_color_detector_resource(resource_ptr); + + // Register with NSP + endpoint_ptr = nsdl_init_register_endpoint(endpoint_ptr, (uint8_t*)endpoint_name, ep_type, lifetime_ptr); + if(sn_nsdl_register_endpoint(endpoint_ptr) != 0) + pc.printf("NSP registering failed\r\n"); + else + pc.printf("NSP registering OK\r\n"); + nsdl_clean_register_endpoint(&endpoint_ptr); + + nsdl_free(resource_ptr->resource_parameters_ptr); + nsdl_free(resource_ptr); + return 1; +} + +// **************************************************************************** +// Program entry point + +int main() +{ + NSDL_DEBUG("mbed Nespresso Demo\n"); + + // Begin Color Sensor init + + // First, ensure I2C bus is released by toggling clock (fixes reset errors) + DigitalOut scl_dummy(I2C_SCL); + + for (int i = 0; i < 100; i++) { + scl_dummy = !scl_dummy; + wait_us(2); + } + + // Next, initialize I2C + I2C i2c(I2C_SDA, I2C_SCL); + + // Create color sensor instance + GroveColourSensor colorSensor(&i2c); + + // Various config + colorSensor.powerUp(); + colorSensor.setGain(1); + colorSensor.setBlockRead(); + + // Create color detector + ColorDetector detector(&colorSensor, 50); + detector.setBaseline(); + + // Pass reference to color detector + set_color_detector(&detector); + + // Initialize Ethernet interface first + ethernet_init(); + + // Initialize NSP node + nsp_init(); + + // Initialize NSDL stack + nsdl_init(); + + // Create NSDL resources + create_resources(); + + nsdl_event_loop_init(); + + while(true) { + // Check if any nsdl events need to be handled + nsdl_event_loop_run_once(); + + // Sample the color detector and potentially send samples to mDS + run_color_detector(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,1 @@ +mbed-rtos#d3d0e710b443
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/433970e64889 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nsdl_lib.lib Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,1 @@ +nsdl_lib#388450b1e776
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nsdl_support.cpp Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,175 @@ +// NSDL library support functions + +#include "mbed.h" +#include "nsdl_support.h" +#include "mbed.h" +#include "rtos.h" +#include "EthernetInterface.h" + +extern Serial pc; +extern EthernetInterface eth; +extern Endpoint nsp; +extern UDPSocket server; +extern char endpoint_name[16]; +extern uint8_t ep_type[]; +extern uint8_t lifetime_ptr[]; + +// Registration update variables +sn_nsdl_ep_parameters_s *endpoint_ptr = NULL; +Ticker registration_updater; +bool update_registration = false; + +// NSDL loop variables +sn_nsdl_addr_s received_packet_address; +uint8_t received_address[4]; +char buffer[1024]; +Endpoint from; + +/* The number of seconds between NSP registration messages */ +#define RD_UPDATE_PERIOD 60 + +void *nsdl_alloc(uint16_t size) +{ + return malloc(size); +} + +void nsdl_free(void* ptr_to_free) +{ + free(ptr_to_free); +} + +/* + * Create a static resoure + * Only get is allowed + */ +void nsdl_create_static_resource(sn_nsdl_resource_info_s *resource_structure, uint16_t pt_len, uint8_t *pt, uint16_t rpp_len, uint8_t *rpp_ptr, uint8_t *rsc, uint16_t rsc_len) +{ + resource_structure->access = SN_GRS_GET_ALLOWED; + resource_structure->mode = SN_GRS_STATIC; + resource_structure->pathlen = pt_len; + resource_structure->path = pt; + resource_structure->resource_parameters_ptr->resource_type_len = rpp_len; + resource_structure->resource_parameters_ptr->resource_type_ptr = rpp_ptr; + resource_structure->resource = rsc; + resource_structure->resourcelen = rsc_len; + sn_nsdl_create_resource(resource_structure); +} + +void nsdl_create_dynamic_resource(sn_nsdl_resource_info_s *resource_structure, uint16_t pt_len, uint8_t *pt, uint16_t rpp_len, uint8_t *rpp_ptr, uint8_t is_observable, sn_grs_dyn_res_callback_t callback_ptr, int access_right) +{ + resource_structure->access = (sn_grs_resource_acl_e)access_right; + resource_structure->resource = 0; + resource_structure->resourcelen = 0; + resource_structure->sn_grs_dyn_res_callback = callback_ptr; + resource_structure->mode = SN_GRS_DYNAMIC; + resource_structure->pathlen = pt_len; + resource_structure->path = pt; + resource_structure->resource_parameters_ptr->resource_type_len = rpp_len; + resource_structure->resource_parameters_ptr->resource_type_ptr = rpp_ptr; + resource_structure->resource_parameters_ptr->observable = is_observable; + sn_nsdl_create_resource(resource_structure); +} + +sn_nsdl_ep_parameters_s* nsdl_init_register_endpoint(sn_nsdl_ep_parameters_s *endpoint_structure, uint8_t* name, uint8_t* typename_ptr, uint8_t *lifetime_ptr) +{ + if (NULL == endpoint_structure) + { + endpoint_structure = (sn_nsdl_ep_parameters_s*)nsdl_alloc(sizeof(sn_nsdl_ep_parameters_s)); + } + if (endpoint_structure) + { + memset(endpoint_structure, 0, sizeof(sn_nsdl_ep_parameters_s)); + endpoint_structure->endpoint_name_ptr = name; + endpoint_structure->endpoint_name_len = strlen((char*)name); + endpoint_structure->type_ptr = typename_ptr; + endpoint_structure->type_len = strlen((char*)typename_ptr); + endpoint_structure->lifetime_ptr = lifetime_ptr; + endpoint_structure->lifetime_len = strlen((char*)lifetime_ptr); + } + return endpoint_structure; +} + +void nsdl_clean_register_endpoint(sn_nsdl_ep_parameters_s **endpoint_structure) +{ + if (*endpoint_structure) + { + nsdl_free(*endpoint_structure); + *endpoint_structure = NULL; + } +} + +static uint8_t tx_cb(sn_nsdl_capab_e protocol, uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr) +{ + pc.printf("TX callback!\n\rSending %d bytes\r\n", data_len); + + if(server.sendTo(nsp, (char*)data_ptr, data_len) != data_len) + pc.printf("sending failed\n\r"); + + return 1; +} + +static uint8_t rx_cb(sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr) +{ + pc.printf("RX callback!\r\n"); + return 0; +} + +void registration_ticker_func() { + update_registration = true; +} + +static void registration_update() +{ + endpoint_ptr = nsdl_init_register_endpoint(endpoint_ptr, (uint8_t*)endpoint_name, ep_type, lifetime_ptr); + if(sn_nsdl_register_endpoint(endpoint_ptr) != 0) + pc.printf("NSP re-registering failed\r\n"); + else + pc.printf("NSP re-registering OK\r\n"); + nsdl_clean_register_endpoint(&endpoint_ptr); +} + +void nsdl_init() +{ + uint8_t nsp_addr[4]; + sn_nsdl_mem_s memory_cbs; + + /* Initialize libNsdl */ + memory_cbs.sn_nsdl_alloc = &nsdl_alloc; + memory_cbs.sn_nsdl_free = &nsdl_free; + if(sn_nsdl_init(&tx_cb, &rx_cb, &memory_cbs) == -1) + pc.printf("libNsdl init failed\r\n"); + else + pc.printf("libNsdl init done\r\n"); + + /* Set nsp address for library */ + set_NSP_address(nsp_addr, 5683, SN_NSDL_ADDRESS_TYPE_IPV4); +} + +void nsdl_event_loop_init() { + server.set_blocking(false, 200); + memset(&received_packet_address, 0, sizeof(sn_nsdl_addr_s)); + received_packet_address.addr_ptr = received_address; + + registration_updater.attach(®istration_ticker_func, RD_UPDATE_PERIOD); +} + +void nsdl_event_loop_run_once() +{ + if (update_registration) { + update_registration = false; + registration_update(); + } + + int n = server.receiveFrom(from, buffer, sizeof(buffer)); + + if (n < 0) + { + pc.printf("Socket error\n\r"); + } + else + { + sn_nsdl_process_coap((uint8_t*)buffer, n, &received_packet_address); + } +} + + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nsdl_support.h Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,25 @@ +// Support functions for the NSDL library + +#ifndef NSDL_SUPPORT_H +#define NSDL_SUPPORT_H + +#include "mbed.h" +#include <stdint.h> +#include "sn_nsdl.h" +#include "sn_coap_header.h" +#include "sn_coap_protocol.h" +#include "sn_nsdl_lib.h" + +typedef uint8_t (*sn_grs_dyn_res_callback_t)(sn_coap_hdr_s *, sn_nsdl_addr_s *, sn_proto_info_s *); + +extern "C" void *nsdl_alloc(uint16_t size); +extern "C" void nsdl_free(void* ptr_to_free); +void nsdl_create_static_resource(sn_nsdl_resource_info_s *resource_structure, uint16_t pt_len, uint8_t *pt, uint16_t rpp_len, uint8_t *rpp_ptr, uint8_t *rsc, uint16_t rsc_len); +void nsdl_create_dynamic_resource(sn_nsdl_resource_info_s *resource_structure, uint16_t pt_len, uint8_t *pt, uint16_t rpp_len, uint8_t *rpp_ptr, uint8_t is_observable, sn_grs_dyn_res_callback_t callback_ptr, int access_right); +sn_nsdl_ep_parameters_s* nsdl_init_register_endpoint(sn_nsdl_ep_parameters_s *endpoint_structure, uint8_t* name, uint8_t* ypename_ptr, uint8_t *lifetime_ptr); +void nsdl_clean_register_endpoint(sn_nsdl_ep_parameters_s **endpoint_structure); +void nsdl_init(); +void nsdl_event_loop_init(); +void nsdl_event_loop_run_once(); + +#endif // NSDL_SUPPORT_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/color_detector.cpp Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,89 @@ +#include "mbed.h" +#include "nsdl_support.h" +#include "payload.h" +#include "ColorDetector.h" + +#define RESOURCE_ID "sensor/capsule" + +extern Serial pc; +/* stored data for observable resource */ +static uint8_t obs_number = 0; +static uint8_t *obs_token_ptr = NULL; +static uint8_t obs_token_len = 0; + +ColorDetector *g_detector; +static Payload g_payload; + +void set_color_detector(ColorDetector *detector) { + g_detector = detector; +} + +void run_color_detector() +{ + if (obs_number == 0 && obs_token_ptr == NULL) + pc.printf("ERROR: obs_number: %d, obs_token_ptr: %0x%08x\r\n", obs_number, obs_token_ptr); + + obs_number++; + + // Take samples from color detector + int samples_captured = g_detector->sample(); + + // If a capsule was detected, a number greater than 0 is returned + if (samples_captured > 0) { + // Build payload from color detector buffer + g_payload.build(g_detector->getBuffer(), samples_captured); + + // Send payload to mDS + int result = sn_nsdl_send_observation_notification(obs_token_ptr, obs_token_len, g_payload.raw_bytes(), g_payload.raw_bytes_size(), &obs_number, 1, COAP_MSG_TYPE_NON_CONFIRMABLE, 0); + + pc.printf("Observation send %s. [samples: %d, bytes: %d]\r\n", result == 0 ? "failed" : "succeeded", samples_captured, g_payload.raw_bytes_size()); + } +} + +/* Only GET method allowed */ +static uint8_t resource_cb(sn_coap_hdr_s *received_coap_ptr, sn_nsdl_addr_s *address, sn_proto_info_s * proto) +{ + sn_coap_hdr_s *coap_res_ptr = 0; + + coap_res_ptr = sn_coap_build_response(received_coap_ptr, COAP_MSG_CODE_RESPONSE_CONTENT); + + coap_res_ptr->payload_len = g_payload.raw_bytes_size(); + coap_res_ptr->payload_ptr = g_payload.raw_bytes(); + + if(received_coap_ptr->token_ptr) + { + if(obs_token_ptr) + { + free(obs_token_ptr); + obs_token_ptr = 0; + } + obs_token_ptr = (uint8_t*)malloc(received_coap_ptr->token_len); + if(obs_token_ptr) + { + memcpy(obs_token_ptr, received_coap_ptr->token_ptr, received_coap_ptr->token_len); + obs_token_len = received_coap_ptr->token_len; + } + } + + if(received_coap_ptr->options_list_ptr->observe) + { + coap_res_ptr->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s)); + memset(coap_res_ptr->options_list_ptr, 0, sizeof(sn_coap_options_list_s)); + coap_res_ptr->options_list_ptr->observe_ptr = &obs_number; + coap_res_ptr->options_list_ptr->observe_len = 1; + obs_number++; + } + + sn_nsdl_send_coap_message(address, coap_res_ptr); + + coap_res_ptr->options_list_ptr->observe_ptr = 0; + sn_coap_parser_release_allocated_coap_msg_mem(coap_res_ptr); + + return 0; +} + +int create_color_detector_resource(sn_nsdl_resource_info_s *resource_ptr) +{ + nsdl_create_dynamic_resource(resource_ptr, sizeof(RESOURCE_ID) - 1, (uint8_t*)RESOURCE_ID, 0, 0, 1, &resource_cb, SN_GRS_GET_ALLOWED); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/color_detector.h Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,13 @@ +// Nespresso resource implementation + +#ifndef _COLOR_DETECTOR_RESOURCE_H_ +#define _COLOR_DETECTOR_RESOURCE_H_ + +#include "ColorDetector.h" +#include "nsdl_support.h" + +void set_color_detector(ColorDetector *detector); +void run_color_detector(); +int create_color_detector_resource(sn_nsdl_resource_info_s *resource_ptr); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/payload.cpp Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,78 @@ +/* + * Builds the payload to send to the server. + * + * Copyright (c) 2014 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <mbed.h> +#include "payload.h" + +// Maximum number of samples to include in the payload. +// Defined such that the payload fits within one UDP packet. +#define MAX_SAMPLES 300 + +Payload::Payload() : + m_mdb_bytes(0) +{ +} + +// +// Build the payload. The payload is defined by the Payload::MeanDeltaBuffer struct +// and consists of: +// * number of samples (32 bits) +// * mean of red, green, blue channels (32 bits each) +// * difference of sample to mean for red, green, blue channels (1 byte each) +// +// This encoding can store ~300 samples in a one UDP packet. +// +void Payload::build(const RGBC* samples, int sample_count) +{ + if (sample_count > MAX_SAMPLES) + sample_count = MAX_SAMPLES; + + for (int i = 0; i < sample_count; i++) + { + m_mdb.mean[0] += (samples[i].data[0]); + m_mdb.mean[1] += (samples[i].data[1]); + m_mdb.mean[2] += (samples[i].data[2]); + } + + m_mdb.sample_count = sample_count; + m_mdb.mean[0] /= sample_count; + m_mdb.mean[1] /= sample_count; + m_mdb.mean[2] /= sample_count; + + for (int i = 0; i < sample_count; i++) + { + // TODO: clamp to signed char range [-128, 127] + m_mdb.deltas[i][0] = m_mdb.mean[0] - (samples[i].data[0]); + m_mdb.deltas[i][1] = m_mdb.mean[1] - (samples[i].data[1]); + m_mdb.deltas[i][2] = m_mdb.mean[2] - (samples[i].data[2]); + } + + // calculate number of bytes in payload + m_mdb_bytes = sizeof(int) + // number of samples + (3 * sizeof(int)) + // mean of red, green & blue channels + (sample_count * sizeof(signed char) * 3); // one byte per channel per sample +} + +int Payload::raw_bytes_size() +{ + return m_mdb_bytes; +} + +uint8_t* Payload::raw_bytes() const +{ + return (uint8_t *)&m_mdb; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/payload.h Wed Apr 15 19:31:33 2015 +0000 @@ -0,0 +1,49 @@ +/* + * Builds the payload to send to the server. + * + * Copyright (c) 2014 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _PAYLOAD_H +#define _PAYLOAD_H +#include "GroveColourSensor.h" + +// TODO: include from common file +#ifndef RGB_VALUES +#define RGB_VALUES 512 +#endif + +class Payload +{ +public: + Payload(); + + void build(const RGBC *samples, int sample_count); + int raw_bytes_size(); + uint8_t* raw_bytes() const; + +private: + typedef struct + { + int sample_count; + int mean[3]; + signed char deltas[RGB_VALUES][3]; + } MeanDeltaBuffer; + + MeanDeltaBuffer m_mdb; + int m_mdb_bytes; +}; + +#endif // _PAYLOAD_H \ No newline at end of file