Line data Source code
1 : /** 2 : * @file i2c_transaction_queue.c 3 : * @brief Implementation for the transaction queue. 4 : * 5 : * Copyright (c) 2025 Cory McKiel. 6 : * Licensed under the MIT License. See LICENSE file in the project root. 7 : */ 8 : #include "i2c_transaction_queue.h" 9 : 10 : /** 11 : * @brief A queue that holds references to the transactions to be processed. 12 : * 13 : * Implemented as a ring buffer with no data overwrite. 14 : */ 15 : typedef struct { 16 : hal_i2c_txn_t *transactions[I2C_TRANSACTION_QUEUE_SIZE]; /*!< Array that holds all the references to transactions. */ 17 : size_t head; /*!< head points to either an empty slot (space in queue) or to tail (no space in queue). */ 18 : size_t tail; /*!< tail points to the next message to be dequeued. */ 19 : size_t transaction_count; /*!< A current count of the number of transactions in the queue. */ 20 : } i2c_transaction_queue_t; 21 : 22 : static i2c_transaction_queue_t queue = { 23 : .head = 0, 24 : .tail = 0, 25 : .transaction_count = 0 26 : }; 27 : 28 630 : i2c_queue_status_t i2c_transaction_queue_add(hal_i2c_txn_t *txn) 29 : { 30 630 : i2c_queue_status_t status = I2C_QUEUE_STATUS_FAIL; 31 : 32 630 : if (txn) 33 : { 34 : // Check if there is space for another message 35 629 : if (queue.transaction_count < I2C_TRANSACTION_QUEUE_SIZE) 36 : { 37 : // Queue the message 38 628 : queue.transactions[queue.head] = txn; 39 628 : queue.transactions[queue.head]->processing_state = HAL_I2C_TXN_STATE_QUEUED; 40 : 41 : // Increment the queue 42 628 : queue.head = (queue.head + 1) % I2C_TRANSACTION_QUEUE_SIZE; 43 628 : queue.transaction_count++; 44 : 45 628 : status = I2C_QUEUE_STATUS_SUCCESS; 46 : } 47 : else 48 : { 49 1 : status = I2C_QUEUE_STATUS_QUEUE_FULL; 50 : } 51 : } 52 : 53 630 : return status; 54 : } 55 : 56 : // Double pointer to transaction. This is because everything is pass by value in C. 57 : // The desire is to actually set the pointer passed to this function, and to set 58 : // a parameter, there needs to be a reference. In conclusion, this is a reference to 59 : // a pointer type. 60 626 : i2c_queue_status_t i2c_transaction_queue_get_next(hal_i2c_txn_t **txn) 61 : { 62 626 : i2c_queue_status_t status = I2C_QUEUE_STATUS_FAIL; 63 : 64 626 : if (txn) 65 : { 66 625 : if (queue.transaction_count == 0) 67 : { 68 11 : status = I2C_QUEUE_STATUS_QUEUE_EMPTY; 69 : } 70 : else 71 : { 72 614 : *txn = queue.transactions[queue.tail]; 73 614 : queue.tail = (queue.tail + 1) % I2C_TRANSACTION_QUEUE_SIZE; 74 614 : queue.transaction_count--; 75 614 : status = I2C_QUEUE_STATUS_SUCCESS; 76 : } 77 : } 78 : 79 626 : return status; 80 : } 81 : 82 10 : void i2c_transaction_queue_reset() 83 : { 84 10 : queue.head = 0; 85 10 : queue.tail = 0; 86 10 : queue.transaction_count = 0; 87 10 : }