diff --git a/Code Telecommande/CMakeLists.txt b/Code Telecommande/CMakeLists.txt index 4d5b3ae..29d3f72 100644 --- a/Code Telecommande/CMakeLists.txt +++ b/Code Telecommande/CMakeLists.txt @@ -18,6 +18,8 @@ pico_sdk_init() add_executable(controller src/main.c + src/controller.c + src/inputs.c src/wifi_operator.c src/udp_server.c ) diff --git a/Code Telecommande/src/controller.c b/Code Telecommande/src/controller.c new file mode 100644 index 0000000..9d160e2 --- /dev/null +++ b/Code Telecommande/src/controller.c @@ -0,0 +1,73 @@ +#include "include/controller.h" + +#include +#include +#include +#include "include/wifi_operator.h" +#include "include/udp_server.h" + +auto_init_mutex(wifi_mutex); + +int controller_init(void) +{ + stdio_init_all(); + + sleep_ms(1000); + + inputs_init(); + + if(cyw43_arch_init()) + { + return -1; + } + + mutex_enter_blocking(&wifi_mutex); + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1); + mutex_exit(&wifi_mutex); + + wifi_operator_init_ap_mode(); + udp_server_init(); + + controller.is_running = true; +} + +static inline void update_time(void) +{ + static bool led_state = false; + static double last_time = 0.0; + double start_time = (double)clock() * 1000.0 / (double)CLOCKS_PER_SEC; + controller.delta_time_ms = start_time - last_time; + last_time = start_time; + + static double elapsed_time = 0.0; + elapsed_time += controller.delta_time_ms; + + if(elapsed_time >= 1000) + { + elapsed_time = 0; + + mutex_enter_blocking(&wifi_mutex); + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led_state); + mutex_exit(&wifi_mutex); + + led_state = !led_state; + } +} + +void controller_handle_inputs_outputs(void) +{ + update_time(); + + get_inputs(); + + mutex_enter_blocking(&wifi_mutex); + udp_server_send(); + mutex_exit(&wifi_mutex); + + tight_loop_contents(); +} + +void controller_deinit(void) +{ + udp_server_exit(); +} diff --git a/Code Telecommande/src/include/controller.h b/Code Telecommande/src/include/controller.h new file mode 100644 index 0000000..360f32e --- /dev/null +++ b/Code Telecommande/src/include/controller.h @@ -0,0 +1,23 @@ +#ifndef CONTROLLER_H +#define CONTROLLER_H + +#include +#include "inputs.h" + +typedef struct controller_t { + inputs_buffer_t inputs_buffer; + + double delta_time_ms; + bool is_running; +} controller_t; + +extern controller_t controller; + +// Init all controller's components +int controller_init(void); +// Handle all inputs and outputs +void controller_handle_inputs_outputs(void); +// Deinit controller's components +void controller_deinit(void); + +#endif // CONTROLLER_H \ No newline at end of file diff --git a/Code Telecommande/src/include/inputs.h b/Code Telecommande/src/include/inputs.h new file mode 100644 index 0000000..33df35d --- /dev/null +++ b/Code Telecommande/src/include/inputs.h @@ -0,0 +1,40 @@ +#ifndef INPUTS_H +#define INPUTS_H + +#include + +typedef enum buttons_t { + BUTTON_L, + BUTTON_R, + BUTTON_BLACK, + BUTTON_BLUE, + BUTTON_WHITE, + BUTTON_GREEN, + + NB_BUTTONS +} buttons_t; + +typedef struct button_def_t { + uint pin; +} button_def_t; + +extern const button_def_t BUTTONS_DEFS[]; + +#define JOYSTICK_X_AXIS_PIN 26 +#define JOYSTICK_Y_AXIS_PIN 27 + +#define JOYSTICK_X_AXIS_ADC_INPUT 0 +#define JOYSTICK_Y_AXIS_ADC_INPUT 1 + +typedef struct inputs_buffer_t { + int8_t x_axis_speed; + int8_t y_axis_speed; + bool buttons_states[NB_BUTTONS]; +} inputs_buffer_t; + + +void inputs_init(void); + +void get_inputs(void); + +#endif // INPUTS_H \ No newline at end of file diff --git a/Code Telecommande/src/include/lwipopts.h b/Code Telecommande/src/include/lwipopts.h new file mode 100644 index 0000000..91c3b05 --- /dev/null +++ b/Code Telecommande/src/include/lwipopts.h @@ -0,0 +1,97 @@ +#ifndef _LWIPOPTS_EXAMPLE_COMMONH_H +#define _LWIPOPTS_EXAMPLE_COMMONH_H + + +// Common settings used in most of the pico_w examples +// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) + +// allow override in some examples +#ifndef NO_SYS +#define NO_SYS 1 +#endif +// allow override in some examples +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 0 +#endif +#if PICO_CYW43_ARCH_POLL +#define MEM_LIBC_MALLOC 1 +#else +// MEM_LIBC_MALLOC is incompatible with non polling versions +#define MEM_LIBC_MALLOC 0 +#endif +#define MEM_ALIGNMENT 4 +#ifndef MEM_SIZE +#define MEM_SIZE 32768 // Augmenté pour plus de mémoire disponible +#endif +#define MEMP_NUM_TCP_SEG 32 +#define MEMP_NUM_ARP_QUEUE 10 +#define PBUF_POOL_SIZE 32 // Augmenté pour réduire les allocations +#define LWIP_ARP 1 +#define LWIP_ETHERNET 1 +#define LWIP_ICMP 1 +#define LWIP_RAW 1 +#define TCP_WND (16 * TCP_MSS) // Augmenté pour de meilleures performances +#define TCP_MSS 1460 +#define TCP_SND_BUF (8 * TCP_MSS) // Augmenté pour de meilleures performances +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS)) +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_NETIF_HOSTNAME 1 +#define LWIP_NETCONN 0 +#define MEM_STATS 0 +#define SYS_STATS 0 +#define MEMP_STATS 0 +#define LINK_STATS 0 +// #define ETH_PAD_SIZE 2 +#define LWIP_CHKSUM_ALGORITHM 3 +#define LWIP_DHCP 0 +#define LWIP_DHCP_SERVER 0 +#define LWIP_IPV4 1 +#define LWIP_TCP 1 +#define LWIP_UDP 1 +#define LWIP_DNS 1 +#define LWIP_TCP_KEEPALIVE 1 +#define LWIP_NETIF_TX_SINGLE_PBUF 1 +#define DHCP_DOES_ARP_CHECK 0 +#define LWIP_DHCP_DOES_ACD_CHECK 0 + +#ifndef NDEBUG +#define LWIP_DEBUG 1 +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 1 +#endif + +#define ETHARP_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define PPP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF + +#define SYS_LIGHTWEIGHT_PROT 1 // Protection pour le multicore +#define MEMP_NUM_PBUF 32 // Augmenté pour les buffers +#define ICMP_TTL 255 // Augmenté pour la fiabilité + +#endif /* __LWIPOPTS_H__ */ \ No newline at end of file diff --git a/Code Telecommande/src/include/udp_server.h b/Code Telecommande/src/include/udp_server.h new file mode 100644 index 0000000..921259d --- /dev/null +++ b/Code Telecommande/src/include/udp_server.h @@ -0,0 +1,29 @@ +#ifndef UDP_SERVER_H +#define UDP_SERVER_H + +#include +#include + +#define UDP_SERVER_PORT 4242 + +#define UDP_SERVER_BUFFER_SIZE 16 + +#define UDP_PAYLOAD_ANGLE_L_BYTE 0x00 +#define UDP_PAYLOAD_ANGLE_H_BYTE 0x01 +#define UDP_PAYLOAD_X_AXIS_SPEED_BYTE 0x02 +#define UDP_PAYLOAD_Y_AXIS_SPEED_BYTE 0x03 + +#define UDP_CLIENT_IP "192.168.128.2" +#define UDP_CLIENT_PORT 4243 + +typedef struct udp_server_t { + struct udp_pcb *pcb; +} udp_server_t; + +void udp_server_init(void); + +void udp_server_exit(void); +// Send data depending of the data in inputs buffer +void udp_server_send(void); + +#endif // UDP_SERVER_H \ No newline at end of file diff --git a/Code Telecommande/src/include/wifi_operator.h b/Code Telecommande/src/include/wifi_operator.h new file mode 100644 index 0000000..c2db061 --- /dev/null +++ b/Code Telecommande/src/include/wifi_operator.h @@ -0,0 +1,10 @@ +#ifndef WIFI_OPERATOR_H +#define WIFI_OPERATOR_H + +#define WIFI_OPERATOR_SSID "RiombotiqueAP" +#define WIFI_OPERATOR_PASSWORD "x4ptSLpPuJFcpzbLEhDoZ5J7dz" +#define WIFI_OPERATOR_CHANNEL 3 + +void wifi_operator_init_ap_mode(void); + +#endif // WIFI_OPERATOR_H \ No newline at end of file diff --git a/Code Telecommande/src/inputs.c b/Code Telecommande/src/inputs.c new file mode 100644 index 0000000..d122ba7 --- /dev/null +++ b/Code Telecommande/src/inputs.c @@ -0,0 +1,50 @@ +#include "include/inputs.h" + +#include +#include "include/controller.h" + +#include + +const button_def_t BUTTONS_DEFS[NB_BUTTONS] = { + {13}, + {9}, + {1}, + {5}, + {6}, + {2} +}; + +void inputs_init(void) +{ + adc_init(); + adc_gpio_init(JOYSTICK_X_AXIS_PIN); + adc_gpio_init(JOYSTICK_Y_AXIS_PIN); + + for(buttons_t actual_button = BUTTON_L; actual_button < NB_BUTTONS; actual_button++) + { + const button_def_t *BUTTON_DEF = &BUTTONS_DEFS[actual_button]; + + gpio_init(BUTTON_DEF->pin); + gpio_set_dir(BUTTON_DEF->pin, GPIO_OUT); + gpio_pull_up(BUTTON_DEF->pin); + } +} + +void get_inputs(void) +{ + adc_select_input(JOYSTICK_X_AXIS_ADC_INPUT); + uint16_t joystick_x_axis = adc_read(); + + adc_select_input(JOYSTICK_Y_AXIS_ADC_INPUT); + uint16_t joystick_y_axis = adc_read(); + + controller.inputs_buffer.x_axis_speed = (joystick_x_axis / 16) - 128; + controller.inputs_buffer.y_axis_speed = (joystick_y_axis / 16) - 128; + + for(buttons_t actual_button = BUTTON_L; actual_button < NB_BUTTONS; actual_button++) + { + const button_def_t *BUTTON_DEF = &BUTTONS_DEFS[actual_button]; + + controller.inputs_buffer.buttons_states[actual_button] = gpio_get(BUTTON_DEF->pin); + } +} diff --git a/Code Telecommande/src/main.c b/Code Telecommande/src/main.c new file mode 100644 index 0000000..9973084 --- /dev/null +++ b/Code Telecommande/src/main.c @@ -0,0 +1,17 @@ +#include "include/controller.h" + +controller_t controller; + +int main(void) +{ + if(controller_init()) return -1; + + while(controller.is_running) + { + controller_handle_inputs_outputs(); + } + + controller_deinit(); + + return 0; +} \ No newline at end of file diff --git a/Code Telecommande/src/udp_server.c b/Code Telecommande/src/udp_server.c new file mode 100644 index 0000000..3e49548 --- /dev/null +++ b/Code Telecommande/src/udp_server.c @@ -0,0 +1,98 @@ +#include "udp_server.h" + +#include +#include +#include +#include "include/controller.h" + +udp_server_t udp_server; + +void udp_server_init() +{ + udp_server.pcb = udp_new(); + if(!udp_server.pcb) + { + puts("Error creating UDP server"); + return; + } + + err_t err = udp_bind(udp_server.pcb, IP_ADDR_ANY, UDP_SERVER_PORT); + if(err != ERR_OK) + { + printf("Error binding UDP server: %d\n", err); + return; + } +} + +void udp_server_exit(void) +{ + if(udp_server.pcb) + { + udp_remove(udp_server.pcb); + udp_server.pcb = NULL; + } +} + +static inline void udp_server_send_data(const uint8_t *data, size_t length) +{ + ip4_addr_t remote_addr; + ip4addr_aton(UDP_CLIENT_IP, &remote_addr); + + // Nombre maximum de tentatives + const int MAX_RETRIES = 3; + uint tries = 0; + + while(tries < MAX_RETRIES) + { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_RAM); + if(p == NULL) + { + printf("Try %d - Error allocating pbuf\n", ++tries); + sleep_ms(100); // Wait before retry + continue; + } + + memcpy(p->payload, (char *)data, length); + err_t err = udp_sendto(udp_server.pcb, p, &remote_addr, UDP_CLIENT_PORT); + pbuf_free(p); + + if (err == ERR_OK) + { + return; // Succès + } + else + { + const char* error_msg; + + switch(err) + { + case ERR_MEM: + error_msg = "Insuficient memory"; + break; + + case ERR_BUF: + error_msg = "Buffer full"; + break; + + default: + error_msg = "Unknown error"; + } + + printf("Try %d - Error send UDP: %d (%s)\n", ++tries, err, error_msg); + + sleep_ms(100); // Wait before retry + } + } + + printf("Error sending data after %d tries...\n", tries); +} + +void udp_server_send(void) +{ + uint8_t data[UDP_SERVER_BUFFER_SIZE]; + + data[UDP_PAYLOAD_X_AXIS_SPEED_BYTE] = *(uint8_t *)&controller.inputs_buffer.x_axis_speed; + data[UDP_PAYLOAD_Y_AXIS_SPEED_BYTE] = *(uint8_t *)&controller.inputs_buffer.x_axis_speed; + + udp_server_send_data(data, UDP_SERVER_BUFFER_SIZE); +} \ No newline at end of file diff --git a/Code Telecommande/src/wifi_operator.c b/Code Telecommande/src/wifi_operator.c new file mode 100644 index 0000000..10d637c --- /dev/null +++ b/Code Telecommande/src/wifi_operator.c @@ -0,0 +1,50 @@ +#include "include/wifi_operator.h" + +#include +#include +#include + +void wifi_operator_init_ap_mode(void) +{ + // Configuration IP pour le mode AP + ip4_addr_t ip, netmask, gateway; + IP4_ADDR(&ip, 192, 168, 128, 1); + IP4_ADDR(&netmask, 255, 255, 255, 0); + IP4_ADDR(&gateway, 192, 168, 128, 1); + + puts("Configuration WiFi en cours..."); + + // Désactiver le mode d'économie d'énergie + cyw43_wifi_pm(&cyw43_state, CYW43_NO_POWERSAVE_MODE); + + // Activer le mode AP + cyw43_arch_enable_ap_mode(WIFI_OPERATOR_SSID, WIFI_OPERATOR_PASSWORD, CYW43_AUTH_WPA2_AES_PSK); + + // Attendre que l'interface soit prête + int retry = 0; + while (netif_default == NULL && retry < 10) + { + sleep_ms(500); + retry++; + } + + if (netif_default == NULL) + { + puts("Erreur: Interface réseau non initialisée"); + return; + } + + // Configuration du canal WiFi + cyw43_wifi_ap_set_channel(&cyw43_state, WIFI_OPERATOR_CHANNEL); + + // Configuration de l'interface réseau + netif_set_up(netif_default); + netif_set_link_up(netif_default); + netif_set_addr(netif_default, &ip, &netmask, &gateway); + + puts("Configuration IP terminée!"); + puts("Point d'accès activé!"); + printf("SSID:%s\n", WIFI_OPERATOR_SSID); + printf("Password:%s\n", WIFI_OPERATOR_PASSWORD); + printf("Channel:%d\n", WIFI_OPERATOR_CHANNEL); +}