mirror of
https://gitee.com/Lamdonn/varch.git
synced 2025-12-06 08:46:42 +08:00
781 lines
28 KiB
C
781 lines
28 KiB
C
/*********************************************************************************************************
|
|
* ------------------------------------------------------------------------------------------------------
|
|
* file description
|
|
* ------------------------------------------------------------------------------------------------------
|
|
* \file slup.c
|
|
* \unit slup
|
|
* \brief This is a simple serial link universal protocol for C language
|
|
* \author Lamdonn
|
|
* \version v0.1.0
|
|
* \license GPL-2.0
|
|
* \copyright Copyright (C) 2023 Lamdonn.
|
|
********************************************************************************************************/
|
|
#include "slup.h"
|
|
|
|
/*
|
|
| HEAD | SN | FrameType | Length | Data | Check | TAIL |
|
|
*/
|
|
|
|
// Macro to send a character and perform some additional operations.
|
|
// It calls the putc function pointer in the slup structure to send the character 'c'.
|
|
// It also logs the character in hexadecimal format using SLUP_DEBUG and updates the upload statistics.
|
|
#define sputc(c) do { (slup->putc)(c); SLUP_DEBUG("%02x ", (c)); slup_statis_upload(slup); } while (0)
|
|
|
|
// Macro to access the i-th element of the head mask in the SLUP configuration.
|
|
#define head(i) (slup->cfg.head[(i)])
|
|
|
|
// Macro to access the i-th element of the tail mask in the SLUP configuration.
|
|
#define tail(i) (slup->cfg.tail[(i)])
|
|
|
|
// Macro to access the i-th byte of the sequence number (sn) in the slup structure.
|
|
#define sn(i) (((uint8_t *)(&(slup->sn)))[(i)])
|
|
|
|
// Macro to access the i-th byte of the length variable.
|
|
#define len(i) (((uint8_t *)(&(length)))[(i)])
|
|
|
|
// Define states for the SLUP receive state machine.
|
|
#define SLUP_RX_STATE_HEAD 0
|
|
#define SLUP_RX_STATE_SN 1
|
|
#define SLUP_RX_STATE_FRAMETYPE 2
|
|
#define SLUP_RX_STATE_LENGTH 3
|
|
#define SLUP_RX_STATE_DATA 4
|
|
#define SLUP_RX_STATE_CHECK 5
|
|
#define SLUP_RX_STATE_TAIL 6
|
|
|
|
// Debug macro, currently defined as an empty operation.
|
|
// Can be redefined to use printf for debugging purposes.
|
|
#define SLUP_DEBUG(...)
|
|
// #define SLUP_DEBUG printf
|
|
|
|
/**
|
|
* \brief Pushes a character into the SLUP queue.
|
|
* \param queue: Pointer to the SLUP queue structure.
|
|
* \param data: The character to be pushed into the queue.
|
|
* \return 1 if the push operation is successful, 0 otherwise.
|
|
*
|
|
* This function adds a character to the SLUP queue. If the queue is not full,
|
|
* it simply adds the character to the tail of the queue and updates the tail index and size.
|
|
* If the queue is full, it overwrites the oldest element and updates both the head and tail indices.
|
|
*/
|
|
static int slup_queue_push(SLUP_QUEUE *queue, char data)
|
|
{
|
|
if (!queue) return 0;
|
|
|
|
if (queue->size < SLUP_RXQUE_SIZE)
|
|
{
|
|
queue->base[queue->tail] = data;
|
|
queue->tail = (queue->tail + 1) % SLUP_RXQUE_SIZE;
|
|
queue->size++;
|
|
}
|
|
else
|
|
{
|
|
queue->base[queue->tail] = data;
|
|
queue->tail = (queue->tail + 1) % SLUP_RXQUE_SIZE;
|
|
queue->head = (queue->head + 1) % SLUP_RXQUE_SIZE;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Pops a specified number of elements from the SLUP queue.
|
|
* \param queue: Pointer to the SLUP queue structure.
|
|
* \param count: The number of elements to be popped from the queue.
|
|
* \return 1 if the pop operation is successful, 0 otherwise.
|
|
*
|
|
* This function removes a specified number of elements from the SLUP queue.
|
|
* If the number of elements to be popped is greater than the current size of the queue,
|
|
* it will only pop the existing elements in the queue.
|
|
*/
|
|
static int slup_queue_pop(SLUP_QUEUE *queue, uint32_t count)
|
|
{
|
|
if (!queue) return 0;
|
|
if (queue->size == 0) return 0;
|
|
if (count == 0) return 0;
|
|
|
|
if (count > queue->size) count = queue->size;
|
|
|
|
queue->head = (queue->head + count) % SLUP_RXQUE_SIZE;
|
|
queue->size -= count;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Retrieves an element at a specified index from the SLUP queue.
|
|
* \param queue: Pointer to the SLUP queue structure.
|
|
* \param index: The index of the element to be retrieved.
|
|
* \return The character at the specified index if the queue is valid and not empty, 0 otherwise.
|
|
*
|
|
* This function returns the element at a given index in the SLUP queue.
|
|
* The index is calculated relative to the head of the queue.
|
|
*/
|
|
static char slup_queue_at(SLUP_QUEUE *queue, uint32_t index)
|
|
{
|
|
if (!queue) return 0;
|
|
if (queue->size == 0) return 0;
|
|
return queue->base[((queue->head + index) % SLUP_RXQUE_SIZE)];
|
|
}
|
|
|
|
/**
|
|
* \brief Update the upload statistics of the SLUP structure.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
*
|
|
* This function increments the 'upbits' field in the SLUP structure by 8,
|
|
* indicating that 8 bits of data have been uploaded. It is called within the 'sputc' macro
|
|
* when sending data to keep track of the amount of uploaded data.
|
|
*/
|
|
static void slup_statis_upload(SLUP *slup)
|
|
{
|
|
slup->upbits += 8;
|
|
}
|
|
|
|
/**
|
|
* \brief Update the download statistics of the SLUP structure.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
*
|
|
* This function increments the 'downbits' field in the SLUP structure by 8,
|
|
* indicating that 8 bits of data have been downloaded. It is used to track
|
|
* the amount of data received in the SLUP communication process.
|
|
*/
|
|
static void slup_statis_download(SLUP *slup)
|
|
{
|
|
slup->downbits += 8;
|
|
}
|
|
|
|
/**
|
|
* \brief Receive and process an SLUP package.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \return SLUP_E_OK: Indicates that the package has been successfully received and processed.
|
|
*
|
|
* This function first checks the 'frame' field in the 'parser' of the SLUP structure.
|
|
* If the 'frame' is 0x00, it extracts the link information from the first byte of the 'buffer'.
|
|
* Depending on the result of the bitwise AND operation between the link information and SLUP_LINK_RX,
|
|
* it updates the 'link' field in the SLUP structure. If the 'frame' is not 0x00 and the 'receive'
|
|
* function pointer in the SLUP structure is valid, it calls the 'receive' function to handle
|
|
* the received data in the 'buffer' with the specified size 'bsize'.
|
|
*/
|
|
static int slup_receive_package(SLUP *slup)
|
|
{
|
|
if (slup->parser.frame == 0x00)
|
|
{
|
|
uint8_t link = 0;
|
|
|
|
link = slup->buffer[0];
|
|
|
|
if (link & SLUP_LINK_RX)
|
|
{
|
|
slup->link |= SLUP_LINK_TX;
|
|
}
|
|
else
|
|
{
|
|
slup->link &= (~SLUP_LINK_TX);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (slup->receive)
|
|
{
|
|
(slup->receive)(slup->buffer, slup->bsize);
|
|
}
|
|
}
|
|
return SLUP_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Send an SLUP package.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \param frame: The frame type of the package.
|
|
* \param data: Pointer to the data buffer of the package.
|
|
* \param length: The length of the data in the package.
|
|
* \return SLUP_E_OK: Indicates that the package has been successfully sent.
|
|
* SLUP_E_INVALID: Returned if the 'slup' pointer is NULL.
|
|
* SLUP_E_DATA: Returned if the 'data' pointer is NULL.
|
|
* SLUP_E_LEN: Returned if the 'length' is 0.
|
|
*
|
|
* This function constructs and sends an SLUP package. It first validates the input parameters.
|
|
* Then it sends each part of the package in order: the head, sequence number (SN), frame type,
|
|
* data length, data, checksum, and tail. The sequence number is incremented after being sent.
|
|
* The checksum is calculated using the 'check' function pointer in the SLUP structure.
|
|
*/
|
|
static int slup_send_package(SLUP *slup, uint8_t frame, uint8_t *data, uint16_t length)
|
|
{
|
|
uint32_t i = 0;
|
|
uint32_t check = 0;
|
|
|
|
if (!slup) return SLUP_E_INVALID;
|
|
if (!data) return SLUP_E_DATA;
|
|
if (length == 0) return SLUP_E_LEN;
|
|
|
|
/* Send the HEAD part of the package */
|
|
for (i = 0; i < slup->cfg.hsize; i++)
|
|
{
|
|
sputc(head(i));
|
|
}
|
|
|
|
/* Send the SN (Sequence Number) part of the package */
|
|
sputc(sn(0));
|
|
sputc(sn(1));
|
|
sputc(sn(2));
|
|
sputc(sn(3));
|
|
slup->sn++;
|
|
|
|
/* Send the FrameType part of the package */
|
|
sputc(frame);
|
|
|
|
/* Send the Length part of the package */
|
|
sputc(len(0));
|
|
sputc(len(1));
|
|
|
|
/* Calculate the checksum of the data */
|
|
check = (slup->check)(data, length);
|
|
|
|
/* Send the Data part of the package */
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
sputc(data[i]);
|
|
}
|
|
|
|
/* Send the Check part of the package */
|
|
for (i = 0; i < slup->cfg.csize; i++)
|
|
{
|
|
sputc((((uint8_t *)(&(check)))[(i)]));
|
|
}
|
|
|
|
/* Send the TAIL part of the package */
|
|
for (i = 0; i < slup->cfg.tsize; i++)
|
|
{
|
|
sputc(tail(i));
|
|
}
|
|
|
|
return SLUP_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Parses the received data in the SLUP queue and processes it according to the SLUP protocol.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
*
|
|
* This function is responsible for parsing the data in the SLUP queue. It iterates through all the
|
|
* data in the queue when there is data available. For each byte of data, it uses a state machine
|
|
* (implemented with a switch statement) to process the data based on the current state of the parser.
|
|
* The states represent different parts of the SLUP package such as the head, sequence number (SN),
|
|
* frame type, length, data, checksum, and tail. Once a complete package is parsed and verified,
|
|
* it calls the slup_receive_package function to handle the received package and resets the buffer
|
|
* and parser state for the next package.
|
|
*/
|
|
static void slup_parse_task(SLUP *slup)
|
|
{
|
|
uint32_t i = 0;
|
|
char data = 0;
|
|
|
|
if (slup->queue.size > 0)
|
|
{
|
|
for (i = 0; i < slup->queue.size; i++)
|
|
{
|
|
data = slup_queue_at(&slup->queue, i);
|
|
|
|
SLUP_DEBUG("%02x ", data);
|
|
|
|
switch (slup->parser.state)
|
|
{
|
|
case SLUP_RX_STATE_HEAD:
|
|
{
|
|
// If the current index for the head (hindex) is less than the configured head size
|
|
if (slup->parser.hindex < slup->cfg.hsize)
|
|
{
|
|
// If the received data byte matches the expected head byte at the current index
|
|
if (data == slup->cfg.head[slup->parser.hindex])
|
|
{
|
|
// Increment the head index
|
|
slup->parser.hindex++;
|
|
|
|
// If the head index reaches the configured head size, it means the head is fully received
|
|
if (slup->parser.hindex == slup->cfg.hsize)
|
|
{
|
|
slup->parser.hindex = 0;
|
|
SLUP_DEBUG(" [SLUP_RX_STATE_HEAD] OK\r\n");
|
|
// Move to the next state which is to receive the sequence number (SN)
|
|
slup->parser.state = SLUP_RX_STATE_SN;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If the received byte doesn't match, reset the head index
|
|
slup->parser.hindex = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
} break;
|
|
case SLUP_RX_STATE_SN:
|
|
{
|
|
// If the current index for the sequence number (sindex) is less than the configured SN size
|
|
if (slup->parser.sindex < slup->cfg.ssize)
|
|
{
|
|
// Store the received data byte into the appropriate position of the parser's SN
|
|
((uint8_t *)(&(slup->parser.sn)))[slup->parser.sindex] = data;
|
|
|
|
// Increment the sequence number index
|
|
slup->parser.sindex++;
|
|
|
|
// If the sequence number index reaches the configured SN size, it means the SN is fully received
|
|
if (slup->parser.sindex == slup->cfg.ssize)
|
|
{
|
|
slup->parser.sindex = 0;
|
|
SLUP_DEBUG(" [SLUP_RX_STATE_SN] OK\r\n");
|
|
// Move to the next state which is to receive the frame type
|
|
slup->parser.state = SLUP_RX_STATE_FRAMETYPE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
} break;
|
|
case SLUP_RX_STATE_FRAMETYPE:
|
|
{
|
|
// Store the received data byte as the frame type
|
|
slup->parser.frame = data;
|
|
SLUP_DEBUG(" [SLUP_RX_STATE_FRAMETYPE] OK\r\n");
|
|
// Move to the next state which is to receive the length
|
|
slup->parser.state = SLUP_RX_STATE_LENGTH;
|
|
} break;
|
|
case SLUP_RX_STATE_LENGTH:
|
|
{
|
|
// If the current index for the length (lindex) is less than the size of a uint16_t (since length is uint16_t)
|
|
if (slup->parser.lindex < sizeof(uint16_t))
|
|
{
|
|
// Store the received data byte into the appropriate position of the parser's length
|
|
((uint8_t *)(&(slup->parser.length)))[slup->parser.lindex] = data;
|
|
|
|
// Increment the length index
|
|
slup->parser.lindex++;
|
|
|
|
// If the length index reaches the size of a uint16_t, it means the length is fully received
|
|
if (slup->parser.lindex == sizeof(uint16_t))
|
|
{
|
|
slup->parser.lindex = 0;
|
|
SLUP_DEBUG(" [SLUP_RX_STATE_LENGTH] OK\r\n");
|
|
// Move to the next state which is to receive the data
|
|
slup->parser.state = SLUP_RX_STATE_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
} break;
|
|
case SLUP_RX_STATE_DATA:
|
|
{
|
|
// Store the received data byte into the buffer and increment the buffer size
|
|
slup->buffer[slup->bsize++] = data;
|
|
// If the current index for the data (dindex) is less than the received length
|
|
if (slup->parser.dindex < slup->parser.length)
|
|
{
|
|
// Increment the data index
|
|
slup->parser.dindex++;
|
|
|
|
// If the data index reaches the received length, it means the data is fully received
|
|
if (slup->parser.dindex == slup->parser.length)
|
|
{
|
|
slup->parser.dindex = 0;
|
|
SLUP_DEBUG(" [SLUP_RX_STATE_DATA] OK\r\n");
|
|
// Move to the next state which is to receive the checksum
|
|
slup->parser.state = SLUP_RX_STATE_CHECK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
} break;
|
|
case SLUP_RX_STATE_CHECK:
|
|
{
|
|
// If the current index for the checksum (cindex) is less than the configured checksum size
|
|
if (slup->parser.cindex < slup->cfg.csize)
|
|
{
|
|
// Store the received data byte into the appropriate position of the parser's checksum
|
|
((uint8_t *)(&(slup->parser.check)))[slup->parser.cindex] = data;
|
|
|
|
// Increment the checksum index
|
|
slup->parser.cindex++;
|
|
|
|
// If the checksum index reaches the configured checksum size, it means the checksum is fully received
|
|
if (slup->parser.cindex == slup->cfg.csize)
|
|
{
|
|
slup->parser.cindex = 0;
|
|
|
|
uint32_t cvalue = 0;
|
|
|
|
// Calculate the checksum of the received data in the buffer
|
|
cvalue = (slup->check)(slup->buffer, slup->bsize);
|
|
|
|
// Compare the calculated checksum with the received checksum
|
|
if (memcmp(&cvalue, &slup->parser.check, slup->cfg.csize) == 0)
|
|
{
|
|
SLUP_DEBUG(" [SLUP_RX_STATE_CHECK] OK\r\n");
|
|
// Move to the next state which is to receive the tail
|
|
slup->parser.state = SLUP_RX_STATE_TAIL;
|
|
}
|
|
else
|
|
{
|
|
// If the checksums don't match, reset the buffer size for the next reception
|
|
slup->bsize = 0;
|
|
// Reset the parser state to start receiving a new package from the head
|
|
slup->parser.state = SLUP_RX_STATE_HEAD;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
} break;
|
|
case SLUP_RX_STATE_TAIL:
|
|
{
|
|
// If the current index for the tail (tindex) is less than the configured tail size
|
|
if (slup->parser.tindex < slup->cfg.tsize)
|
|
{
|
|
// If the received data byte matches the expected tail byte at the current index
|
|
if (data == slup->cfg.tail[slup->parser.tindex])
|
|
{
|
|
// Increment the tail index
|
|
slup->parser.tindex++;
|
|
|
|
// If the tail index reaches the configured tail size, it means the tail is fully received
|
|
if (slup->parser.tindex == slup->cfg.tsize)
|
|
{
|
|
slup->parser.tindex = 0;
|
|
SLUP_DEBUG(" [SLUP_RX_STATE_TAIL] OK\r\n");
|
|
// Call the function to handle the received package
|
|
slup_receive_package(slup);
|
|
// Reset the buffer size for the next reception
|
|
slup->bsize = 0;
|
|
// Reset the parser state to start receiving a new package from the head
|
|
slup->parser.state = SLUP_RX_STATE_HEAD;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If the received byte doesn't match, reset the tail index and the parser state to start from the head
|
|
slup->parser.tindex = 0;
|
|
slup->parser.state = SLUP_RX_STATE_HEAD;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Pop all the data from the queue after processing
|
|
slup_queue_pop(&slup->queue, 0xFFFFF);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Calculate the upload and download rates and reset the bit counters.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
*
|
|
* This function is responsible for calculating the upload and download rates.
|
|
* It copies the current values of 'upbits' and 'downbits' to 'uprate' and 'downrate' respectively.
|
|
* Then it resets 'upbits' and 'downbits' to zero, preparing for the next rate calculation.
|
|
*/
|
|
static void slup_calrate_task(SLUP *slup)
|
|
{
|
|
slup->uprate = slup->upbits;
|
|
slup->downrate = slup->downbits;
|
|
slup->upbits = 0;
|
|
slup->downbits = 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Update the dummy data parameters based on the upload rate.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
*
|
|
* This function updates the 'gapcount', 'gapbase', 'compression', and 'rate' fields
|
|
* in the 'dummy' structure of the SLUP object. It first calculates the deviation
|
|
* between the upload rate and the target rate. If the upload rate is less than the target,
|
|
* it increases the 'gapcount' by a fixed resolution value. If the upload rate is greater
|
|
* than the target, it decreases the 'gapcount' by the same resolution value.
|
|
* Then it calculates the 'gapbase' as the integer part of 'gapcount' divided by 100,
|
|
* and the 'compression' as the fractional part of 'gapcount' divided by 100 minus 'gapbase'.
|
|
* Finally, it sets the 'rate' to the 'compression' value.
|
|
*/
|
|
static void slup_dummy_update(SLUP *slup)
|
|
{
|
|
const uint32_t resolution = 5;
|
|
|
|
/* Update the deviation value and record it in 'slup->dummy.gapcount' */
|
|
if (slup->uprate < slup->dummy.target)
|
|
{
|
|
if (slup->dummy.gapcount + resolution > slup->dummy.gapcount)
|
|
{
|
|
slup->dummy.gapcount += resolution;
|
|
}
|
|
}
|
|
else if (slup->uprate > slup->dummy.target)
|
|
{
|
|
if (slup->dummy.gapcount >= resolution)
|
|
{
|
|
slup->dummy.gapcount -= resolution;
|
|
}
|
|
}
|
|
|
|
/* Update the basic sending number and compression rate of the sending point */
|
|
slup->dummy.gapbase = (uint32_t)(slup->dummy.gapcount / 100);
|
|
slup->dummy.compression = (double)slup->dummy.gapcount / 100.0 - slup->dummy.gapbase;
|
|
slup->dummy.rate = slup->dummy.compression;
|
|
}
|
|
|
|
/**
|
|
* \brief Execute the dummy data sending process based on the calculated parameters.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
*
|
|
* This function calculates the number of messages to send based on the 'gapbase'
|
|
* and 'compression' values in the 'dummy' structure of the SLUP object. It adds the
|
|
* 'compression' value to the 'rate'. If the 'rate' exceeds 1.0, it subtracts 1.0 from
|
|
* the 'rate' and increments the number of messages to send.
|
|
* If there are messages to send, it calls the 'slup_send' function to send the dummy data
|
|
* in the 'dummy' structure 'send' times.
|
|
*/
|
|
static void slup_dummy_execute(SLUP *slup)
|
|
{
|
|
uint32_t send = 0;
|
|
|
|
/* Calculate how many messages the current sending point needs to send */
|
|
send = slup->dummy.gapbase;
|
|
slup->dummy.rate += slup->dummy.compression;
|
|
if (slup->dummy.rate > 1.0)
|
|
{
|
|
slup->dummy.rate -= 1.0;
|
|
send++;
|
|
}
|
|
|
|
/* Evenly 'gapCount' the difference to each sending point for sending */
|
|
if (send > 0)
|
|
{
|
|
for (int i = 0; i < send; i++)
|
|
{
|
|
slup_send(slup, slup->dummy.data, sizeof(slup->dummy.data));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Sends a heartbeat message in the SLUP protocol.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \return SLUP_E_OK if the message is successfully sent, appropriate error code otherwise.
|
|
*
|
|
* This function constructs a heartbeat message. It sets the first byte of the data buffer
|
|
* to the current link status from the SLUP structure. Then it calls the slup_send_package
|
|
* function with a frame type of 0x00 to send the message.
|
|
*/
|
|
static int slup_send_heart(SLUP *slup)
|
|
{
|
|
uint8_t data[SLUP_SN_MAX];
|
|
uint16_t length = 0;
|
|
|
|
data[0] = slup->link;
|
|
|
|
length = 1;
|
|
|
|
return slup_send_package(slup, 0x00, data, length);
|
|
}
|
|
|
|
/**
|
|
* \brief Initializes the SLUP structure.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \return SLUP_E_OK if the initialization is successful, SLUP_E_INVALID if the pointer is NULL.
|
|
*
|
|
* This function initializes various fields in the SLUP structure. It sets the buffer size (bsize),
|
|
* sequence number (sn), and timestamp to 0. It also initializes the queue's head, tail, and size to 0,
|
|
* and clears the parser structure using memset.
|
|
*/
|
|
int slup_init(SLUP *slup)
|
|
{
|
|
if (!slup) return SLUP_E_INVALID;
|
|
|
|
// memset(slup, 0, sizeof(SLUP));
|
|
|
|
slup->bsize = 0;
|
|
slup->sn = 0;
|
|
slup->timestamp = 0;
|
|
|
|
/* Init queue */
|
|
slup->queue.head = 0;
|
|
slup->queue.tail = 0;
|
|
slup->queue.size = 0;
|
|
|
|
/* Init parser */
|
|
memset(&slup->parser, 0, sizeof(SLUP_PARSER));
|
|
|
|
return SLUP_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Sends data in the SLUP protocol with a frame type of 0x01.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \param data: Pointer to the data buffer to be sent.
|
|
* \param length: The length of the data buffer.
|
|
* \return SLUP_E_OK if the data is successfully sent, appropriate error code otherwise.
|
|
*
|
|
* This function simply calls the slup_send_package function with a frame type of 0x01
|
|
* to send the provided data.
|
|
*/
|
|
int slup_send(SLUP *slup, uint8_t *data, uint16_t length)
|
|
{
|
|
return slup_send_package(slup, 0x01, data, length);
|
|
}
|
|
|
|
/**
|
|
* \brief Handles the reception of a single character in the SLUP system.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \param c: The received character.
|
|
*
|
|
* This function updates the link status to indicate a received character (sets SLUP_LINK_RX),
|
|
* clears the silent flag, updates the download statistics, and pushes the received character
|
|
* into the queue.
|
|
*/
|
|
void slup_getc(SLUP *slup, char c)
|
|
{
|
|
if (!slup) return;
|
|
|
|
slup->link |= SLUP_LINK_RX;
|
|
slup->silent = 0;
|
|
|
|
slup_statis_download(slup);
|
|
|
|
slup_queue_push(&slup->queue, c);
|
|
}
|
|
|
|
/**
|
|
* \brief Retrieves the current link status from the SLUP structure.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \param link: Pointer to a variable where the link status will be stored.
|
|
* \return SLUP_E_OK if the retrieval is successful, appropriate error code otherwise.
|
|
*
|
|
* This function checks if the provided pointers are valid. If so, it copies the current
|
|
* link status from the SLUP structure to the provided variable.
|
|
*/
|
|
int slup_link_status(SLUP *slup, uint8_t *link)
|
|
{
|
|
if (!slup) return SLUP_E_INVALID;
|
|
if (!link) return SLUP_E_LINK;
|
|
|
|
*link = slup->link;
|
|
|
|
return SLUP_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Retrieves the upload rate from the SLUP structure.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \param rate: Pointer to a variable where the upload rate will be stored.
|
|
* \return SLUP_E_OK if the retrieval is successful, appropriate error code otherwise.
|
|
*
|
|
* This function checks if the provided pointers are valid. If so, it copies the current
|
|
* upload rate from the SLUP structure to the provided variable.
|
|
*/
|
|
int slup_upload_rate(SLUP *slup, uint32_t *rate)
|
|
{
|
|
if (!slup) return SLUP_E_INVALID;
|
|
if (!rate) return SLUP_E_RATE;
|
|
|
|
*rate = slup->uprate;
|
|
|
|
return SLUP_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Retrieves the download rate from the SLUP structure.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \param rate: Pointer to a variable where the download rate will be stored.
|
|
* \return SLUP_E_OK if the retrieval is successful, appropriate error code otherwise.
|
|
*
|
|
* This function checks if the provided pointers are valid. If so, it copies the current
|
|
* download rate from the SLUP structure to the provided variable.
|
|
*/
|
|
int slup_download_rate(SLUP *slup, uint32_t *rate)
|
|
{
|
|
if (!slup) return SLUP_E_INVALID;
|
|
if (!rate) return SLUP_E_RATE;
|
|
|
|
*rate = slup->downrate;
|
|
|
|
return SLUP_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Sets the target rate for the dummy data in the SLUP structure.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
* \param rate: The target rate value to be set.
|
|
* \return SLUP_E_OK if the setting is successful, SLUP_E_INVALID if the pointer is NULL.
|
|
*
|
|
* This function checks if the provided pointer is valid. If so, it sets the target rate
|
|
* in the dummy data part of the SLUP structure to the provided value.
|
|
*/
|
|
int slup_set_dummy(SLUP *slup, uint32_t rate)
|
|
{
|
|
if (!slup) return SLUP_E_INVALID;
|
|
|
|
slup->dummy.target = rate;
|
|
|
|
return SLUP_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief The main task function for the SLUP system.
|
|
* \param slup: Pointer to the SLUP structure.
|
|
*
|
|
* This function is the main task handler for the SLUP system. It updates the timestamp,
|
|
* and based on the timestamp value, performs various operations such as sending heartbeat
|
|
* messages, calculating rates, executing dummy data sending, and updating dummy data parameters.
|
|
* It also calls the slup_parse_task function to parse the received data in the queue.
|
|
*/
|
|
void slup_task(SLUP *slup)
|
|
{
|
|
if (!slup) return;
|
|
|
|
slup->timestamp += slup->period;
|
|
if (slup->timestamp >= 252000000) slup->timestamp = 0;
|
|
|
|
if (slup->timestamp % 500 == 0)
|
|
{
|
|
if (slup->silent < 3)
|
|
{
|
|
slup->silent++;
|
|
}
|
|
else
|
|
{
|
|
slup->link &= (~SLUP_LINK_RX);
|
|
}
|
|
|
|
slup_send_heart(slup);
|
|
}
|
|
|
|
if (slup->timestamp % 1000 == 0)
|
|
{
|
|
slup_calrate_task(slup);
|
|
}
|
|
|
|
if (slup->timestamp % 10 == 0)
|
|
{
|
|
slup_dummy_execute(slup);
|
|
}
|
|
|
|
if (slup->timestamp % 1000 == 0)
|
|
{
|
|
slup_dummy_update(slup);
|
|
}
|
|
|
|
slup_parse_task(slup);
|
|
}
|
|
|