Skip to content

Commit

Permalink
Implements Sample Rate, resolves #21
Browse files Browse the repository at this point in the history
References:
- 449565f
- 83043a6
  • Loading branch information
daniel-j-h committed Feb 11, 2017
1 parent 4af23e5 commit a3b9155
Show file tree
Hide file tree
Showing 15 changed files with 278 additions and 29 deletions.
16 changes: 16 additions & 0 deletions libsweep/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,22 @@ Sets the `sweep_device_s`'s motor speed in Hz.
The device supports speeds of 1 Hz to 10 Hz.
In case of error a `sweep_error_s` will be written into `error`.
```c++
int32_t sweep_device_get_sample_rate(sweep_device_s device, sweep_error_s* error)
```

Returns the `sweep_device_s`'s sample rate in Hz.
In case of error a `sweep_error_s` will be written into `error`.

```c++
void sweep_device_set_sample_rate(sweep_device_s device, int32_t hz, sweep_error_s* error)
```
Sets the `sweep_device_s`'s sample rate in Hz.
The device supports sample rates of 500 Hz, 750 Hz and 1000 Hz.
The device guarantees for those sample rates but they can be slightly higher by a maximum of roughly 50-100 Hz.
In case of error a `sweep_error_s` will be written into `error`.
```c++
void sweep_device_reset(sweep_device_s device, sweep_error_s* error)
```
Expand Down
20 changes: 18 additions & 2 deletions libsweep/dummy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef struct sweep_error {
typedef struct sweep_device {
bool scanning;
int32_t motor_speed;
int32_t sample_rate;
int32_t nth_scan_request;
} sweep_device;

Expand Down Expand Up @@ -44,7 +45,7 @@ sweep_device_s sweep_device_construct(const char* port, int32_t bitrate, sweep_e
SWEEP_ASSERT(bitrate > 0);
SWEEP_ASSERT(error);

auto out = new sweep_device{/*scanning=*/false, /*motor_speed=*/1, /*nth_scan_request=*/0};
auto out = new sweep_device{/*scanning=*/false, /*motor_speed=*/5, /*sample_rate*/ 500, /*nth_scan_request=*/0};
return out;
}

Expand Down Expand Up @@ -124,7 +125,7 @@ int32_t sweep_scan_get_signal_strength(sweep_scan_s scan, int32_t sample) {
SWEEP_ASSERT(scan);
SWEEP_ASSERT(sample >= 0 && sample < scan->count && "sample index out of bounds");

return 100;
return 200;
}

void sweep_scan_destruct(sweep_scan_s scan) {
Expand All @@ -148,6 +149,21 @@ void sweep_device_set_motor_speed(sweep_device_s device, int32_t hz, sweep_error
device->motor_speed = hz;
}

int32_t sweep_device_get_sample_rate(sweep_device_s device, sweep_error_s* error) {
SWEEP_ASSERT(device);
SWEEP_ASSERT(error);

return device->sample_rate;
}

void sweep_device_set_sample_rate(sweep_device_s device, int32_t hz, sweep_error_s* error) {
SWEEP_ASSERT(device);
SWEEP_ASSERT(hz == 500 || hz == 750 || hz == 1000);
SWEEP_ASSERT(error);

device->sample_rate = hz;
}

void sweep_device_reset(sweep_device_s device, sweep_error_s* error) {
SWEEP_ASSERT(device);
SWEEP_ASSERT(error);
Expand Down
6 changes: 6 additions & 0 deletions libsweep/examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ int main() {

fprintf(stdout, "Motor Speed: %" PRId32 " Hz\n", speed);

// The Sweep's sample rate in Hz
int32_t rate = sweep_device_get_sample_rate(sweep, &error);
check(error);

fprintf(stdout, "Sample Rate: %" PRId32 " Hz\n", rate);

// Capture scans
sweep_device_start_scanning(sweep, &error);
check(error);
Expand Down
3 changes: 3 additions & 0 deletions libsweep/examples/example.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ int main() try {

device.start_scanning();

std::cout << "Motor Speed: " << device.get_motor_speed() << " Hz" << std::endl;
std::cout << "Sample Rate: " << device.get_sample_rate() << " Hz" << std::endl;

for (auto n = 0; n < 10; ++n) {
const sweep::scan scan = device.get_scan();

Expand Down
39 changes: 30 additions & 9 deletions libsweep/protocol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const uint8_t DATA_ACQUISITION_START[2] = {'D', 'S'};
const uint8_t DATA_ACQUISITION_STOP[2] = {'D', 'X'};
const uint8_t MOTOR_SPEED_ADJUST[2] = {'M', 'S'};
const uint8_t MOTOR_INFORMATION[2] = {'M', 'I'};
const uint8_t SAMPLE_RATE_ADJUST[2] = {'L', 'R'};
const uint8_t SAMPLE_RATE_INFORMATION[2] = {'L', 'I'};
const uint8_t VERSION_INFORMATION[2] = {'I', 'V'};
const uint8_t DEVICE_INFORMATION[2] = {'I', 'D'};
const uint8_t RESET_DEVICE[2] = {'R', 'R'};
Expand Down Expand Up @@ -114,8 +116,6 @@ void read_response_header(serial::device_s serial, const uint8_t cmd[2], respons
SWEEP_ASSERT(header);
SWEEP_ASSERT(error);

const uint8_t* cmdBytes = (const uint8_t*)cmd;

serial::error_s serialerror = nullptr;

serial::device_read(serial, header, sizeof(response_header_s), &serialerror);
Expand All @@ -133,7 +133,7 @@ void read_response_header(serial::device_s serial, const uint8_t cmd[2], respons
return;
}

bool ok = header->cmdByte1 == cmdBytes[0] && header->cmdByte2 == cmdBytes[1];
bool ok = header->cmdByte1 == cmd[0] && header->cmdByte2 == cmd[1];

if (!ok) {
*error = error_construct("invalid header response commands");
Expand All @@ -147,8 +147,6 @@ void read_response_param(serial::device_s serial, const uint8_t cmd[2], response
SWEEP_ASSERT(param);
SWEEP_ASSERT(error);

const uint8_t* cmdBytes = (const uint8_t*)cmd;

serial::error_s serialerror = nullptr;

serial::device_read(serial, param, sizeof(response_param_s), &serialerror);
Expand All @@ -166,7 +164,7 @@ void read_response_param(serial::device_s serial, const uint8_t cmd[2], response
return;
}

bool ok = param->cmdByte1 == cmdBytes[0] && param->cmdByte2 == cmdBytes[1];
bool ok = param->cmdByte1 == cmd[0] && param->cmdByte2 == cmd[1];

if (!ok) {
*error = error_construct("invalid param response commands");
Expand Down Expand Up @@ -203,8 +201,6 @@ void read_response_info_motor(serial::device_s serial, const uint8_t cmd[2], res
SWEEP_ASSERT(info);
SWEEP_ASSERT(error);

const uint8_t* cmdBytes = (const uint8_t*)cmd;

serial::error_s serialerror = nullptr;

serial::device_read(serial, info, sizeof(response_info_motor_s), &serialerror);
Expand All @@ -215,13 +211,38 @@ void read_response_info_motor(serial::device_s serial, const uint8_t cmd[2], res
return;
}

bool ok = info->cmdByte1 == cmdBytes[0] && info->cmdByte2 == cmdBytes[1];
bool ok = info->cmdByte1 == cmd[0] && info->cmdByte2 == cmd[1];

if (!ok) {
*error = error_construct("invalid motor info response commands");
return;
}
}

void read_response_info_sample_rate(sweep::serial::device_s serial, const uint8_t cmd[2], response_info_sample_rate_s* info,
error_s* error) {
SWEEP_ASSERT(serial);
SWEEP_ASSERT(cmd);
SWEEP_ASSERT(info);
SWEEP_ASSERT(error);

serial::error_s serialerror = nullptr;

serial::device_read(serial, info, sizeof(response_info_sample_rate_s), &serialerror);

if (serialerror) {
*error = error_construct("unable to read response sample rate info");
serial::error_destruct(serialerror);
return;
}

bool ok = info->cmdByte1 == cmd[0] && info->cmdByte2 == cmd[1];

if (!ok) {
*error = error_construct("invalid sample rate info response commands");
return;
}
}

} // ns protocol
} // ns sweep
42 changes: 28 additions & 14 deletions libsweep/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ extern const uint8_t DATA_ACQUISITION_START[2];
extern const uint8_t DATA_ACQUISITION_STOP[2];
extern const uint8_t MOTOR_SPEED_ADJUST[2];
extern const uint8_t MOTOR_INFORMATION[2];
extern const uint8_t SAMPLE_RATE_ADJUST[2];
extern const uint8_t SAMPLE_RATE_INFORMATION[2];
extern const uint8_t VERSION_INFORMATION[2];
extern const uint8_t DEVICE_INFORMATION[2];
extern const uint8_t RESET_DEVICE[2];
Expand Down Expand Up @@ -122,6 +124,15 @@ typedef struct {

static_assert(sizeof(response_info_motor_s) == 5, "response info motor size mismatch");

typedef struct {
uint8_t cmdByte1;
uint8_t cmdByte2;
uint8_t sample_rate[2];
uint8_t term;
} SWEEP_PACKED response_info_sample_rate_s;

static_assert(sizeof(response_info_sample_rate_s) == 5, "response info sample rate siye mismatch");

// Read and write specific packets

void write_command(sweep::serial::device_s serial, const uint8_t cmd[2], error_s* error);
Expand All @@ -136,39 +147,42 @@ void read_response_scan(sweep::serial::device_s serial, response_scan_packet_s*

void read_response_info_motor(sweep::serial::device_s serial, const uint8_t cmd[2], response_info_motor_s* info, error_s* error);

void read_response_info_sample_rate(sweep::serial::device_s serial, const uint8_t cmd[2], response_info_sample_rate_s* info,
error_s* error);

// Some protocol conversion utilities
inline float u16_to_f32(uint16_t v) { return ((float)(v >> 4u)) + (v & 15u) / 16.0f; }

inline void speed_to_ascii_bytes(int32_t speed, uint8_t bytes[2]) {
SWEEP_ASSERT(speed >= 0);
SWEEP_ASSERT(speed <= 10);
inline void integral_to_ascii_bytes(const int32_t integral, uint8_t bytes[2]) {
SWEEP_ASSERT(integral >= 0);
SWEEP_ASSERT(integral <= 99);
SWEEP_ASSERT(bytes);

// Speed values are still ASCII codes, numbers begin at code point 48
// Numbers begin at ASCII code point 48
const uint8_t ASCIINumberBlockOffset = 48;

uint8_t num1 = (speed / 10) + ASCIINumberBlockOffset;
uint8_t num2 = (speed % 10) + ASCIINumberBlockOffset;
const uint8_t num1 = (integral / 10) + ASCIINumberBlockOffset;
const uint8_t num2 = (integral % 10) + ASCIINumberBlockOffset;

bytes[0] = num1;
bytes[1] = num2;
}

inline int32_t ascii_bytes_to_speed(const uint8_t bytes[2]) {
inline int32_t ascii_bytes_to_integral(const uint8_t bytes[2]) {
SWEEP_ASSERT(bytes);

// Speed values are still ASCII codes, numbers begin at code point 48
// Numbers begin at ASCII code point 48
const uint8_t ASCIINumberBlockOffset = 48;

uint8_t num1 = bytes[0] - ASCIINumberBlockOffset;
uint8_t num2 = bytes[1] - ASCIINumberBlockOffset;
const uint8_t num1 = bytes[0] - ASCIINumberBlockOffset;
const uint8_t num2 = bytes[1] - ASCIINumberBlockOffset;

int32_t speed = (num1 * 10) + (num2 * 1);
const int32_t integral = (num1 * 10) + (num2 * 1);

SWEEP_ASSERT(speed >= 0);
SWEEP_ASSERT(speed <= 10);
SWEEP_ASSERT(integral >= 0);
SWEEP_ASSERT(integral <= 99);

return speed;
return integral;
}

} // ns protocol
Expand Down
95 changes: 93 additions & 2 deletions libsweep/sweep.cc
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ int32_t sweep_device_get_motor_speed(sweep_device_s device, sweep_error_s* error
return 0;
}

int32_t speed = sweep::protocol::ascii_bytes_to_speed(response.motor_speed);
int32_t speed = sweep::protocol::ascii_bytes_to_integral(response.motor_speed);
SWEEP_ASSERT(speed >= 0);

return speed;
}
Expand All @@ -289,7 +290,7 @@ void sweep_device_set_motor_speed(sweep_device_s device, int32_t hz, sweep_error
SWEEP_ASSERT(error);

uint8_t args[2] = {0};
sweep::protocol::speed_to_ascii_bytes(hz, args);
sweep::protocol::integral_to_ascii_bytes(hz, args);

sweep::protocol::error_s protocolerror = nullptr;

Expand All @@ -311,6 +312,96 @@ void sweep_device_set_motor_speed(sweep_device_s device, int32_t hz, sweep_error
}
}

int32_t sweep_device_get_sample_rate(sweep_device_s device, sweep_error_s* error) {
SWEEP_ASSERT(device);
SWEEP_ASSERT(error);

sweep::protocol::error_s protocolerror = nullptr;

sweep::protocol::write_command(device->serial, sweep::protocol::SAMPLE_RATE_INFORMATION, &protocolerror);

if (protocolerror) {
*error = sweep_error_construct("unable to send sample rate command");
sweep::protocol::error_destruct(protocolerror);
return 0;
}

sweep::protocol::response_info_sample_rate_s response;
sweep::protocol::read_response_info_sample_rate(device->serial, sweep::protocol::SAMPLE_RATE_INFORMATION, &response,
&protocolerror);

if (protocolerror) {
*error = sweep_error_construct("unable to receive sample rate command response");
sweep::protocol::error_destruct(protocolerror);
return 0;
}

// 01: 500-600Hz, 02: 750-800Hz, 03: 1000-1050Hz
int32_t code = sweep::protocol::ascii_bytes_to_integral(response.sample_rate);
int32_t rate = 0;

switch (code) {
case 1:
rate = 500;
break;
case 2:
rate = 750;
break;
case 3:
rate = 1000;
break;
default:
SWEEP_ASSERT(false && "sample rate code unknown");
}

return rate;
}

void sweep_device_set_sample_rate(sweep_device_s device, int32_t hz, sweep_error_s* error) {
SWEEP_ASSERT(device);
SWEEP_ASSERT(hz == 500 || hz == 750 || hz == 1000);
SWEEP_ASSERT(error);

// 01: 500-600Hz, 02: 750-800Hz, 03: 1000-1050Hz
int32_t code = 1;

switch (hz) {
case 500:
code = 1;
break;
case 750:
code = 2;
break;
case 1000:
code = 3;
break;
default:
SWEEP_ASSERT(false && "sample rate unknown");
}

uint8_t args[2] = {0};
sweep::protocol::integral_to_ascii_bytes(code, args);

sweep::protocol::error_s protocolerror = nullptr;

sweep::protocol::write_command_with_arguments(device->serial, sweep::protocol::SAMPLE_RATE_ADJUST, args, &protocolerror);

if (protocolerror) {
*error = sweep_error_construct("unable to send sample rate command");
sweep::protocol::error_destruct(protocolerror);
return;
}

sweep::protocol::response_param_s response;
sweep::protocol::read_response_param(device->serial, sweep::protocol::SAMPLE_RATE_ADJUST, &response, &protocolerror);

if (protocolerror) {
*error = sweep_error_construct("unable to receive sample rate command response");
sweep::protocol::error_destruct(protocolerror);
return;
}
}

void sweep_device_reset(sweep_device_s device, sweep_error_s* error) {
SWEEP_ASSERT(device);
SWEEP_ASSERT(error);
Expand Down
3 changes: 3 additions & 0 deletions libsweep/sweep.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ SWEEP_API int32_t sweep_scan_get_signal_strength(sweep_scan_s scan, int32_t samp
SWEEP_API int32_t sweep_device_get_motor_speed(sweep_device_s device, sweep_error_s* error);
SWEEP_API void sweep_device_set_motor_speed(sweep_device_s device, int32_t hz, sweep_error_s* error);

SWEEP_API int32_t sweep_device_get_sample_rate(sweep_device_s device, sweep_error_s* error);
SWEEP_API void sweep_device_set_sample_rate(sweep_device_s device, int32_t hz, sweep_error_s* error);

SWEEP_API void sweep_device_reset(sweep_device_s device, sweep_error_s* error);

#ifdef __cplusplus
Expand Down
Loading

0 comments on commit a3b9155

Please sign in to comment.