Fix error queue and resolve #67
| | |
| | | XE(SCPI_ERROR_OUT_OF_DEVICE_MEMORY, -321, "Out of memory") \ |
| | | XE(SCPI_ERROR_SELF_TEST_FAILED, -330, "Self-test failed") \ |
| | | XE(SCPI_ERROR_CALIBRATION_FAILED, -340, "Calibration failed") \ |
| | | XE(SCPI_ERROR_QUEUE_OVERFLOW, -350, "Queue overflow") \ |
| | | X(SCPI_ERROR_QUEUE_OVERFLOW, -350, "Queue overflow") \ |
| | | XE(SCPI_ERROR_COMMUNICATION_ERROR, -360, "Communication error") \ |
| | | XE(SCPI_ERROR_PARITY_ERROR_IN_CMD_MSG, -361, "Parity error in program message") \ |
| | | XE(SCPI_ERROR_FRAMING_ERROR_IN_CMD_MSG, -362, "Framing error in program message") \ |
| | |
| | | * @param context - scpi context |
| | | */ |
| | | void SCPI_ErrorInit(scpi_t * context) { |
| | | /* |
| | | * // FreeRTOS |
| | | * context->error_queue = (scpi_error_queue_t)xQueueCreate(100, sizeof(int16_t)); |
| | | */ |
| | | |
| | | /* basic FIFO */ |
| | | context->error_queue = (scpi_error_queue_t) & local_error_queue; |
| | | fifo_init((scpi_fifo_t *) context->error_queue); |
| | | } |
| | |
| | | * @param context - scpi context |
| | | */ |
| | | void SCPI_ErrorClear(scpi_t * context) { |
| | | /* |
| | | * // FreeRTOS |
| | | * xQueueReset((xQueueHandle)context->error_queue); |
| | | */ |
| | | |
| | | /* basic FIFO */ |
| | | fifo_clear((scpi_fifo_t *) context->error_queue); |
| | | |
| | | SCPI_ErrorEmitEmpty(context); |
| | |
| | | int16_t SCPI_ErrorPop(scpi_t * context) { |
| | | int16_t result = 0; |
| | | |
| | | /* |
| | | * // FreeRTOS |
| | | * if (pdFALSE == xQueueReceive((xQueueHandle)context->error_queue, &result, 0)) { |
| | | * result = 0; |
| | | * } |
| | | */ |
| | | |
| | | /* basic FIFO */ |
| | | fifo_remove((scpi_fifo_t *) context->error_queue, &result); |
| | | |
| | | SCPI_ErrorEmitEmpty(context); |
| | |
| | | int32_t SCPI_ErrorCount(scpi_t * context) { |
| | | int16_t result = 0; |
| | | |
| | | /* |
| | | * // FreeRTOS |
| | | * result = uxQueueMessagesWaiting((xQueueHandle)context->error_queue); |
| | | */ |
| | | |
| | | /* basic FIFO */ |
| | | fifo_count((scpi_fifo_t *) context->error_queue, &result); |
| | | |
| | | return result; |
| | | } |
| | | |
| | | static void SCPI_ErrorAddInternal(scpi_t * context, int16_t err) { |
| | | /* |
| | | * // FreeRTOS |
| | | * xQueueSend((xQueueHandle)context->error_queue, &err, 0); |
| | | */ |
| | | |
| | | /* basic FIFO */ |
| | | fifo_add((scpi_fifo_t *) context->error_queue, err); |
| | | if (!fifo_add((scpi_fifo_t *) context->error_queue, err)) { |
| | | fifo_remove_last((scpi_fifo_t *) context->error_queue, NULL); |
| | | fifo_add((scpi_fifo_t *) context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW); |
| | | } |
| | | } |
| | | |
| | | struct error_reg { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Add element to fifo. If fifo is full, remove last element. |
| | | * Test if fifo is empty |
| | | * @param fifo |
| | | * @return |
| | | */ |
| | | scpi_bool_t fifo_is_empty(scpi_fifo_t * fifo) { |
| | | return fifo->wr == fifo->rd; |
| | | } |
| | | |
| | | /** |
| | | * Test if fifo is full |
| | | * @param fifo |
| | | * @return |
| | | */ |
| | | scpi_bool_t fifo_is_full(scpi_fifo_t * fifo) { |
| | | return fifo->wr == ((fifo->rd + fifo->size - 1) % (fifo->size)); |
| | | } |
| | | |
| | | /** |
| | | * Add element to fifo. If fifo is full, return FALSE. |
| | | * @param fifo |
| | | * @param value |
| | | * @return |
| | | */ |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t value) { |
| | | /* FIFO full? */ |
| | | if (fifo->wr == ((fifo->rd + fifo->size) % (fifo->size + 1))) { |
| | | fifo_remove(fifo, NULL); |
| | | if (fifo_is_full(fifo)) { |
| | | return FALSE; |
| | | } |
| | | |
| | | fifo->data[fifo->wr] = value; |
| | | fifo->wr = (fifo->wr + 1) % (fifo->size + 1); |
| | | fifo->wr = (fifo->wr + 1) % (fifo->size); |
| | | |
| | | return TRUE; |
| | | } |
| | |
| | | */ |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, int16_t * value) { |
| | | /* FIFO empty? */ |
| | | if (fifo->wr == fifo->rd) { |
| | | if (fifo_is_empty(fifo)) { |
| | | return FALSE; |
| | | } |
| | | |
| | |
| | | *value = fifo->data[fifo->rd]; |
| | | } |
| | | |
| | | fifo->rd = (fifo->rd + 1) % (fifo->size + 1); |
| | | fifo->rd = (fifo->rd + 1) % (fifo->size); |
| | | |
| | | return TRUE; |
| | | } |
| | | |
| | | /** |
| | | * Remove last element from fifo |
| | | * @param fifo |
| | | * @param value |
| | | * @return FALSE - fifo is empty |
| | | */ |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, int16_t * value) { |
| | | /* FIFO empty? */ |
| | | if (fifo_is_empty(fifo)) { |
| | | return FALSE; |
| | | } |
| | | |
| | | fifo->wr = (fifo->wr + fifo->size - 1) % (fifo->size); |
| | | |
| | | if (value) { |
| | | *value = fifo->data[fifo->wr]; |
| | | } |
| | | |
| | | return TRUE; |
| | | } |
| | |
| | | scpi_bool_t fifo_count(scpi_fifo_t * fifo, int16_t * value) { |
| | | *value = fifo->wr - fifo->rd; |
| | | if (*value < 0) { |
| | | *value += (fifo->size + 1); |
| | | *value += (fifo->size); |
| | | } |
| | | return TRUE; |
| | | } |
| | |
| | | |
| | | void fifo_init(scpi_fifo_t * fifo) LOCAL; |
| | | void fifo_clear(scpi_fifo_t * fifo) LOCAL; |
| | | scpi_bool_t fifo_is_empty(scpi_fifo_t * fifo) LOCAL; |
| | | scpi_bool_t fifo_is_full(scpi_fifo_t * fifo) LOCAL; |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t value) LOCAL; |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, int16_t * value) LOCAL; |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, int16_t * value) LOCAL; |
| | | scpi_bool_t fifo_count(scpi_fifo_t * fifo, int16_t * value) LOCAL; |
| | | |
| | | #ifdef __cplusplus |
| | |
| | | fifo_init(&fifo); |
| | | int16_t value; |
| | | |
| | | fifo.size = 4; |
| | | fifo.size = 5; |
| | | |
| | | #define TEST_FIFO_COUNT(n) \ |
| | | do { \ |
| | |
| | | |
| | | |
| | | TEST_FIFO_COUNT(0); |
| | | CU_ASSERT_TRUE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 1)); |
| | | TEST_FIFO_COUNT(1); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 2)); |
| | | TEST_FIFO_COUNT(2); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 3)); |
| | | TEST_FIFO_COUNT(3); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 4)); |
| | | TEST_FIFO_COUNT(4); |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 1)); |
| | | TEST_FIFO_COUNT(4); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_TRUE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_EQUAL(fifo.data[0], 1); |
| | | CU_ASSERT_EQUAL(fifo.data[1], 2); |
| | | CU_ASSERT_EQUAL(fifo.data[2], 3); |
| | | CU_ASSERT_EQUAL(fifo.data[3], 4); |
| | | |
| | | |
| | | CU_ASSERT_FALSE(fifo_add(&fifo, 5)); |
| | | TEST_FIFO_COUNT(4); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_TRUE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_EQUAL(fifo.data[0], 1); |
| | | CU_ASSERT_EQUAL(fifo.data[1], 2); |
| | | CU_ASSERT_EQUAL(fifo.data[2], 3); |
| | | CU_ASSERT_EQUAL(fifo.data[3], 4); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove_last(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 4); |
| | | TEST_FIFO_COUNT(3); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 6)); |
| | | TEST_FIFO_COUNT(4); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_TRUE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_EQUAL(fifo.data[0], 1); |
| | | CU_ASSERT_EQUAL(fifo.data[1], 2); |
| | | CU_ASSERT_EQUAL(fifo.data[2], 3); |
| | | CU_ASSERT_EQUAL(fifo.data[3], 6); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 1); |
| | | TEST_FIFO_COUNT(3); |
| | | CU_ASSERT_FALSE(fifo_is_empty(&fifo)); |
| | | CU_ASSERT_FALSE(fifo_is_full(&fifo)); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 7)); |
| | | TEST_FIFO_COUNT(4); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 2); |
| | | TEST_FIFO_COUNT(3); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 5)); |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 3); |
| | | TEST_FIFO_COUNT(2); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 10)); |
| | | TEST_FIFO_COUNT(3); |
| | | |
| | | CU_ASSERT_TRUE(fifo_add(&fifo, 11)); |
| | | TEST_FIFO_COUNT(4); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 3); |
| | | CU_ASSERT_EQUAL(value, 6); |
| | | TEST_FIFO_COUNT(3); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 4); |
| | | CU_ASSERT_EQUAL(value, 7); |
| | | TEST_FIFO_COUNT(2); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 1); |
| | | CU_ASSERT_TRUE(fifo_remove_last(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 11); |
| | | TEST_FIFO_COUNT(1); |
| | | |
| | | CU_ASSERT_TRUE(fifo_remove(&fifo, &value)); |
| | | CU_ASSERT_EQUAL(value, 5); |
| | | CU_ASSERT_EQUAL(value, 10); |
| | | TEST_FIFO_COUNT(0); |
| | | |
| | | CU_ASSERT_FALSE(fifo_remove(&fifo, &value)); |
| | | TEST_FIFO_COUNT(0); |
| | | |
| | | CU_ASSERT_FALSE(fifo_remove_last(&fifo, NULL)); |
| | | } |
| | | |
| | | int main() { |
| | |
| | | #include "CUnit/Basic.h" |
| | | |
| | | #include "scpi/scpi.h" |
| | | #include "../src/fifo_private.h" |
| | | |
| | | /* |
| | | * CUnit Test Suite |
| | |
| | | TEST_SCPI_NumberToStr(TRUE, SCPI_NUM_DEF, SCPI_UNIT_NONE, "DEFault"); |
| | | } |
| | | |
| | | static void testErrorQueue(void) { |
| | | ((scpi_fifo_t *) (scpi_context.error_queue))->size = 5; |
| | | |
| | | SCPI_ErrorClear(&scpi_context); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); |
| | | SCPI_ErrorPush(&scpi_context, -1); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 1); |
| | | SCPI_ErrorPush(&scpi_context, -2); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 2); |
| | | SCPI_ErrorPush(&scpi_context, -3); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 3); |
| | | SCPI_ErrorPush(&scpi_context, -4); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 4); |
| | | SCPI_ErrorPush(&scpi_context, -5); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 4); |
| | | SCPI_ErrorPush(&scpi_context, -6); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 4); |
| | | |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), -1); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 3); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), -2); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 2); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), -3); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 1); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), SCPI_ERROR_QUEUE_OVERFLOW); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorPop(&scpi_context), 0); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); |
| | | |
| | | SCPI_ErrorClear(&scpi_context); |
| | | ((scpi_fifo_t *) (scpi_context.error_queue))->size = FIFO_SIZE; |
| | | } |
| | | |
| | | int main() { |
| | | unsigned int result; |
| | | CU_pSuite pSuite = NULL; |
| | |
| | | || (NULL == CU_add_test(pSuite, "SCPI_ResultArbitraryBlock", testResultArbitraryBlock)) |
| | | || (NULL == CU_add_test(pSuite, "SCPI_ResultArray", testResultArray)) |
| | | || (NULL == CU_add_test(pSuite, "SCPI_NumberToStr", testNumberToStr)) |
| | | || (NULL == CU_add_test(pSuite, "SCPI_ErrorQueue", testErrorQueue)) |
| | | ) { |
| | | CU_cleanup_registry(); |
| | | return CU_get_error(); |