Changeset - a72d393244e6
[Not reviewed]
default
0 4 2
matthewreed - 8 years ago 2017-07-02 20:26:42

Added can buffering and protocol updates
6 files changed with 121 insertions and 12 deletions:
0 comments (0 inline, 0 general)
inc/can.h
Show inline comments
 
#ifndef _CAN_H_
 
#define _CAN_H_
 
 
#include <stdbool.h>
 
#include <string.h>
 
#include "stm32f0xx_hal.h"
 
 
#include "config.h"
 
#include "led.h"
 
#include "protocol.h"
 
#include "can_buffer.h"
 
 
extern CAN_HandleTypeDef can_handle;
 
 
void can_init(uint32_t rx_id, uint32_t broadcast_id);
 
void can_send_test(uint16_t id);
 
bool can_send(uint32_t id, uint32_t ide, uint8_t dlc, uint8_t data[8]);
 
void can_set_receive_mask(uint32_t mask);
 
void can_set_receive_id(uint32_t id);
 
bool can_silence_bus(bool value);
 
void can_receive(void);
 
void can_process_receive_buffer(void);
 
 
#endif //_CAN_H_
inc/can_buffer.h
Show inline comments
 
new file 100644
 
#ifndef _CAN_BUFFER_H
 
#define _CAN_BUFFER_H
 

	
 
#include <string.h>
 
#include "system.h"
 

	
 
#define CAN_BUFFER_SIZE 8
 

	
 
typedef enum CanBufferStatus {CAN_BUFFER_OK, CAN_BUFFER_EMPTY, CAN_BUFFER_FULL} CanBufferStatus;
 

	
 
typedef struct CanBuffer
 
{
 
    volatile CanRxMsgTypeDef data[CAN_BUFFER_SIZE];
 
    volatile uint8_t head;
 
    volatile uint8_t tail;
 
    volatile uint8_t count;
 
} CanBuffer;
 

	
 
void can_buffer_init(volatile CanBuffer *buffer);
 
CanBufferStatus can_buffer_add(volatile CanBuffer *buffer, CanRxMsgTypeDef *msg);
 
volatile CanRxMsgTypeDef* can_buffer_remove(volatile CanBuffer *buffer);
 
bool can_buffer_is_empty(volatile CanBuffer *buffer);
 
uint8_t can_buffer_size(volatile CanBuffer *buffer);
 

	
 
#endif //_CAN_BUFFER_H
inc/protocol.h
Show inline comments
 
#ifndef _PROTOCOL_H_
 
#define _PROTOCOL_H_
 
 
#include <stdbool.h>
 
 
#include "config.h"
 
#include "can.h"
 
#include "flash.h"
 
 
#define DEFAULT_BROADCAST_ID 0x00000000
 
 
typedef struct {
 
    bool command;
 
    uint8_t id;
 
    uint16_t key;
 
    uint8_t sensor;
 
    union {
 
        float float_data;
 
        uint8_t byte_data[4];
 
    } data;
 
}  protocol_message_t;
 
 
typedef enum {
 
    ESTOP = 0x00,
 
    SILENCE_BUS = 0x01,
 
    SET_OUTPUT = 0X10,
 
    GET_DATA = 0x11,
 
    CONFIG = 0x12,
 
    CALIBRATE = 0x13,
 
} protocol_command_t;
 
 
typedef enum {
 
    MASTER = 0x00,
 
    AIRSENSE = 0x01,
 
    RELAYDRIVE = 0X02,
 
    WATERSENSE = 0x03,
 
    PROTOMODULE = 0x04,
 
} protocol_device_t;
 
 
typedef enum {
 
    NONE = 0x0000,
 
    DIGITAL_INPUT = 0x0001,
 
    FREQ_INPUT = 0x0002,
 
    ANALOG_INPUT = 0x0003,
 
    DIGITAL_OUTPUT = 0x0004,
 
    FREQ_OUTPUT = 0x0005,
 
    PWM_OUTPUT = 0x0005,
 
    ANALOG_OUTPUT = 0x0006,
 
    AIR_TEMP = 0x0007,
 
    AIR_HUMIDITY = 0x0008,
 
    AIR_PRESSURE = 0x0009,
 
    AMBIENT_LIGHT = 0x000A,
 
    WATER_TEMP = 0x000B,
 
    WATER_LEVEL = 0x000C,
 
    WATER_CONDUCTIVITY = 0x000D,
 
    WATER_PH = 0x000E,
 
    CAN_ID = 0x0100,
 
    DATA_RATE = 0x0101,
 
    GPIO = 0x0102,
 
    LED_BRIGHTNESS = 0x0103,
 
} protocol_data_key_t;
 
 
void protocol_init(protocol_device_t device);
 
flash_settings_t* protocol_get_settings(void);
 
bool protocol_receive_message(CanRxMsgTypeDef* can_message);
 
bool protocol_send_message(protocol_message_t* message);
 
bool protocol_process_message(protocol_message_t* message);
 
bool protocol_send_data(protocol_data_key_t key, uint8_t sensor, float data);
 
bool protocol_send_test();
 
bool _protocol_config(protocol_message_t* message);
 
 
bool protocol_estop(bool value);
 
bool protocol_set_output(protocol_message_t* message);
 
bool protocol_get_data(protocol_message_t* message);
 
bool protocol_config(protocol_message_t* message);
 
 
#endif //_PROTOCOL_H_
src/can.c
Show inline comments
 
#include "can.h"
 
 
CAN_HandleTypeDef can_handle;
 
CAN_FilterConfTypeDef can_filter;
 
 
CanRxMsgTypeDef can_rx_msg;
 
CanTxMsgTypeDef can_tx_msg;
 
 
bool can_silenced;
 
uint32_t can_broadcast_id;
 
uint32_t can_rx_id;
 
 
volatile CanBuffer can_rx_buffer;
 
 
void can_init(uint32_t rx_id, uint32_t broadcast_id)
 
{
 
    can_handle.Instance = CAN;
 
    can_handle.pRxMsg = &can_rx_msg;
 
    can_handle.pTxMsg = &can_tx_msg;
 
 
    can_handle.Init.Mode = CAN_MODE_NORMAL;
 
    can_handle.Init.Prescaler = 6;
 
    can_handle.Init.SJW = CAN_SJW_1TQ;
 
    can_handle.Init.BS1 = CAN_BS1_11TQ;
 
    can_handle.Init.BS2 = CAN_BS2_4TQ;
 
    can_handle.Init.TTCM = DISABLE;
 
    can_handle.Init.ABOM = ENABLE;
 
    can_handle.Init.AWUM = DISABLE;
 
    can_handle.Init.NART = DISABLE;
 
    can_handle.Init.RFLM = DISABLE;
 
    can_handle.Init.TXFP = DISABLE;
 
    HAL_CAN_Init(&can_handle);
 
 
    can_filter.FilterNumber = 0;
 
    can_filter.BankNumber = 0;
 
    can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
 
    can_filter.FilterScale = CAN_FILTERSCALE_16BIT;
 
    uint32_t mask = 0x00000000;
 
    uint32_t id = 0x00000000;
 
    can_filter.FilterIdHigh = (id >> 11) & 0xFFFF;
 
    can_filter.FilterIdLow = (id << 5) & 0xFFFF;
 
    can_filter.FilterMaskIdHigh = (mask >> 11) & 0xFFFF;
 
    can_filter.FilterMaskIdLow = (mask << 5) & 0xFFFF;
 
    can_filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
 
    can_filter.FilterActivation = ENABLE;
 
    HAL_CAN_ConfigFilter(&can_handle, &can_filter);
 
 
    HAL_NVIC_SetPriority(CEC_CAN_IRQn, 1, 0);
 
    HAL_NVIC_EnableIRQ(CEC_CAN_IRQn);
 
    HAL_CAN_Receive_IT(&can_handle, CAN_FIFO0);
 
    //HAL_NVIC_SetPriority(CEC_CAN_IRQn, 1, 0);
 
    //HAL_NVIC_EnableIRQ(CEC_CAN_IRQn);
 
    //HAL_CAN_Receive_IT(&can_handle, CAN_FIFO0);
 
 
    can_silenced = false;
 
    can_rx_id = rx_id;
 
    can_broadcast_id = broadcast_id;
 
 
    can_buffer_init(&can_rx_buffer);
 
}
 
 
void can_send_test(uint16_t id)
 
{
 
    can_handle.pTxMsg->StdId = id;
 
    can_handle.pTxMsg->IDE = CAN_ID_STD;
 
    can_handle.pTxMsg->RTR = CAN_RTR_DATA;
 
    can_handle.pTxMsg->DLC = 4;
 
    can_handle.pTxMsg->Data[0] = 'T'; //0x54
 
    can_handle.pTxMsg->Data[1] = 'E'; //0x45
 
    can_handle.pTxMsg->Data[2] = 'S'; //0x53
 
    can_handle.pTxMsg->Data[3] = 'T'; //0x54
 
    HAL_CAN_Transmit_IT(&can_handle);
 
}
 
 
bool can_send(uint32_t id, uint32_t ide, uint8_t dlc, uint8_t data[8])
 
{
 
    bool result = true;
 
 
    if (!can_silenced)
 
    {
 
        can_handle.pTxMsg->StdId = id;
 
        can_handle.pTxMsg->ExtId = id;
 
        can_handle.pTxMsg->IDE = ide;
 
        can_handle.pTxMsg->RTR = CAN_RTR_DATA;
 
        can_handle.pTxMsg->DLC = dlc;
 
        memcpy(can_handle.pTxMsg->Data, data, 8);
 
 
        HAL_CAN_Transmit_IT(&can_handle);
 
    }
 
    else
 
    {
 
        result = false;
 
    }
 
 
    return result;
 
}
 
 
void can_set_receive_mask(uint32_t mask)
 
{
 
    can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
 
    can_filter.FilterScale = CAN_FILTERSCALE_32BIT;
 
    can_filter.FilterMaskIdHigh = (mask >> 16) & 0xFFFF;
 
    can_filter.FilterMaskIdLow = mask & 0xFFFF;
 
    can_filter.FilterActivation = ENABLE;
 
 
    HAL_CAN_ConfigFilter(&can_handle, &can_filter);
 
}
 
 
void can_set_receive_id(uint32_t id)
 
{
 
    can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
 
    can_filter.FilterScale = CAN_FILTERSCALE_32BIT;
 
    can_filter.FilterIdHigh = (id >> 16) & 0xFFFF;
 
    can_filter.FilterIdLow = id & 0xFFFF;
 
    can_filter.FilterActivation = ENABLE;
 
 
    HAL_CAN_ConfigFilter(&can_handle, &can_filter);
 
 
}
 
 
bool can_silence_bus(bool value)
 
{
 
    bool result = true;
 
 
    can_silenced = value;
 
 
    return result;
 
}
 
 
void can_receive(void)
 
{
 
    if ((can_handle.Instance->RF0R & CAN_RF0R_FMP0) != 0)
 
    {
 
        HAL_StatusTypeDef status = HAL_CAN_Receive(&can_handle, 0, 0);
 
 
        if ((status == HAL_OK) & ((can_handle.pRxMsg->StdId == can_rx_id) | (can_handle.pRxMsg->StdId == can_broadcast_id)))
 
        {
 
            can_buffer_add(&can_rx_buffer, can_handle.pRxMsg);
 
        }
 
        //can_handle.Instance->RF0R |= CAN_RF0R_RFOM0;
 
 
        led_blink_once(LED_CAN, 250);
 
    }
 
}
 
 
void can_process_receive_buffer(void)
 
{
 
    CanRxMsgTypeDef msg;
 
    uint8_t size = can_buffer_size(&can_rx_buffer);
 
 
    for (uint8_t i = 0; i < size; i++)
 
    {
 
        msg = *can_buffer_remove(&can_rx_buffer);
 
        protocol_receive_message(&msg);
 
    }
 
}
 
 
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)
 
{
 
    if ((hcan->pRxMsg->StdId == can_rx_id) | (hcan->pRxMsg->StdId == can_broadcast_id))
 
    {
 
        protocol_receive_message(hcan->pRxMsg);
 
        can_buffer_add(&can_rx_buffer, hcan->pRxMsg);
 
    }
 
 
    led_blink_once(LED_CAN, 500);
 
    led_blink_once(LED_ERROR, 500);
 
    HAL_CAN_Receive_IT(&can_handle, CAN_FIFO0);
 
}
 
 
void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan) {}
 
 
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef* hcan)
 
{
 
    led_set(LED_ERROR, 1);
 
}
src/can_buffer.c
Show inline comments
 
new file 100644
 
#include "can_buffer.h"
 

	
 
void can_buffer_init(volatile CanBuffer *buffer)
 
{
 
    memset((void*)buffer, 0, sizeof(CanBuffer));
 
}
 

	
 
CanBufferStatus can_buffer_add(volatile CanBuffer *buffer, CanRxMsgTypeDef *msg)
 
{
 
    if ((uint16_t) buffer->count < ((uint16_t) CAN_BUFFER_SIZE)) {
 
        buffer->data[buffer->head] = *msg;
 
        buffer->head = (buffer->head + 1) % CAN_BUFFER_SIZE;
 
        buffer->count++;
 
        return CAN_BUFFER_OK;
 
    }
 
    else {
 
        return CAN_BUFFER_FULL;
 
    }
 
}
 

	
 
volatile CanRxMsgTypeDef* can_buffer_remove(volatile CanBuffer *buffer)
 
{
 
    volatile CanRxMsgTypeDef* msg;
 
    if (buffer->count > 0) {
 
        msg = &buffer->data[buffer->tail];
 
        buffer->tail = (buffer->tail + 1) % CAN_BUFFER_SIZE;
 
        buffer->count--;
 
    }
 
    return msg;
 
}
 

	
 
bool can_buffer_is_empty(volatile CanBuffer *buffer)
 
{
 
    return (buffer->count < 1);
 
}
 

	
 
uint8_t can_buffer_size(volatile CanBuffer *buffer)
 
{
 
    return buffer->count;
 
}
src/protocol.c
Show inline comments
 
#include "protocol.h"
 
 
protocol_device_t protocol_device;
 
flash_settings_t protocol_settings;
 
 
void protocol_init(protocol_device_t device)
 
{
 
    protocol_device = device;
 
    flash_restore(&protocol_settings);
 
    led_set_brightness(protocol_settings.val.led_brightness);
 
 
    can_init(protocol_settings.val.can_id, DEFAULT_BROADCAST_ID);
 
}
 
 
flash_settings_t* protocol_get_settings(void)
 
{
 
    return &protocol_settings;
 
}
 
 
bool protocol_send_test()
 
{
 
    bool result = true;
 
    can_send_test(protocol_settings.val.can_id | 0x00000001);
 
    return result;
 
}
 
 
bool protocol_receive_message(CanRxMsgTypeDef* can_message)
 
{
 
    bool result = true;
 
    
 
    protocol_message_t message;
 
    message.command = can_message->Data[0] & 0x80;
 
    message.id = can_message->Data[0] & 0x7F;
 
    message.key = (can_message->Data[1] << 8) | can_message->Data[2];
 
    message.sensor = can_message->Data[3];
 
    message.data.byte_data[0] = can_message->Data[4];
 
    message.data.byte_data[1] = can_message->Data[5];
 
    message.data.byte_data[2] = can_message->Data[6];
 
    message.data.byte_data[3] = can_message->Data[7];
 
    
 
    protocol_process_message(&message);
 
    
 
    return result;
 
}
 
 
bool protocol_send_message(protocol_message_t* message)
 
{
 
    bool result = true;
 
    uint8_t data[8];
 
    
 
    data[0] = (message->command & 0x80) | (message->id & 0x7F);
 
    data[1] = (message->key >> 8) & 0xFF;
 
    data[2] = (message->key >> 0) & 0xFF;
 
    data[3] = message->sensor;
 
    data[4] = message->data.byte_data[0];
 
    data[5] = message->data.byte_data[1];
 
    data[6] = message->data.byte_data[2];
 
    data[7] = message->data.byte_data[3];
 
@@ -82,86 +83,94 @@ bool protocol_process_message(protocol_m
 
                }
 
                break;
 
            case SET_OUTPUT:
 
                {
 
                    //call set output weak function
 
                    result = protocol_set_output(message);
 
                }
 
                break;
 
            case GET_DATA:
 
                {
 
                    //call get data weak function
 
                    result = protocol_get_data(message);
 
                }
 
                break;
 
            case CONFIG:
 
                {
 
                    result = _protocol_config(message);
 
                }
 
                break;
 
            default:
 
                result = false;
 
                break;
 
        }
 
    }
 
    
 
    return result;
 
}
 
 
bool protocol_send_data(protocol_data_key_t key, uint8_t sensor, float data)
 
{
 
    bool result = true;
 
 
    protocol_message_t message;
 
    message.command = false;
 
    message.id = protocol_device;
 
    message.key = key;
 
    message.sensor = sensor;
 
    message.data.float_data = data;
 
 
    result = protocol_send_message(&message);
 
 
    return result;
 
}
 
 
bool _protocol_config(protocol_message_t* message)
 
{
 
    bool result = false;
 
 
    if (message->key == LED_BRIGHTNESS)
 
    if (message->key == CAN_ID)
 
    {
 
        uint32_t can_id = (uint16_t) message->data.float_data;
 
        protocol_settings.val.can_id = can_id;
 
        flash_save(&protocol_settings);
 
    }
 
    else if (message->key == DATA_RATE)
 
    {
 
        uint16_t data_rate = (uint16_t) message->data.float_data;
 
        protocol_settings.val.data_rate = data_rate * 1000;
 
        flash_save(&protocol_settings);
 
    }
 
    else if (message->key == LED_BRIGHTNESS)
 
    {
 
        uint8_t brightness = (uint8_t)message->data.float_data;
 
        result = led_set_brightness(brightness);
 
        protocol_settings.val.led_brightness = brightness;
 
    }
 
    else if (message->key == DATA_RATE)
 
    {
 
        uint16_t data_rate = (uint16_t) message->data.float_data;
 
        protocol_settings.val.data_rate = data_rate;
 
        flash_save(&protocol_settings);
 
    }
 
    else
 
    {
 
        //call config weak function
 
        result = protocol_config(message);
 
    }
 
    return result;
 
}
 
 
__weak bool protocol_estop(bool value)
 
{
 
    return false;
 
}
 
 
__weak bool protocol_set_output(protocol_message_t* message)
 
{
 
    return false;
 
}
 
 
__weak bool protocol_get_data(protocol_message_t* message)
 
{
 
    return false;
 
}
 
 
__weak bool protocol_config(protocol_message_t* message)
 
{
 
    return false;
 
}
0 comments (0 inline, 0 general)