// // Created by jedi on 25.06.21. // #include "lux.h" #include "log.h" #include #include #include #include extern "C" { #include #include #include } #include const int signal_led_pin = 2; const int cs0 = 15; const int gpio4 = 4; const int gpio5 = 5; extern "C" void signal_led(bool state) { gpio_write(signal_led_pin, !state); } enum class parse_status { ERROR, SET_PIXEL_RGB, SET_PIXEL_RGBW, GET_PIXEL, GET_DIMENSIONS, GET_HELP }; parse_status parse_pixelflut_message(const char *msg, size_t len, uint16_t &x, uint16_t &y, uint8_t &r, uint8_t &g, uint8_t &b, uint8_t &w) { if(len < 4) return parse_status::ERROR; if(msg[0] == 'P' && msg[1] == 'X' && msg[2] == ' ') { size_t i = 3; size_t j = 0; char buf[5]; while (i < len && msg[i] != ' ' && j < 4) { buf[j++] = msg[i++]; } buf[j] = 0; x = atoi(buf); while(i < len && msg[i] == ' ') i++; j = 0; while (i < len && msg[i] != ' ' && j < 4) { buf[j++] = msg[i++]; } buf[j] = 0; y = atoi(buf); while(i < len && msg[i] == ' ') i++; if(i >= len) return parse_status::GET_PIXEL; j = 0; while (i < len && msg[i] != ' ' && j < 4) { buf[j++] = msg[i++]; } buf[j] = 0; r = atoi(buf); while(i < len && msg[i] == ' ') i++; j = 0; while (i < len && msg[i] != ' ' && j < 4) { buf[j++] = msg[i++]; } buf[j] = 0; g = atoi(buf); while(i < len && msg[i] == ' ') i++; j = 0; while (i < len && msg[i] != ' ' && j < 4) { buf[j++] = msg[i++]; } buf[j] = 0; b = atoi(buf); while(i < len && msg[i] == ' ') i++; if(i >= len) return parse_status::SET_PIXEL_RGB; j = 0; while (i < len && msg[i] != ' ' && j < 4) { buf[j++] = msg[i++]; } buf[j] = 0; w = atoi(buf); return parse_status::SET_PIXEL_RGBW; } else if(msg[0] == 'S' && msg[1] == 'I' && msg[2] == 'Z' && msg[3] == 'E') { return parse_status::GET_DIMENSIONS; } else if(msg[0] == 'H' && msg[1] == 'E' && msg[2] == 'L' && msg[3] == 'P') { return parse_status::GET_HELP; } else { return parse_status::ERROR; } } [[noreturn]] static void pixelflut_task(void *pvParameters) { //char *wifi_ap_ip_addr = nullptr; //sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); //if(!wifi_ap_ip_addr) { // syslog("dns: no ip address\n"); // vTaskDelete(nullptr); //} //ip4_addr_t server_addr; //server_addr.addr = ipaddr_addr(wifi_ap_ip_addr); #if LWIP_IPV6 int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); sockaddr_in6 serv_addr; memset(&serv_addr, '0', sizeof(serv_addr)); serv_addr.sin6_family = AF_INET6; serv_addr.sin6_port = htons(53); serv_addr.sin6_flowinfo = 0; serv_addr.sin6_addr = in6addr_any; serv_addr.sin6_scope_id = IP6_NO_ZONE; #else int fd = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); sockaddr_in serv_addr{}; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = lwip_htonl(INADDR_ANY); serv_addr.sin_port = lwip_htons(2342); #endif lwip_bind(fd, (sockaddr *) &serv_addr, sizeof(serv_addr)); printf("pixelflut: listening on port 2342\n"); const ifreq ifreq0 = {"en0"}; const ifreq ifreq1 = {"en1"}; lwip_setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, sdk_wifi_get_opmode() == STATIONAP_MODE ? &ifreq1 : &ifreq0, sizeof(ifreq0)); int width = 23; int height = 42; char buffer[96] = {0}; sockaddr_storage src_addr{}; for (;;) { socklen_t src_addr_len = sizeof(src_addr); ssize_t count = lwip_recvfrom(fd, buffer, sizeof(buffer), 0, (sockaddr *) &src_addr, &src_addr_len); uint16_t x, y; uint8_t r, g, b, w; parse_status status = parse_pixelflut_message((char *) buffer, count, x, y, r, g, b, w); if(status == parse_status::SET_PIXEL_RGB) { printf("set pixel %d %d to %d %d %d\n", x, y, r, g, b); } else if(status == parse_status::SET_PIXEL_RGBW) { printf("set pixel %d %d to %d %d %d %d\n", x, y, r, g, b, w); } else if(status == parse_status::GET_PIXEL) { uint32_t reply_len = snprintf((char *) buffer, 96, "PX %d %d %d %d %d %d", x, y, r, g, b, w); lwip_sendto(fd, buffer, reply_len, 0, (sockaddr *) &src_addr, src_addr_len); } else if(status == parse_status::GET_DIMENSIONS) { uint32_t reply_len = snprintf((char *) buffer, 96, "SIZE %d %d", width, height); lwip_sendto(fd, buffer, reply_len, 0, (sockaddr *) &src_addr, src_addr_len); } else if(status == parse_status::GET_HELP) { uint32_t reply_len = snprintf((char *) buffer, 96, "HELP"); lwip_sendto(fd, buffer, reply_len, 0, (sockaddr *) &src_addr, src_addr_len); } else { uint32_t reply_len = snprintf((char *) buffer, 96, "ERR"); lwip_sendto(fd, buffer, reply_len, 0, (sockaddr *) &src_addr, src_addr_len); printf("error parsing message [%d bytes]: \n", count); for (int i = 0; i < count; i++) { printf("%c", buffer[i]); } printf("\n"); } } } extern "C" void lux_task(void *pvParameters) { gpio_enable(signal_led_pin, GPIO_OUTPUT); gpio_enable(cs0, GPIO_OUTPUT); gpio_enable(gpio4, GPIO_OUTPUT); gpio_enable(gpio5, GPIO_OUTPUT); spi_init(1, SPI_MODE0, SPI_FREQ_DIV_1M, true, SPI_BIG_ENDIAN, true); xTaskCreate(&pixelflut_task, "pixelflut_task", 512, nullptr, 2, nullptr); vTaskDelete(nullptr); }