Skip to content
Snippets Groups Projects
communication.c 6.48 KiB
Newer Older
#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) {
	if (uart0_int_init(COMM_UART_INT_IRQ_ID, (Xil_ExceptionHandler) uart_interrupt_handler) != XST_SUCCESS) {
	/*
	 * 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);

	// 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) {
bbartels's avatar
bbartels committed
	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);
	unsigned char calculated_checksum = 0;
	for(i = 0; i < meta_data.data_len + 7; i++){
bbartels's avatar
bbartels committed
		calculated_checksum ^= uart_buff_get_u8(i);
	if(packet_checksum != calculated_checksum) {
		printf("Checksums did not match: 0x%02x\t0x%02x\n", packet_checksum, calculated_checksum);
		return -1;
	(* (MessageTypes[meta_data.msg_type].subtypes[meta_data.msg_subtype].functionPtr))(structs);
	uart_buff_flush_packet();
}

/*
 * 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()) {
		u32 start = timer_get_count();
		process_packet(structs);
		u32 end = timer_get_count();
		u32 duration = end - start;
		send_data(0, 0, 0, (char *) &duration, 4);
}

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);
		CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_SR_OFFSET);

	// 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;

	// TODO: Look into uart0_sendBytes and see if it would be better to use
	// Send header
	for(i = 0; i < 7; i++) {
		packet_checksum ^= formattedHeader[i];
		uart0_sendByte(formattedHeader[i]);
	// Send data
	for (i = 0; i < size; i++) {
		packet_checksum ^= data[i];
		uart0_sendByte(data[i]);
	// Send checksum
	uart0_sendByte(packet_checksum);

	return 0;