Newer
Older
#include "communication.h"
#include "uart_buff.h"
ucart@co3050-12
committed
#define INTC XScuGic
#define COMM_UART_DEVICE_ID XPAR_PS7_UART_0_DEVICE_ID
#define COMM_INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define COMM_UART_INT_IRQ_ID XPAR_PS7_UART_0_INTR//XPAR_XUARTPS_0_INTR
#define BAUD_RATE 921600
// Maximum number of bytes to be received within our loop time,
// plus the maximum packet size that might be carried over from the last call,
// plus 128 for a little buffer
// (bit/s) * (seconds) / (10 bits / byte for UART)
#define MAX_PACKET_SIZE 256
#define UART_BUF_SIZE (((BAUD_RATE * (DESIRED_USEC_PER_LOOP / 1000) / 1000) / 10) + MAX_PACKET_SIZE + 128)
// Declaration of interrupt handler
void Handler(void *CallBackRef, u32 Event, unsigned int EventData);
// Pointer to the UART driver instance
static XUartPs* uartInstPtr;
int initUartComms() {
uartInstPtr = uart0_init(COMM_UART_DEVICE_ID, BAUD_RATE);
// Initialize UART0 (Bluetooth/WiFi)
if(!uartInstPtr) {
return -1;
}
ucart@co3050-12
committed
uart0_clearFIFOs();
ucart@co3050-12
committed
if (uart0_int_init(COMM_UART_INT_IRQ_ID, (Xil_ExceptionHandler) uart_interrupt_handler) != XST_SUCCESS) {
return -1;
}
ucart@co3050-12
committed
/*
* Setup the handlers for the UART that will be called from the
* interrupt context when data has been sent and received, specify
* a pointer to the UART driver instance as the callback reference
* so the handlers are able to access the instance data
*/
//XUartPs_SetHandler(uartInstPtr, (XUartPs_Handler)Handler, uartInstPtr);
u32 IntrMask = XUARTPS_IXR_RXFULL | XUARTPS_IXR_RXOVR | XUARTPS_IXR_TOUT;
XUartPs_SetInterruptMask(uartInstPtr, IntrMask);
/*
* Set the receiver timeout. If it is not set, and the last few bytes
* of data do not trigger the over-water or full interrupt, the bytes
* will not be received. By default it is disabled.
* Timeout duration = RecvTimeout x 4 x Bit Period. 0 disables the
* timeout function.
*
* The setting of 8 will timeout after 8 x 4 = 32 character times.
* Increase the time out value if baud rate is high, decrease it if
* baud rate is low.
*/
XUartPs_SetRecvTimeout(uartInstPtr, 8);
ucart@co3050-12
committed
// Second argument is the number of bytes to trigger an interrupt at
XUartPs_SetFifoThreshold(uartInstPtr, 48);
return 0;
}
int process_packet(modular_structs_t *structs) {
ucart@co3050-12
committed
metadata_t meta_data;
// parse metadata
meta_data.begin_char = uart_buff_get_u8(0);
meta_data.msg_type = uart_buff_get_u8(1);
meta_data.msg_subtype = uart_buff_get_u8(2);
meta_data.msg_id = uart_buff_get_u16(3);
meta_data.data_len = uart_buff_get_u16(5);
unsigned char packet_checksum = uart_buff_get_u8(7+meta_data.data_len);
//unsigned char* packet_data = packet + sizeof(metadata_t);
ucart@co3050-12
committed
// Compute checksum
int i;
unsigned char calculated_checksum = 0;
ucart@co3050-12
committed
for(i = 0; i < meta_data.data_len + 7; i++){
ucart@co3050-12
committed
// Discard if checksum didn't match
if(packet_checksum != calculated_checksum) {
ucart@co3050-12
committed
printf("Checksums did not match: 0x%02x\t0x%02x\n", packet_checksum, calculated_checksum);
return -1;
}
ucart@co3050-12
committed
// Call appropriate function for packet
(* (MessageTypes[meta_data.msg_type].subtypes[meta_data.msg_subtype].functionPtr))(structs);

dawehr
committed
uart_buff_consume_packet();
ucart@co3050-12
committed
ucart@co3050-12
committed
}
/*
* Temporarily disables interrupts and returns the interrupt state, for restoring them
*/
u32 disable_interrupts() {
u32 ImrRegister;
ImrRegister = XUartPs_ReadReg(uartInstPtr->Config.BaseAddress, XUARTPS_IMR_OFFSET);
XUartPs_WriteReg(uartInstPtr->Config.BaseAddress, XUARTPS_IDR_OFFSET, XUARTPS_IXR_MASK);
return ImrRegister;
}
/*
* Restores the interrupt state, saved from disable_interrupts
*/
void restore_interrupts(u32 intr_state) {
XUartPs_WriteReg(uartInstPtr->Config.BaseAddress, XUARTPS_IER_OFFSET, intr_state);
}
void process_received(modular_structs_t *structs) {
// Parse as many packets as possible
while (uart_buff_packet_ready()) {
process_packet(structs);
}
ucart@co3050-12
committed
}
void uart_interrupt_handler(XUartPs *InstancePtr) {
u32 IsrStatus;
/*
* Read the interrupt ID register to determine which
* interrupt is active
*/
IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
XUARTPS_IMR_OFFSET);
IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
XUARTPS_ISR_OFFSET);
/*
* Read the Channel Status Register to determine if there is any data in
* the RX FIFO
*/
u32 CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
XUARTPS_SR_OFFSET);
while (0 == (CsrRegister & XUARTPS_SR_RXEMPTY) && !uart_buff_full()) {
u8 byte = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_FIFO_OFFSET);
uart_buff_put_byte(byte);
ucart@co3050-12
committed
CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_SR_OFFSET);
ucart@co3050-12
committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Clear the interrupt status.
XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
IsrStatus);
}
int send_data(u16 type_id, u16 subtype_id, u16 msg_id, char* data, size_t size) {
//----------------------------------------------------------------------------------------------
// index|| 0 | 1 | 2 | 3 & 4 | 5 & 6 | 7+ | end |
//---------------------------------------------------------------------------------------------|
// msg param|| beg char | msg type | msg subtype | msg id | data len (bytes) | data | checksum |
//-------------------------------------------------------------------------------------------- |
// bytes|| 1 | 1 | 1 | 2 | 2 | var | 1 |
//----------------------------------------------------------------------------------------------
char formattedHeader[7];
// Begin Char:
formattedHeader[0] = BEGIN_CHAR;
// Msg type:
formattedHeader[1] = type_id;
// Msg subtype
formattedHeader[2] = subtype_id;
//Msg id 2 bytes
formattedHeader[3] = msg_id & 0x000000ff;
formattedHeader[4] = (msg_id >> 8) & 0x000000ff;
// Data length and data - bytes 5&6 for len, 7+ for data
formattedHeader[5] = size & 0x000000ff;
formattedHeader[6] = (size >> 8) & 0x000000ff;
// Compute checksum while sending
unsigned char packet_checksum = 0;
int i;
ucart@co3050-12
committed
// TODO: Look into uart0_sendBytes and see if it would be better to use
// Send header
//uart0_sendBytes(formattedHeader, 7);
ucart@co3050-12
committed
for(i = 0; i < 7; i++) {
packet_checksum ^= formattedHeader[i];
uart0_sendByte(formattedHeader[i]);
ucart@co3050-12
committed
// Send data
for (i = 0; i < size; i++) {
packet_checksum ^= data[i];
uart0_sendByte(data[i]);
}
//uart0_sendBytes(data, size);
ucart@co3050-12
committed
// Send checksum
uart0_sendByte(packet_checksum);
return 0;