Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added simulation project #256

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions projects/simulation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!--
General guidelines
These are just guidelines, not strict rules - document however seems best.
A README for a firmware-only project (e.g. Babydriver, MPXE, bootloader, CAN explorer) should answer the following questions:
- What is it?
- What problem does it solve?
- How do I use it? (with usage examples / example commands, etc)
- How does it work? (architectural overview)
A README for a board project (powering a hardware board, e.g. power distribution, centre console, charger, BMS carrier) should answer the following questions:
- What is the purpose of the board?
- What are all the things that the firmware needs to do?
- How does it fit into the overall system?
- How does it work? (architectural overview, e.g. what each module's purpose is or how data flows through the firmware)
-->
# simulation

6 changes: 6 additions & 0 deletions projects/simulation/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"libs": [
"FreeRTOS",
"ms-common"
]
}
37 changes: 37 additions & 0 deletions projects/simulation/inc/operation_listener.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
#include <poll.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#include "adc.h"
#include "gpio.h"
#include "gpio_it.h"
#include "i2c.h"
#include "log.h"

#define x86 1
#define PORT 2520

void sim_init(int sock_num);

typedef enum {
GPIO_SET = 0,
GPIO_TOGGLE,
GPIO_IT_TRIGGER,
ADC_SET_READING,
I2C_SET_READING,
SPI_SET_RX,
UART,
NUM_OF_OPERATIONS
} Operations;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just add a NUM_OF_OPERATIONS at the end

206 changes: 206 additions & 0 deletions projects/simulation/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
#include "operation_listener.h"
#include "spi.h"

bool s_keep_alive = true;

void gpio_set_sim(char buffer[]) {
int param1, param2, param3;
LOG_DEBUG("GPIO_SET\n");
if (length != 3) {
LOG_DEBUG("Invalid length: %d\n", length);
return;
}

sscanf(buffer, "%d, %d, %d", &param1, &param2, &param3);
if (param1 < 0 || param2 < 0 || param3 < 0 || param1 > 6 || param2 > 16 || param3 > 1) {
LOG_DEBUG("Invalid param, 1: %d, 2: %d, 3: %d\n", param1, param2, param3);
return;
}

GpioAddress GPIO_SET_ADDR = { .port = param1, .pin = param2 };
gpio_set_state(&GPIO_SET_ADDR, param3);
}

void gpio_toggle_sim(int length, char buffer[]) {
int param1, param2;
LOG_DEBUG("GPIO_TOGGLE\n");
if (length != 2) {
LOG_DEBUG("Invalid length: %d\n", length);
return;
}
sscanf(buffer, "%d, %d, %d", &param1, &param2);
if (param1 < 0 || param2 < 0 || param1 > 6 || param2 > 16) {
LOG_DEBUG("Invalid param, 1: %d, 2: %d\n", param1, param2);
return;
}

GpioAddress GPIO_TOGGLE_ADDR = { .port = param1, .pin = param2 };
gpio_toggle_state(&GPIO_TOGGLE_ADDR);
}

void gpio_it_trigger_sim(int length, char buffer[]) {
LOG_DEBUG("GPIO_IT_TRIGGER\n");
int param1, param2;
if (length != 2) {
LOG_DEBUG("Invalid length: %d\n", length);
return;
}
sscanf(buffer, "%d, %d", &param1, &param2);
if (param1 < 0 || param2 < 0 || param1 > 6 || param2 > 16) {
LOG_DEBUG("Invalid param, 1: %d, 2: %d\n", param1, param2);
return;
}

GpioAddress IT_TRIGGER_ADDR = { .port = param1, .pin = param2 };
gpio_it_trigger_interrupt(&IT_TRIGGER_ADDR);
}

void adc_set_reading_sim(int length, char buffer[]) {
LOG_DEBUG("ADC_SET_READING\n");
int param1, param2, param3;
if (length != 3) {
LOG_DEBUG("Invalid length: %d\n", length);
return;
}

sscanf(buffer, "%d, %d, %d", &param1, &param2, &param3);
if (param1 < 0 || param2 < 0 || param3 < 0 || param1 > 6 || param2 > 16) {
LOG_DEBUG("Invalid param, 1: %d, 2: %d, 3: %d\n", param1, param2, param3);
return;
}

GpioAddress ADC_SET_READING_ADDR = { .port = param1, .pin = param2 };
adc_set_reading(ADC_SET_READING_ADDR, param3);
}

void i2c_set_reading_sim(int length, char buffer[]) {
int param1, param2;
LOG_DEBUG("I2C_SET_READING\n");
if (length != 3) {
LOG_DEBUG("Invalid length: %d\n", length);
return;
}

sscanf(buffer, "%d, %d, %[^\n\t]", &param1, &param2, buffer);
if (param1 < 0 || param2 < 0 || param1 > 1) {
LOG_DEBUG("Invalid param, param1: %d, param2: %d\n", param1, param2);
return;
}

I2CPort i2c_port = param1;
i2c_set_data(i2c_port, (uint8_t *)&buffer, (size_t)param2);
}

void spi_set_rx_sim(int length, char buffer[]) {
LOG_DEBUG("SPI_SET_RX\n");
int param1;
if (length != 2) {
LOG_DEBUG("Invalid length: %d\n", length);
return;
}

sscanf(buffer, "%d, %[^\n\t]", &param1, buffer);
if (param1 < 0) {
LOG_DEBUG("Invalid param, param1: %d", param1);
return;
}

spi_set_rx((uint8_t *)&buffer, param1);
}

void sim_init(int sock_num) {
char buffer[2024];
LOG_DEBUG("Simulation thread started\n");
int res;
int operation, length;
char rcv[1];
int p;
Operations input;

while (s_keep_alive) {
res = 0;
memset(buffer, 0, sizeof(buffer));
p = 0;
LOG_DEBUG("Listening\n");
while (s_keep_alive) {
memset(rcv, 0, sizeof(rcv));
res = recv(sock_num, rcv, 1, 0);
if (res == 1) {
if (rcv[0] != '\n') {
buffer[p] = rcv[0];
p++;
} else {
break;
}
}
}
LOG_DEBUG("Message received!\n");
sscanf(buffer, "%d: %d, %[^\n\t]", &operation, &length, buffer);
if (operation < 0 || operation > 6) {
LOG_DEBUG("Invalid operation: %d\n", operation);
continue;
}

input = operation;
switch (input) {
case GPIO_SET:
gpio_set_sim(length, buffer) break;
case GPIO_TOGGLE:
gpio_toggle_sim(length, buffer);
break;
case GPIO_IT_TRIGGER:
gpio_it_trigger_sim(length, buffer);
break;
case ADC_SET_READING:
adc_set_reading_sim(length, buffer);
break;
case I2C_SET_READING:
i2c_set_reading_sim(length, buffer);
break;
case SPI_SET_RX:
spi_set_rx_sim(length, buffer);
break;
case UART:
LOG_DEBUG("UART\n");
break;
default:
LOG_DEBUG("UNRECOGNIZED OPERATION: %d\n", input);
}
usleep(1000000);
}
}

int main(int argc, char *argv[]) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be getting the port from the args, but this is fine for now

LOG_DEBUG("Operation listener thread started\n");
int socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd < 0) {
LOG_DEBUG("Socket error: %d", socketfd);
return 0;
}
LOG_DEBUG("Socket successful\n");
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(2520);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int status = bind(socketfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (status < 0) {
LOG_DEBUG("Bind failed: %d\n", status);
return 0;
}
LOG_DEBUG("Bind successful\n");
if (listen(socketfd, 5) < 0) {
LOG_DEBUG("Listen failed\n");
return 0;
}
LOG_DEBUG("Listen successful\n");
int newsockfd = accept(socketfd, NULL, NULL);
if (newsockfd < 0) {
LOG_DEBUG("Accept failed: %d \n", newsockfd);
return 0;
}
LOG_DEBUG("Accept successful\n");

sim_init(newsockfd);
close(newsockfd);
close(socketfd);
}
58 changes: 58 additions & 0 deletions projects/simulation/src/simulation_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
#include <poll.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#include "gpio.h"
#include "gpio_it.h"
#include "log.h"

#define PORT 2520

int main() {
int socketfd;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also consider putting this socket logic into a function so other users don't need to copy this

struct sockaddr_in server_addr;
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd < 0) {
LOG_DEBUG("Socket error: %d \n", socketfd);
return 0;
}
LOG_DEBUG("Socket successful\n");

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

if (connect(socketfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
LOG_DEBUG("Connect error\n");
return 0;
}
LOG_DEBUG("Connect successful\n");
const char *test1 = "0: 3, 2, 16, 0\n";
const char *test2 = "1: 2, 2, 16\n";
const char *test3 = "2: 2, 2, 16\n";
const char *test4 = "3: 3, 2, 16, 3\n";
const char *test5 = "4: 3, 1, 5, hello\n";
const char *test6 = "5: 3, 1, 5, hello\n";
const char *test7 = "6: 3, 2, 5, hello\n";
const char *test8 = "7: 3, 2, 16, 0";
send(socketfd, test1, strlen(test1), 0);
send(socketfd, test2, strlen(test2), 0);
send(socketfd, test3, strlen(test3), 0);
send(socketfd, test4, strlen(test4), 0);
send(socketfd, test5, strlen(test5), 0);
send(socketfd, test6, strlen(test6), 0);
send(socketfd, test7, strlen(test7), 0);
send(socketfd, test8, strlen(test8), 0);
close(socketfd);
return 0;
}
Loading