//*****************************************************************************
//
// main.c - CAN to UART bridge example.
//
// Copyright (c) 2020 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "main.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>CAN UART BRIDGE Example (can)</h1>
//!
//! This example interfaces a UART to a CAN bus. It receives data on UART0
//! then sends it out on CAN0 and receives data on CAN0 then sends it out on
//! UART0. By default UART0 is configured for 115200 baud (defined in
//! UartFunctions.h) and CAN0 is configured for 1M baud (defined in
//! CanFunctions.h). At these rates continuous data received on the UART
//! will consume 17% of the CAN bus bandwidth.
//!
//! Data received by either UART or CAN is handled by interrupt routines.
//! The received data is put into its respective circular buffer. Both buffers
//! are defined with a size of 256 bytes (defined in main.h). When continuous
//! data is received on the UART, the UART interrupt routine is triggered
//! after receiving four bytes, a half full FIFO. The data is then collected
//! until eight bytes are received before being put in the circular buffer.
//! This allows the CAN transmission to be the most efficient by supporting
//! up to eight bytes in a CAN packet. When the UART reception halts or
//! pauses, a receive timeout (RT) interrupt is generated. In this case, all
//! the bytes in the UART receive FIFO are transferred to the circular buffer
//! and a CAN frame of less than eight bytes is sent.
//!
//! The arbitration ID for CAN transmitted messages and CAN received messages
//! is the same, 0x101 (defined in CanFunctions.h). This allows two devices
//! running the same software to transmit data from one serial port to another
//! over a CAN network. With more than two devices on the network running the
//! same software, data received on one serial port is transmitted through the
//! CAN network and then output on the serial ports of all the other devices.
//!
//! CAN HARDWARE SETUP:
//!
//! To use this example you will need to hook up two EK-TM4C123G boards with
//! CAN drivers such as found on the edde FLEX CAN Booster Pack together in a
//! CAN network. This involves hooking the CANH screw terminals together and
//! the CANL terminals together. In addition 120ohm termination resistors will
//! need to be added to the edges of the network between CANH and CANL.  This
//! can be done using the resistor on-board the booster pack by placing DIP
//! switch three in the "on" position.
//!
//! See diagram below for visual. '---' represents wire.
//!
//! \verbatim
//!       CANH--+--------------------------+--CANH
//!             |                          |
//!            .-.                        .-.
//!            | |120ohm                  | |120ohm
//!            | |                        | |
//!            '-'                        '-'
//!             |                          |
//!       CANL--+--------------------------+--CANL
//! \endverbatim
//!
//! SOFTWARE SETUP:
//!
//! Once the hardware connections are setup connect both boards to the computer
//! via the In-Circuit Debug Interface USB port next to the graphical display.
//! Attach a UART terminal to each board configured 115,200 baud, 8-n-1 mode.
//!
//! Anything you type into one terminal will show up in the other terminal and
//! vice versa.
//
//*****************************************************************************

//*****************************************************************************
//
// Define circular buffers for UART and CAN received data
//
//*****************************************************************************
uint8_t g_ui8CANRxBuffer[BUFFER_SIZE];
uint8_t g_ui8UARTRxBuffer[BUFFER_SIZE];
circular_buf_t g_sUARTBuffer;
circular_buf_t g_sCANBuffer;

//*****************************************************************************
//
// A global to keep track of the error flags that have been thrown so they may
// be processed. This is necessary because reading the error register clears
// the flags, so it is necessary to save them somewhere for processing.
//
//*****************************************************************************
volatile uint32_t g_ui32ErrFlag = 0;

//*****************************************************************************
//
// CAN message Objects for data being sent / received
//
//*****************************************************************************
tCANMsgObject g_sCAN0RxMessage;
uint8_t g_ui8RXMsgData[8];
tCANMsgObject g_sCAN0TxMessage;

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif


//*****************************************************************************
//
// Set up the system, initialize the UART, and CAN. Then poll the
// UART for data. If there is any data send it, if there is any thing received
// print it out to the UART. If there are errors call the error handling
// function.
//
//*****************************************************************************
int
main(void)
{
    uint8_t data[8];
    uint32_t i;
    //
    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    MAP_FPULazyStackingEnable();

    //
    // Setup the system clock to run at 80 Mhz from PLL with PIOSC reference
    //
    MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|
                   SYSCTL_OSC_INT);
    // Initialize the UART
    ConfigureUART();
    // Initialize CAN0
    InitCAN0();
    // Enable interrupts
    MAP_IntMasterEnable();

    while(1)
    {
        //
        // If there are characters in the CAN buffer, send them out the UART
        //
        while(UARTSpaceAvail(UART0_BASE))
        {
            if(circular_buf_get(&g_sCANBuffer, data))
            {
                MAP_UARTCharPut(UART0_BASE, data[0]);
            }
            else
            {
                break;
            }
        }
        //
        // If there are characters in the UART buffer, and the last CAN
        // transmission completed, send the new characters out the CAN
        //
        if((circular_buf_empty(&g_sUARTBuffer) == false) && \
           ((CANStatusGet(CAN0_BASE, CAN_STS_TXREQUEST) &   \
            (1 << (TXOBJECT - 1))) == 0))
        {
            for(i = 0; i < 8; i++)
            {
                if(circular_buf_get(&g_sUARTBuffer, data + i) == false)
                {
                    break;
                }
            }
            g_sCAN0TxMessage.ui32MsgLen = i;
            g_sCAN0TxMessage.pui8MsgData = data;
            CANMessageSet(CAN0_BASE, TXOBJECT, &g_sCAN0TxMessage,
                                          MSG_OBJ_TYPE_TX);
        }

        //
        // Error Handling
        //
        if(g_ui32ErrFlag != 0)
        {
            // Add error handling here
            g_ui32ErrFlag = 0;
        }
    }
}
