diff --git a/arduino/AC.c b/arduino/AC.c index 1be04a3..1a699fc 100644 --- a/arduino/AC.c +++ b/arduino/AC.c @@ -1,35 +1,37 @@ #include "AC.h" -void registerRxHandler(unsigned char code, rxHandler handler) +void registerRxHandlerAC(unsigned char code, rxHandler handler) { - rxHandlers[code] = handler; + rxHandlersAC[code] = handler; } - ISR(USART0_UDRE_vect) { // When a transmit is ready to be done again - TaskHandle_t holder = xSemaphoreGetMutexHolder(sSendAC); - if (holder != NULL) { - vTaskResume(holder); + UDR0 = *toSendAC; + toSendAC++; + toSendSizeAC--; + if (toSendSizeAC <= 0) { + UCSR0B &= ~(1 << UDRIE0); + TaskHandle_t holder = xSemaphoreGetMutexHolder(sSendAC); + if (holder != NULL) { + vTaskNotifyGiveFromISR(holder, NULL); + } } } -void sendByteAC(unsigned char data) -{ - while (!bit_is_set(UCSR0A, UDRE0)) { - vTaskSuspend(xSemaphoreGetMutexHolder(sSendAC)); - } - UDR0 = data; -} - void sendAC(unsigned char code, void* data, size_t size) { - xSemaphoreTake(sSendAC, 0); - sendByteAC(code); - unsigned char* p = data; - for (int i = 0; i < size; i++) { - sendByteAC(*p++); + xSemaphoreTake(sSendAC, portMAX_DELAY); + toSendAC = &code; + toSendSizeAC = sizeof(code); + UCSR0B |= (1 << UDRIE0); + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); + if (size > 0) { + toSendAC = data; + toSendSizeAC = size; + UCSR0B |= (1 << UDRIE0); + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); } xSemaphoreGive(sSendAC); } @@ -37,15 +39,16 @@ void sendAC(unsigned char code, void* data, size_t size) ISR(USART0_RX_vect) { // When a character is received - vTaskResume(tReaderAC); + vTaskNotifyGiveFromISR(tReaderAC, NULL); } unsigned char readByteAC() { while (!bit_is_set(UCSR0A, RXC0)) { - vTaskSuspend(tReaderAC); + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); } - return UDR0; + unsigned char c = UDR0; + return c; } void readAC(void* data, size_t size) @@ -64,16 +67,21 @@ void TaskReaderAC(void* pvParameters) for (;;) { code = readByteAC(); - rxHandler handler = rxHandlers[code]; + rxHandler handler = rxHandlersAC[code]; if (handler != NULL) { handler(); } else { - struct A2CI_ERRs err = { ERR_UNKNOWN_CODE }; + struct A2CD_ERRs err = { ERR_UNKNOWN_CODE }; sendAC(A2CD_ERR, &err, sizeof(err)); } } } +void onC2AD_PING() +{ + sendAC(C2AD_PING, NULL, 0); +} + void configureAC() { /* Set baud rate */ @@ -83,14 +91,16 @@ void configureAC() UCSR0A &= ~(1 << U2X0); /* Enable transmitter & receiver with interrupts */ - UCSR0B = (1 << RXCIE0 | 1 << UDRIE0 | 1 << TXEN0 | 1 << RXEN0); + UCSR0B = (1 << RXCIE0 | 1 << TXEN0 | 1 << RXEN0); /* Set 8 bits character and 1 stop bit */ UCSR0C = (1 << UCSZ01 | 1 << UCSZ00); for (int i = 0; i < 256; i++) { - rxHandlers[i] = NULL; + rxHandlersAC[i] = NULL; } sSendAC = xSemaphoreCreateMutex(); xTaskCreate(TaskReaderAC, "TaskReaderAC", 128, NULL, 2, &tReaderAC); + + registerRxHandlerAC(C2AD_PING, onC2AD_PING); } diff --git a/arduino/AC.h b/arduino/AC.h index 9792485..aeffa7e 100644 --- a/arduino/AC.h +++ b/arduino/AC.h @@ -2,8 +2,8 @@ * Définition des fonctions utilisées pour échager entre l'Arduino et le chef */ -#ifndef __SERIAL_H_ -#define __SERIAL_H_ +#ifndef __AC_H_ +#define __AC_H_ #include #include @@ -19,16 +19,17 @@ TaskHandle_t tReaderAC; SemaphoreHandle_t sSendAC; +unsigned char* toSendAC; +size_t toSendSizeAC; typedef void (*rxHandler)(void); -rxHandler rxHandlers[256]; +rxHandler rxHandlersAC[256]; -void registerRxHandler(unsigned char code, rxHandler handler); -void sendByteAC(unsigned char data); +void registerRxHandlerAC(unsigned char code, rxHandler handler); // À utiliser après configureAC(); void sendAC(unsigned char code, void* data, size_t size); unsigned char readByteAC(); // À utiliser uniquement depuis un rxHandler void readAC(void* data, size_t size); // À utiliser uniquement depuis un rxHandler -void TaskReaderAC(void* pvParameters); +void TaskReaderAC(void* pvParameters); // Privé void configureAC(); #endif diff --git a/arduino/ACsignals.h b/arduino/ACsignals.h index c8dfd43..2e4b35c 100644 --- a/arduino/ACsignals.h +++ b/arduino/ACsignals.h @@ -8,7 +8,7 @@ #define AC_BAUDRATE 9600UL // Structures used everywhere -struct position { +struct __attribute__ ((packed)) position { float x; float y; float o; @@ -30,13 +30,9 @@ struct position { // Pour le debug #define C2AD_PING 'P' -struct C2AD_PINGs { -}; // Arrête tous les actionneurs #define C2AD_STOP 'S' -struct C2ADD_STOPs { -}; // Donne une destination #define C2AD_GOTO 'G' @@ -47,15 +43,16 @@ struct C2ADD_STOPs { // Erreur quelconque #define A2CD_ERR 'E' -struct A2CI_ERRs { +struct __attribute__ ((packed)) A2CD_ERRs { unsigned char code; }; #define ERR_UNKNOWN_CODE 'C' +#define ERR_UNKNOWN_CODE_FPGA 'c' // Envoie les infos de debug #define A2CI_DBG 'D' -struct A2CI_DBGs { +struct __attribute__ ((packed)) A2CI_DBGs { struct position actuel; struct position destination; unsigned char movement; diff --git a/arduino/AF.c b/arduino/AF.c new file mode 100644 index 0000000..fff99f1 --- /dev/null +++ b/arduino/AF.c @@ -0,0 +1,99 @@ +#include "AF.h" +#include "AC.h" + +void registerRxHandlerAF(unsigned char code, rxHandler handler) +{ + rxHandlersAF[code] = handler; +} + +ISR(USART1_UDRE_vect) +{ + // When a transmit is ready to be done again + UDR1 = *toSendAF; + toSendAF++; + toSendSizeAF--; + if (toSendSizeAF <= 0) { + UCSR1B &= ~(1 << UDRIE0); + TaskHandle_t holder = xSemaphoreGetMutexHolder(sSendAF); + if (holder != NULL) { + vTaskNotifyGiveFromISR(holder, NULL); + } + } +} + +void sendAF(unsigned char code, void* data, size_t size) +{ + xSemaphoreTake(sSendAF, portMAX_DELAY); + toSendAF = &code; + toSendSizeAF = sizeof(code); + UCSR1B |= (1 << UDRIE0); + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); + if (size > 0) { + toSendAF = data; + toSendSizeAF = size; + UCSR1B |= (1 << UDRIE0); + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); + } + xSemaphoreGive(sSendAF); +} + +ISR(USART1_RX_vect) +{ + // When a character is received + vTaskNotifyGiveFromISR(tReaderAF, NULL); +} + +unsigned char readByteAF() +{ + while (!bit_is_set(UCSR1A, RXC1)) { + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); + } + return UDR1; +} + +void readAF(void* data, size_t size) +{ + unsigned char* p = data; + for (int i = 0; i < size; i++) { + *p = readByteAF(); + p++; + } +} + +void TaskReaderAF(void* pvParameters) +{ + (void)pvParameters; + unsigned char code; + for (;;) { + code = readByteAF(); + + rxHandler handler = rxHandlersAF[code]; + if (handler != NULL) { + handler(); + } else { + struct A2CD_ERRs err = { ERR_UNKNOWN_CODE_FPGA }; + sendAC(A2CD_ERR, &err, sizeof(err)); + } + } +} + +void configureAF() +{ + /* Set baud rate */ + UBRR1 = AF_PRESCALER; + + /* Set off UART baud doubler */ + UCSR1A &= ~(1 << U2X1); + + /* Enable transmitter & receiver with interrupts */ + UCSR1B = (1 << RXCIE1 | 1 << TXEN1 | 1 << RXEN1); + + /* Set 8 bits character and 1 stop bit */ + UCSR1C = (1 << UCSZ11 | 1 << UCSZ10); + + for (int i = 0; i < 256; i++) { + rxHandlersAF[i] = NULL; + } + sSendAF = xSemaphoreCreateMutex(); + xTaskCreate(TaskReaderAF, "TaskReaderAF", 128, NULL, 2, &tReaderAF); +} diff --git a/arduino/AF.h b/arduino/AF.h new file mode 100644 index 0000000..2f711fb --- /dev/null +++ b/arduino/AF.h @@ -0,0 +1,35 @@ +/* + * Définition des fonctions utilisées pour échager entre l'Arduino et le chef + */ + +#ifndef __AF_H_ +#define __AF_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "AFsignals.h" + +#define CPU_FREQ 16000000UL +#define AF_PRESCALER CPU_FREQ / (AF_BAUDRATE << 4) - 1 + +TaskHandle_t tReaderAF; +SemaphoreHandle_t sSendAF; +unsigned char* toSendAF; +size_t toSendSizeAF; + +typedef void (*rxHandler)(void); +rxHandler rxHandlersAF[256]; + +void registerRxHandlerAF(unsigned char code, rxHandler handler); // À utiliser après configureAF(); +void sendAF(unsigned char code, void* data, size_t size); +unsigned char readByteAF(); // À utiliser uniquement depuis un rxHandler +void readAF(void* data, size_t size); // À utiliser uniquement depuis un rxHandler +void TaskReaderAF(void* pvParameters); // Privé +void configureAF(); + +#endif diff --git a/arduino/AFsignals.h b/arduino/AFsignals.h new file mode 100644 index 0000000..a808fc8 --- /dev/null +++ b/arduino/AFsignals.h @@ -0,0 +1,67 @@ +/* + * Définition des signaux échagés entre l'Arduino et le chef + */ + +#ifndef __AFSIGNALS_H_ +#define __AFSIGNALS_H_ + +#include + +#define AF_BAUDRATE 9600UL + +// Structures used everywhere + +// D: Direct +// Sens naturel : Envoi de donnée +// Sens inverse : Accusé de réception + +// I: Indirect +// Sens inverse : Demande de donnée +// Sens naturel : Envoi de donnée + +// T: Trigger +// Sens inverse : Paramètrage du trigger +// Sens naturel : Envoi de trigger + +// Arduino → FPGA + +// Pour le debug +#define A2FD_PING 'P' + +// Réinitialise la valeur des codeuses +#define A2FD_RESETCODER 'R' + +// FPGA → Arduino + +// Erreur quelconque +#define F2AD_ERR 'E' +struct __attribute__ ((packed)) F2AD_ERRs { + unsigned char code; +}; + +#define ERR_UNKNOWN_CODE 'C' + +// Récupère les valeur des encodeurs +#define F2AI_CODER 'D' +struct __attribute__ ((packed)) F2AI_CODERs { + int16_t left; + int16_t right; +}; + +// Récupère les valeur des capteurs de distance +#define F2AI_CAPT 'C' +struct __attribute__ ((packed)) F2AI_CAPTs { + uint16_t front; + uint16_t back; +}; + +// Récupère les valeur des capteurs de distance (trigger au supérieur) +#define F2AT_CAPT 'c' +// /!\ Structure de la requête de trigger (A→F). Les données seront envoyées avec F2AI_CAPT +struct __attribute__ ((packed)) F2AT_CAPTs { + uint16_t front; + uint16_t back; +}; + + +#endif diff --git a/arduino/FreeRTOSConfig.h b/arduino/FreeRTOSConfig.h index 89c586a..a925dd0 100644 --- a/arduino/FreeRTOSConfig.h +++ b/arduino/FreeRTOSConfig.h @@ -85,13 +85,6 @@ #define INCLUDE_xQueueGetMutexHolder 1 // -- done -// JF: added -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY 3 -#define configTIMER_QUEUE_LENGTH 10 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE -// -- done - #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 diff --git a/arduino/Makefile b/arduino/Makefile index e89302f..92f6c2f 100644 --- a/arduino/Makefile +++ b/arduino/Makefile @@ -29,7 +29,7 @@ FORMAT = ihex # Target file name (without extension). TARGET = principal -OBJS = AC position movement debug +OBJS = AC AF position movement debug # Custom NAME = $(TARGET).c @@ -78,7 +78,7 @@ LDFLAGS = -Wl,-Map=$(TARGET).map,--cref # Type: avrdude -c ? # to get a full listing. # -AVRDUDE_PROGRAMMER = stk500 +AVRDUDE_PROGRAMMER = wiring AVRDUDE_PORT = /dev/ttyACM0 # programmer connected to serial device diff --git a/arduino/debug.c b/arduino/debug.c index aa70c53..af9650b 100644 --- a/arduino/debug.c +++ b/arduino/debug.c @@ -8,7 +8,7 @@ void TaskDebug(void *pvParameters) { (void) pvParameters; for (;;) { - vTaskSuspend(tDebug); + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); // Copie des valeurs à envoyer en debug memcpy((void*) &debug.actuel, (const void*) &actuel, (unsigned long) sizeof(actuel)); @@ -21,12 +21,12 @@ void TaskDebug(void *pvParameters) { } void onA2CI_DBG() { - vTaskResume(tDebug); + vTaskNotifyGiveFromISR(tDebug, NULL); } void configureDebug() { - registerRxHandler(A2CI_DBG, onA2CI_DBG); + registerRxHandlerAC(A2CI_DBG, onA2CI_DBG); xTaskCreate(TaskDebug, "Debug", 128, NULL, 10, &tDebug);; } diff --git a/arduino/movement.c b/arduino/movement.c index e8b6534..ddddded 100644 --- a/arduino/movement.c +++ b/arduino/movement.c @@ -1,4 +1,5 @@ #include "movement.h" +#include "position.h" #include "AC.h" void TaskMovement(void *pvParameters) { @@ -6,19 +7,25 @@ void TaskMovement(void *pvParameters) { TickType_t xLastWakeTime; TickType_t xFrequency = 100 / portTICK_PERIOD_MS; - vTaskSuspend(tMovement); // Mettre en veille jusqu'à l'arrivée de la prochaine instruction + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); // Mettre en veille jusqu'à l'arrivée de la prochaine instruction xLastWakeTime = xTaskGetTickCount(); for (;;) { // TODO Ici ira le code qui changera les valeurs des moteurs vTaskDelayUntil(&xLastWakeTime, 1000 / portTICK_PERIOD_MS); + if (movement == C2AD_GOTO) { + actuel.x = destination.x; + actuel.y = destination.y; + actuel.o = destination.o; + } + if (true) { // Arrivé à destination sendAC(movement, NULL, 0); // On rapporte au chef qu'on a terminé l'action en cours - // Mettre en brake + // TODO Mettre en brake + movement = C2AD_STOP; - // Envoi du message de bonne réception - vTaskSuspend(tMovement); // Mettre en veille jusqu'à l'arrivée de la prochaine instruction + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); // Mettre en veille jusqu'à l'arrivée de la prochaine instruction xLastWakeTime = xTaskGetTickCount(); } else { vTaskDelayUntil(&xLastWakeTime, xFrequency); @@ -28,13 +35,13 @@ void TaskMovement(void *pvParameters) { void onC2AD_STOP() { movement = C2AD_STOP; - vTaskResume(tMovement); + vTaskNotifyGiveFromISR(tMovement, NULL); } void onC2AD_GOTO() { movement = C2AD_GOTO; readAC(&destination, sizeof(struct C2AD_GOTOs)); - vTaskResume(tMovement); + vTaskNotifyGiveFromISR(tMovement, NULL); } @@ -43,8 +50,8 @@ void configureMovement() { movement = C2AD_STOP; - registerRxHandler(C2AD_STOP, onC2AD_STOP); - registerRxHandler(C2AD_GOTO, onC2AD_GOTO); + registerRxHandlerAC(C2AD_STOP, onC2AD_STOP); + registerRxHandlerAC(C2AD_GOTO, onC2AD_GOTO); xTaskCreate(TaskMovement, "Movement", 128, NULL, 2, &tMovement);; } diff --git a/arduino/position.c b/arduino/position.c index a67b83b..8809e3a 100644 --- a/arduino/position.c +++ b/arduino/position.c @@ -6,7 +6,7 @@ void TaskPosition(void *pvParameters) { TickType_t xLastWakeTime; TickType_t xFrequency = 100 / portTICK_PERIOD_MS; - vTaskSuspend(tPosition); // TODO Dummy + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); // TODO Dummy xLastWakeTime = xTaskGetTickCount(); for (;;) { vTaskDelayUntil(&xLastWakeTime, xFrequency); @@ -16,6 +16,10 @@ void TaskPosition(void *pvParameters) { void configurePosition() { + actuel.x = 0; + actuel.y = 0; + actuel.o = 90; + xTaskCreate(TaskPosition, "Position", 128, NULL, 2, &tPosition);; } diff --git a/arduino/principal.c b/arduino/principal.c index 88b55dc..c55785f 100644 --- a/arduino/principal.c +++ b/arduino/principal.c @@ -4,16 +4,15 @@ #include #include "AC.h" +#include "AF.h" #include "position.h" #include "movement.h" #include "debug.h" -unsigned char speed = 200; - void TaskBlink(void *pvParameters) { (void) pvParameters; TickType_t xLastWakeTime; - TickType_t xFrequency = speed / portTICK_PERIOD_MS; + TickType_t xFrequency = 200 / portTICK_PERIOD_MS; DDRB = 0xFF; @@ -26,6 +25,7 @@ void TaskBlink(void *pvParameters) { int main(void) { configureAC(); // Doit rester en premier :) + configureAF(); // Doit rester en premier :) configureMovement(); configurePosition(); configureDebug(); diff --git a/chef/Makefile b/chef/Makefile index 2042105..12c05e2 100644 --- a/chef/Makefile +++ b/chef/Makefile @@ -5,7 +5,7 @@ CC=gcc # Bibliothèques LIBS= ## Drapeaux pour le linker -LDFLAGS= +LDFLAGS=-lpthread ## Drapeaux pour le compilateur CFLAGS= ## Générateurs de drapeaux pour les bibliothèques @@ -37,7 +37,7 @@ endif default: bin/testpin bin/premier # Binaires (dont il faut spécifier les objets explicitement) -bin/premier: obj/common.o obj/serial.o +bin/premier: obj/CA.o obj/debug.o obj/movement.o bin/testPin: obj/testPin.o $(CC) $(LDFLAGS) $^ -lwiringPi -o $@ diff --git a/chef/src/CA.c b/chef/src/CA.c new file mode 100644 index 0000000..1fe0759 --- /dev/null +++ b/chef/src/CA.c @@ -0,0 +1,178 @@ +#include "CA.h" +#include // O_* +#include // printf... +#include // stuff +#include // memcpy +#include // bzero +#include // read(), write()... + +void printData(void* data, size_t size) +{ + printf(" "); + unsigned char* p = data; + for (size_t i = 0; i < size; i++) { + if (*p >= ' ' && *p <= '~') { + printf(" %c", *p); + } else { + printf(" %02x", *p); + } + p++; + } + printf("\n"); +} + +void configureArduino() +{ + // Connection au port série + printf("Connexion à %s... ", ARDUINO_PORTNAME); + arduino = open(ARDUINO_PORTNAME, O_RDWR | O_NOCTTY | O_NDELAY); + if (arduino < 0) { + printf("Échec !\n"); + exit(1); + } + + // Configuration du port série + struct termios cfg; + bzero(&cfg, sizeof(cfg)); + cfg.c_cflag = CLOCAL | CREAD | CA_BAUDRATE | CS8; + cfg.c_iflag = 0; + cfg.c_oflag = 0; + cfg.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */ + cfg.c_cc[VTIME] = 0; /* inter-character timer unused */ + cfg.c_cc[VMIN] = 1; /* blocking read until 1 char received */ + if (tcsetattr(arduino, TCSANOW, &cfg) < 0) { + perror("serialConfig.tcsetattr"); + exit(1); + } + + sleep(1); + + // Flush + unsigned char trash[1024]; + read(arduino, &trash, sizeof(trash)); + + printf("OK!\n"); +} + +void deconfigureArduino() +{ + close(arduino); + printf("Déconnecté\n"); +} + +void registerRxHandler(unsigned char code, rxHandler handler) +{ + rxHandlersAC[code] = handler; +} + +void* TaskReaderAC(void* pdata) +{ + (void)pdata; + unsigned char code; + for (;;) { + code = readByteCA(); + +#ifdef PRINTRAWDATA + printf("↓"); + printData(&code, sizeof(code)); +#endif + rxHandler handler = rxHandlersAC[code]; + if (handler != NULL) { + handler(); + } else { + printf("Code inconnu: %x (%c)\n", code, code); + } + } + return NULL; +} + +void onA2CD_ERR() +{ + struct A2CD_ERRs s; + readCA(&s, sizeof(struct A2CD_ERRs)); + printf("Erreur reçue : %c (%2x)\n", s.code, s.code); +} + +void configureCA() +{ + configureArduino(); + for (int i = 0; i < 256; i++) { + rxHandlersAC[i] = NULL; + } + + pthread_mutex_init(&sSendCA, NULL); + pthread_create(&tReaderAC, NULL, TaskReaderAC, NULL); + registerRxHandler(A2CD_ERR, onA2CD_ERR); +} + +void deconfigureCA() +{ + deconfigureArduino(); +} + +void sendByteCA(unsigned char data) +{ + write(arduino, &data, sizeof(data)); + +#ifdef PRINTRAWDATA + printf("↑"); + printData(&data, sizeof(data)); +#endif +} + +void sendCA(unsigned char code, void* data, size_t size) +{ + pthread_mutex_lock(&sSendCA); + + sendByteCA(code); + if (size > 0) { + unsigned char* p = data; + for (size_t i = 0; i < size; i++) { + write(arduino, p, sizeof(unsigned char)); + p++; + } + // Envoyer plus d'un octet d'un coup curieusement il aime pas ça du tout + } + pthread_mutex_unlock(&sSendCA); + +#ifdef PRINTRAWDATA + if (size > 0) { + printf("↑"); + printData(data, size); + } +#endif +} + +unsigned char readByteCA() +{ + unsigned char c; + + while (read(arduino, &c, sizeof(c)) < 1) { + sleep(0); + } + return c; + +#ifdef PRINTRAWDATA + printf("↓"); + printData(&c, sizeof(c)); +#endif +} + +void readCA(void* data, size_t size) +{ + size_t remaining = size; + int justRead; + char* p = data; + do { + justRead = read(arduino, p, remaining); + if (justRead > 0) { + p += justRead; + remaining -= justRead; + } + } while (remaining > 0); + +#ifdef PRINTRAWDATA + printf("↓"); + printData(data, size); +#endif +} diff --git a/chef/src/CA.h b/chef/src/CA.h new file mode 100644 index 0000000..e7e380d --- /dev/null +++ b/chef/src/CA.h @@ -0,0 +1,29 @@ +#ifndef __AC_H_ +#define __AC_H_ + +#include +#include +#include // baudrates + +#include "ACsignals.h" + +#define ARDUINO_PORTNAME "/dev/ttyACM0" +#define CA_BAUDRATE B9600 +// #define PRINTRAWDATA + +int arduino; +pthread_mutex_t sSendCA; +pthread_t tReaderAC; + +typedef void (*rxHandler)(void); +rxHandler rxHandlersAC[256]; + +void registerRxHandler(unsigned char code, rxHandler handler); // À utiliser après configureCA(); +void sendByteCA(unsigned char data); // Privé +void sendCA(unsigned char code, void* data, size_t size); +unsigned char readByteCA(); // À utiliser uniquement depuis un rxHandler +void readCA(void* data, size_t size); // À utiliser uniquement depuis un rxHandler +void configureCA(); +void deconfigureCA(); + +#endif diff --git a/chef/src/common.c b/chef/src/common.c deleted file mode 100644 index 67c02a2..0000000 --- a/chef/src/common.c +++ /dev/null @@ -1 +0,0 @@ -#include "common.h" diff --git a/chef/src/common.h b/chef/src/common.h deleted file mode 100644 index 72bccea..0000000 --- a/chef/src/common.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __COMMON_H_ -#define __COMMON_H_ - -#include -#include - -#define SIGNAL_AVANCER 42 - -#endif - diff --git a/chef/src/debug.c b/chef/src/debug.c new file mode 100644 index 0000000..ff2b532 --- /dev/null +++ b/chef/src/debug.c @@ -0,0 +1,52 @@ +#include "debug.h" +#include +#include // sleep + +void* TaskDebug(void* pdata) +{ + (void)pdata; + struct timespec tim; + /* tim.tv_sec = 0; */ + /* tim.tv_nsec = 100000000L; */ + tim.tv_sec = 1; + tim.tv_nsec = 0; + + for (;;) { + nanosleep(&tim, NULL); + sendCA(A2CI_DBG, NULL, 0); + } + + return NULL; +} + +void printDebugInfos(struct A2CI_DBGs* debug) +{ + printf("← Position actuelle (%f; %f) (%f°)", debug->actuel.x, debug->actuel.y, debug->actuel.o); + printf(", destination : "); + if (debug->movement == C2AD_STOP) { + printf("aucune\n"); + } else { + printf("(%f; %f) (%f°)\n", debug->destination.x, debug->destination.y, debug->destination.o); + } +} + +void onA2CI_DBG() +{ + readCA(&debug, sizeof(struct A2CI_DBGs)); + printDebugInfos(&debug); +} + +void configureDebug() +{ + registerRxHandler(A2CI_DBG, onA2CI_DBG); +#ifdef REGULARREPORTS + pthread_create(&tDebug, NULL, TaskDebug, NULL); +#endif +} + +void deconfigureDebug() +{ +#ifdef REGULARREPORTS + pthread_cancel(tDebug); +#endif +} diff --git a/chef/src/debug.h b/chef/src/debug.h new file mode 100644 index 0000000..aac10a7 --- /dev/null +++ b/chef/src/debug.h @@ -0,0 +1,16 @@ +#ifndef __DEBUG_H_ +#define __DEBUG_H_ + +#include +#include "CA.h" +#define REGULARREPORTS + +struct A2CI_DBGs debug; +pthread_t tDebug; + +void* TaskDebug(void *pdata); +void onA2CI_DBG(); +void configureDebug(); +void deconfigureDebug(); + +#endif diff --git a/chef/src/movement.c b/chef/src/movement.c new file mode 100644 index 0000000..f9bd0a7 --- /dev/null +++ b/chef/src/movement.c @@ -0,0 +1,55 @@ +#include "movement.h" +#include "CA.h" +#include +#include +#include + +void onC2AD_STOP() +{ + // On considère que l'arrêt se fait très rapidement pour ne pas + // avoir à attendre le signal de retour de C2AD_STOP +} + +void stop() +{ + printf("→ Arrêt\n"); + sendCA(C2AD_STOP, NULL, 0); + registerRxHandler(C2AD_STOP, onC2AD_STOP); +} + +// Inspiré de https://stackoverflow.com/a/1760819 +pthread_mutex_t reponseMutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t reponseCond = PTHREAD_COND_INITIALIZER; +bool attenteReponse = false; + +void onC2AD_GOTO() +{ + pthread_mutex_lock(&reponseMutex); + attenteReponse = false; + pthread_cond_signal(&reponseCond); + pthread_mutex_unlock(&reponseMutex); +} + +void aller(struct position* pos) +{ + printf("→ Déplacement vers (%f; %f) (%f°)\n", pos->x, pos->y, pos->o); + + if (attenteReponse) { + printf("Déjà en déplacement !\n"); + exit(EXIT_FAILURE); + } + attenteReponse = true; + + registerRxHandler(C2AD_GOTO, onC2AD_GOTO); + sendCA(C2AD_GOTO, (struct C2AD_GOTOs*)pos, sizeof(struct C2AD_GOTOs)); + + pthread_mutex_lock(&reponseMutex); + while (attenteReponse) { + pthread_cond_wait(&reponseCond, &reponseMutex); + } + pthread_mutex_unlock(&reponseMutex); + + registerRxHandler(C2AD_GOTO, NULL); + + printf("← Arrivé à destination\n"); +} diff --git a/chef/src/movement.h b/chef/src/movement.h new file mode 100644 index 0000000..5f568e4 --- /dev/null +++ b/chef/src/movement.h @@ -0,0 +1,9 @@ +#ifndef __MOVEMENT_H_ +#define __MOVEMENT_H_ + +#include "CA.h" + +void stop(); +void aller(struct position* pos); + +#endif diff --git a/chef/src/premier.c b/chef/src/premier.c index e7d0f03..014546d 100644 --- a/chef/src/premier.c +++ b/chef/src/premier.c @@ -1,15 +1,59 @@ -#include "premier.h" +#include +#include +#include // random seed +#include +#include // sleep -#include "serial.h" +#include "CA.h" +#include "movement.h" +#include "debug.h" + +#define TEMPSMAX 10 + +void* TaskParcours(void *pdata) +{ + (void) pdata; + + struct position pos; + for (;;) { + pos.x = (int) (rand()*200.0/RAND_MAX); + pos.y = (int) (rand()*100.0/RAND_MAX); + pos.o = (int) (rand()*360.0/RAND_MAX); + aller(&pos); + sleep(1); + stop(); + sleep(2); + } + + printf("Fin du parcours\n"); + return NULL; +} int main() { - unsigned char g; + + printf("Démarrage...\n"); configureCA(); - sendByteCA('c'); - while ((g = readByteCA())) { - printf("%c\n", g); - } + configureDebug(); + srand(time(NULL)); + + /* printf("Synchronisation avec le Raspberry Pi\n"); // TODO */ + + /* printf("En attente de la tirette...\n"); // TODO */ + printf("C'est parti !\n"); + + pthread_t tParcours; + pthread_create(&tParcours, NULL, TaskParcours, NULL); + + sleep(TEMPSMAX); + + printf("Fin des %d secondes\n", TEMPSMAX); + /* pthread_cancel(tParcours); */ + + + /* stop(); */ + /* */ + deconfigureDebug(); deconfigureCA(); - return 0; + return EXIT_SUCCESS; } diff --git a/chef/src/premier.h b/chef/src/premier.h deleted file mode 100644 index 01ffa10..0000000 --- a/chef/src/premier.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __PREMIER_H_ - -#include "common.h" - -#endif diff --git a/chef/src/serial.c b/chef/src/serial.c deleted file mode 100644 index 2c75b46..0000000 --- a/chef/src/serial.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "serial.h" -#include // printf... -#include // stuff -#include // read(), write()... -#include // O_* -#include // bzero - -#include "common.h" - -void configureCA() -{ - // Connection au port série - printf("Connexion à %s... ", ARDUINO_PORTNAME); - arduino = open(ARDUINO_PORTNAME, O_RDWR | O_NOCTTY | O_NDELAY); - if (arduino < 0) { - printf("Échec !\n"); - exit(1); - } - - // Configuration du port série - struct termios cfg; - bzero(&cfg, sizeof(cfg)); - cfg.c_cflag = CLOCAL | CREAD | CA_BAUDRATE | CS8; - cfg.c_iflag = 0; - cfg.c_oflag = 0; - cfg.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */ - cfg.c_cc[VTIME] = 0; /* inter-character timer unused */ - cfg.c_cc[VMIN] = 1; /* blocking read until 1 char received */ - if (tcsetattr(arduino, TCSANOW, &cfg) < 0) { - perror("serialConfig.tcsetattr"); - exit(1); - } - - sleep(1); - - printf("OK!\n"); -} - -void deconfigureCA() { - close(arduino); -} - -void sendByteCA(unsigned char data) { - write(arduino, &data, sizeof(data)); -} - -void sendCA(unsigned char code, void* data, size_t size) -{ - sendByteCA(code); - write(arduino, data, size); -} - -unsigned char readByteCA() { - unsigned char c; - while (read(arduino, &c, sizeof(c)) < 1) { - } - return c; -} diff --git a/chef/src/serial.h b/chef/src/serial.h deleted file mode 100644 index a021964..0000000 --- a/chef/src/serial.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __SERIAL_H_ -#define __SERIAL_H_ - -#include -#include // baudrates - -#include "ACsignals.h" - -#define ARDUINO_PORTNAME "/dev/ttyACM0" -#define CA_BAUDRATE B9600 - -int arduino; - -void configureCA(); -void deconfigureCA(); -void sendByteCA(unsigned char data); -unsigned char readByteCA(); - -#endif