<commit_before>/*
 *
 *  Derived from CanDemo.pde, example code that came with the
 *  chipKIT Network Shield libraries.
 */

#include <stdint.h>
#include "chipKITCAN.h"
#include "chipKITUSBDevice.h"
#include "bitfield.h"
#include "canutil_chipkit.h"
#include "canwrite_chipkit.h"
#include "usbutil.h"
#include "cJSON.h"
#include "signals.h"

#define VERSION_CONTROL_COMMAND 0x80
#define RESET_CONTROL_COMMAND 0x81

// USB
#define DATA_ENDPOINT 1

extern char* MESSAGE_SET;

char* VERSION = "2.0-pre";
CAN can1(CAN::CAN1);
CAN can2(CAN::CAN2);

// USB

#define DATA_ENDPOINT 1

USB_HANDLE USB_OUTPUT_HANDLE = 0;
CanUsbDevice usbDevice = {USBDevice(usbCallback), DATA_ENDPOINT, ENDPOINT_SIZE};

int receivedMessages = 0;
unsigned long lastSignificantChangeTime;
int receivedMessagesAtLastMark = 0;

/* Forward declarations */

void initializeAllCan();
void receiveCan(CanBus*);
void decodeCanMessage(int id, uint8_t* data);
void checkIfStalled();
void receiveWriteRequest(char*);

void setup() {
    Serial.begin(115200);

    initializeUsb(&usbDevice);
    initializeAllCan();
    lastSignificantChangeTime = millis();
}

void loop() {
    for(int i = 0; i < CAN_BUS_COUNT; i++) {
        receiveCan(&getCanBuses()[i]);
    }
    USB_OUTPUT_HANDLE = readFromHost(
            &usbDevice, USB_OUTPUT_HANDLE, &receiveWriteRequest);
    checkIfStalled();
}

void initializeAllCan() {
    for(int i = 0; i < CAN_BUS_COUNT; i++) {
        initializeCan(&(getCanBuses()[i]));
    }
}

void mark() {
    lastSignificantChangeTime = millis();
    receivedMessagesAtLastMark = receivedMessages;
}

void checkIfStalled() {
    // a workaround to stop CAN from crashing indefinitely
    // See these tickets in Redmine:
    // https://fiesta.eecs.umich.edu/issues/298
    // https://fiesta.eecs.umich.edu/issues/244
    if(receivedMessagesAtLastMark + 10 < receivedMessages) {
        mark();
    }

    if(receivedMessages > 0 && receivedMessagesAtLastMark > 0
            && millis() > lastSignificantChangeTime + 500) {
        initializeAllCan();
        delay(200);
        mark();
    }
}

void receiveWriteRequest(char* message) {
    if(message != NULL) {
        cJSON *root = cJSON_Parse(message);
        if(root != NULL) {
            char* name = cJSON_GetObjectItem(root, "name")->valuestring;
            CanSignal* signal = lookupSignal(name, getSignals(),
                    getSignalCount());
            if(signal != NULL) {
                sendCanSignal(signal,
                        cJSON_GetObjectItem(root, "value"),
                        signal->writeHandler, getSignals(),
                        getSignalCount());
            } else {
                Serial.print("Writing not allowed for signal with name ");
                Serial.println(name);
            }
            cJSON_Delete(root);
        }
    }
}

/*
 * Check to see if a packet has been received. If so, read the packet and print
 * the packet payload to the serial monitor.
 */
void receiveCan(CanBus* bus) {
    CAN::RxMessageBuffer* message;

    if(bus->messageReceived == false) {
        // The flag is updated by the CAN ISR.
        return;
    }
    ++receivedMessages;<commit_msg>Attempt to buffer 4 packets of an OUT message.<commit_after>/*
 *
 *  Derived from CanDemo.pde, example code that came with the
 *  chipKIT Network Shield libraries.
 */

#include <stdint.h>
#include "chipKITCAN.h"
#include "chipKITUSBDevice.h"
#include "bitfield.h"
#include "canutil_chipkit.h"
#include "canwrite_chipkit.h"
#include "usbutil.h"
#include "cJSON.h"
#include "signals.h"

#define VERSION_CONTROL_COMMAND 0x80
#define RESET_CONTROL_COMMAND 0x81

// USB
#define DATA_ENDPOINT 1

extern char* MESSAGE_SET;

char* VERSION = "2.0-pre";
CAN can1(CAN::CAN1);
CAN can2(CAN::CAN2);

// USB

#define DATA_ENDPOINT 1

USB_HANDLE USB_OUTPUT_HANDLE = 0;
CanUsbDevice usbDevice = {USBDevice(usbCallback), DATA_ENDPOINT, ENDPOINT_SIZE};

int receivedMessages = 0;
unsigned long lastSignificantChangeTime;
int receivedMessagesAtLastMark = 0;

// buffer messages up to 4x 1 USB packet in size waiting for a NUL char
char messageBuffer[ENDPOINT_SIZE * 4];

/* Forward declarations */

void initializeAllCan();
void receiveCan(CanBus*);
void decodeCanMessage(int id, uint8_t* data);
void checkIfStalled();
void receiveWriteRequest(char*);

void setup() {
    Serial.begin(115200);

    initializeUsb(&usbDevice);
    initializeAllCan();
    lastSignificantChangeTime = millis();
}

void loop() {
    for(int i = 0; i < CAN_BUS_COUNT; i++) {
        receiveCan(&getCanBuses()[i]);
    }
    USB_OUTPUT_HANDLE = readFromHost(
            &usbDevice, USB_OUTPUT_HANDLE, &receiveWriteRequest);
    checkIfStalled();
}

void initializeAllCan() {
    for(int i = 0; i < CAN_BUS_COUNT; i++) {
        initializeCan(&(getCanBuses()[i]));
    }
}

void mark() {
    lastSignificantChangeTime = millis();
    receivedMessagesAtLastMark = receivedMessages;
}

void checkIfStalled() {
    // a workaround to stop CAN from crashing indefinitely
    // See these tickets in Redmine:
    // https://fiesta.eecs.umich.edu/issues/298
    // https://fiesta.eecs.umich.edu/issues/244
    if(receivedMessagesAtLastMark + 10 < receivedMessages) {
        mark();
    }

    if(receivedMessages > 0 && receivedMessagesAtLastMark > 0
            && millis() > lastSignificantChangeTime + 500) {
        initializeAllCan();
        delay(200);
        mark();
    }
}

/*
 * Thanks to https://gist.github.com/855214.
 */
const char *strnchr(const char *str, size_t len, int character) {
    const char *end = str + len;
    char c = (char)character;
    do {
        if(*str == c) {
            return str;
        }
    } while (++str <= end);
    return NULL;
}

void receiveWriteRequest(char* message) {
    if(message != NULL) {
        Serial.println(message);
        Serial.println(messageBuffer);
        // TODO we need to watch out when this gets over 4 packets in size
        strncat(messageBuffer, message, ENDPOINT_SIZE);
        if(strnchr(message, ENDPOINT_SIZE, NULL) == NULL) {
            return;
        }

        cJSON *root = cJSON_Parse(messageBuffer);
        if(root != NULL) {
            char* name = cJSON_GetObjectItem(root, "name")->valuestring;
            CanSignal* signal = lookupSignal(name, getSignals(),
                    getSignalCount());
            if(signal != NULL) {
                sendCanSignal(signal,
                        cJSON_GetObjectItem(root, "value"),
                        signal->writeHandler, getSignals(),
                        getSignalCount());
            } else {
                Serial.print("Writing not allowed for signal with name ");
                Serial.println(name);
            }
            cJSON_Delete(root);
        }
        messageBuffer[0] = NULL;
    }
}

/*
 * Check to see if a packet has been received. If so, read the packet and print
 * the packet payload to the serial monitor.
 */
void receiveCan(CanBus* bus) {
    CAN::RxMessageBuffer* message;

    if(bus->messageReceived == false) {
        // The flag is updated by the CAN ISR.
        return;
    }
    ++receivedMessages;
{'fraction_non_alphanumeric': 0.11686307519640853, 'fraction_numerical': 0.013468013468013467, 'mean_word_length': 2.7799575821845175, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 17, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6791498', 'n_tokens_mistral': 2295, 'n_tokens_neox': 2191, 'n_words': 547}