commit edf1e9fd8abc9cbf6e7d80730abc07665f684374 Author: PoliEcho Date: Tue Aug 4 17:03:04 2026 +0200 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e3e6610 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build* +.cache +.vscode +src/core/config.hpp +readsb \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..14345f7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 3.13) + +option(BUILD_FOR_PICO "Build for Raspberry Pi Pico" ON) + +if(BUILD_FOR_PICO) + set(PICO_BOARD pico_w CACHE STRING "Board type") + include(pico_sdk_import.cmake) + project(p-rad C CXX ASM) + + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + + pico_sdk_init() + + add_executable(p-rad + src/main.cpp + src/core/logic.cpp + src/hal/hal_pico.cpp + ) + + target_compile_definitions(p-rad PRIVATE PICO_BUILD) + target_include_directories(p-rad PRIVATE src) + target_link_libraries(p-rad pico_stdlib pico_cyw43_arch_lwip_threadsafe_background hardware_rtc) + + pico_enable_stdio_usb(p-rad 1) + pico_enable_stdio_uart(p-rad 0) + + pico_add_extra_outputs(p-rad) +else() + project(p-rad CXX) + + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + + add_executable(p-rad + src/main.cpp + src/core/logic.cpp + src/hal/hal_linux.cpp + ) + + target_include_directories(p-rad PRIVATE src) + find_package(Threads REQUIRED) + find_package(SDL3 REQUIRED CONFIG) + find_package(CURL REQUIRED) + target_link_libraries(p-rad Threads::Threads SDL3::SDL3 CURL::libcurl) +endif() \ No newline at end of file diff --git a/pico_sdk_import.cmake b/pico_sdk_import.cmake new file mode 100644 index 0000000..d493cc2 --- /dev/null +++ b/pico_sdk_import.cmake @@ -0,0 +1,121 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +# Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +# following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG)) + set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG}) + message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')") +endif () + +if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG) + set(PICO_SDK_FETCH_FROM_GIT_TAG "master") + message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG") +endif() + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") +set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + ) + + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + # GIT_SUBMODULES_RECURSE was added in 3.17 + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") + FetchContent_Populate( + pico_sdk + QUIET + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + GIT_SUBMODULES_RECURSE FALSE + + SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src + BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build + SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild + ) + else () + FetchContent_Populate( + pico_sdk + QUIET + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + + SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src + BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build + SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild + ) + endif () + + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/res/station.h b/res/station.h new file mode 100644 index 0000000..677d7cb --- /dev/null +++ b/res/station.h @@ -0,0 +1,25 @@ +/* Auto-generated by export-alpha-bitmap GIMP plugin */ +/* 1 = opaque, 0 = transparent. MSB-first, rows padded to a byte. */ + +#define STATION_WIDTH 16 +#define STATION_HEIGHT 16 +#define STATION_BYTES_PER_ROW 2 + +static const unsigned char station[32] = { + 0x7F, 0xFE, + 0x84, 0x21, + 0x84, 0x21, + 0x84, 0x21, + 0x84, 0x21, + 0x7F, 0xFE, + 0x22, 0x44, + 0x12, 0x48, + 0x0A, 0x50, + 0x0A, 0x50, + 0x0A, 0x50, + 0x0A, 0x50, + 0x0A, 0x50, + 0x0A, 0x50, + 0x0A, 0x50, + 0x0F, 0xF0 +}; diff --git a/src/core/color.h b/src/core/color.h new file mode 100644 index 0000000..a424b8d --- /dev/null +++ b/src/core/color.h @@ -0,0 +1,23 @@ + +// Header guard +#ifndef RESET + +#define RESET "\033[0m" +#define BLACK "\033[30m" /* Black */ +#define RED "\033[31m" /* Red */ +#define GREEN "\033[32m" /* Green */ +#define YELLOW "\033[33m" /* Yellow */ +#define BLUE "\033[34m" /* Blue */ +#define MAGENTA "\033[35m" /* Magenta */ +#define CYAN "\033[36m" /* Cyan */ +#define WHITE "\033[37m" /* White */ +#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */ +#define BOLDRED "\033[1m\033[31m" /* Bold Red */ +#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */ +#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */ +#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */ +#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */ +#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */ +#define BOLDWHITE "\033[1m\033[37m" /* Bold White */ + +#endif \ No newline at end of file diff --git a/src/core/const.hpp b/src/core/const.hpp new file mode 100644 index 0000000..f549e90 --- /dev/null +++ b/src/core/const.hpp @@ -0,0 +1,13 @@ +#pragma once +#include +#include +constexpr char *program_name = "p-rad"; +constexpr char* user_agent = "p-rad/0.1"; + +constexpr char* base_url = "http://127.0.0.1:8200/"; + +// max range in km +constexpr uint16_t max_range = 500; + +// distance of first ring from the center on the screen +constexpr uint16_t first_ring_distance = 50; \ No newline at end of file diff --git a/src/core/logic.cpp b/src/core/logic.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/core/logic.hpp b/src/core/logic.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/hal/draw.hpp b/src/hal/draw.hpp new file mode 100644 index 0000000..6cd230a --- /dev/null +++ b/src/hal/draw.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + + +namespace draw { + struct color_t { + uint8_t r; + uint8_t g; + uint8_t b; +}; +struct rect_t { + uint16_t w; + uint16_t h; + uint16_t x; + uint16_t y; +}; + void pixel(const uint16_t x, const uint16_t y, const color_t color); + void filled_rect(const rect_t* rect, const color_t color); + void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color); +} \ No newline at end of file diff --git a/src/hal/hal.hpp b/src/hal/hal.hpp new file mode 100644 index 0000000..6c917d3 --- /dev/null +++ b/src/hal/hal.hpp @@ -0,0 +1,10 @@ +#pragma once +#include +#include +namespace hal { +int init(); +std::tuple get_screen_size(); + +void start_frame(); +void end_frame(); +} \ No newline at end of file diff --git a/src/hal/hal_linux.cpp b/src/hal/hal_linux.cpp new file mode 100644 index 0000000..d5a06e2 --- /dev/null +++ b/src/hal/hal_linux.cpp @@ -0,0 +1,185 @@ +#include "../core/const.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "draw.hpp" +#include "hal/hal.hpp" +#include +#include +#include +#include +#include +#include +#include "../core/color.h" +struct sdl_session { + SDL_Window *window; + SDL_Renderer *renderer; +}; + +sdl_session main_sdl_session; +const SDL_DisplayMode *mode; +CURL *curl; + +namespace hal { +int init() { + SDL_Init(SDL_INIT_VIDEO); + mode = SDL_GetCurrentDisplayMode(SDL_GetPrimaryDisplay()); + main_sdl_session.window = + SDL_CreateWindow(program_name, mode->w, mode->h, SDL_WINDOW_FULLSCREEN); + main_sdl_session.renderer = + SDL_CreateRenderer(main_sdl_session.window, "gpu,vulcan"); + return 0; + + curl = curl_easy_init(); +} + +std::tuple get_screen_size() { return {mode->w, mode->h}; } +uint64_t frame_start; +void start_frame() { + frame_start = SDL_GetTicksNS(); + SDL_SetRenderDrawColor(main_sdl_session.renderer, 0, 0, 0, 255); + SDL_RenderClear(main_sdl_session.renderer); +} + +const Uint64 frame_delay_ns = 1000000000ULL / 1; +void end_frame() { + + SDL_RenderPresent(main_sdl_session.renderer); + + uint64_t frame_time = SDL_GetTicksNS() - frame_start; + + if (frame_time < frame_delay_ns) { + SDL_DelayNS(frame_delay_ns - frame_time); + } +} +} // namespace hal + +namespace draw { +void pixel(const uint16_t x, const uint16_t y, const color_t color) { + SDL_SetRenderDrawColor(main_sdl_session.renderer, color.r, color.g, color.b, + 0xff); + SDL_RenderPoint(main_sdl_session.renderer, x, y); +} + +void filled_rect(const rect_t *rect, const color_t color) { + SDL_SetRenderDrawColor(main_sdl_session.renderer, color.r, color.g, color.b, + 0xff); + const SDL_FRect frect = { + static_cast(rect->x), static_cast(rect->y), + static_cast(rect->w), static_cast(rect->h)}; + SDL_RenderFillRect(main_sdl_session.renderer, &frect); +} + +void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color) { + SDL_SetRenderDrawColor(main_sdl_session.renderer, color.r, color.g, color.b, + 0xff); + + // based on https://www.geeksforgeeks.org/dsa/mid-point-circle-drawing-algorithm/ + int x = radius, y = 0; + + // Printing the initial point on the axes + // after translation + SDL_RenderPoint(main_sdl_session.renderer, x + x_center, y + y_center); + + // When radius is zero only a single + // point will be printed + if (radius > 0) + { + SDL_RenderPoint(main_sdl_session.renderer, x + x_center, -y + y_center); + SDL_RenderPoint(main_sdl_session.renderer, y + x_center, x + y_center); + SDL_RenderPoint(main_sdl_session.renderer, -y + x_center, x + y_center); + std::cout << "\n"; + } + + // Initialising the value of P + int P = 1 - radius; + while (x > y) + { + y++; + + // Mid-point is inside or on the perimeter + if (P <= 0) + P = P + 2*y + 1; + // Mid-point is outside the perimeter + else + { + x--; + P = P + 2*y - 2*x + 1; + } + + // All the perimeter points have already been printed + if (x < y) + break; + + // Printing the generated point and its reflection + // in the other octants after translation + SDL_RenderPoint(main_sdl_session.renderer, x + x_center, y + y_center); + SDL_RenderPoint(main_sdl_session.renderer, -x + x_center, y + y_center); + SDL_RenderPoint(main_sdl_session.renderer, x + x_center, -y + y_center); + SDL_RenderPoint(main_sdl_session.renderer, -x + x_center, -y + y_center); + + // If the generated point is on the line x = y then + // the perimeter points have already been printed + if (x != y) + { + SDL_RenderPoint(main_sdl_session.renderer, y + x_center, x + y_center); + SDL_RenderPoint(main_sdl_session.renderer, -y + x_center, x + y_center); + SDL_RenderPoint(main_sdl_session.renderer, y + x_center, -x + y_center); + SDL_RenderPoint(main_sdl_session.renderer, -y + x_center, -x + y_center); + } + } +} +} // namespace draw + +namespace net { +// Callback function to write data into a std::string +size_t WriteCallback_to_string(void *contents, size_t size, size_t nmemb, + void *userp) { + size_t totalSize = size * nmemb; + static_cast(userp)->append((char *)contents, totalSize); + return totalSize; +} + +nlohmann::json http_get_json(const std::string &url) { + std::string response; + if (curl) { + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback_to_string); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip, deflate"); + + curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent); + + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); + + CURLcode curl_return_code = curl_easy_perform(curl); + if (curl_return_code != CURLE_OK) { + std::cerr << RED "[ERROR] " << RESET << "curl_easy_perform() failed: " + << curl_easy_strerror(curl_return_code) << "\n"; + exit(21); + } + int http_code = 0; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + + if (http_code < 200 || http_code >= 300) { + return nullptr; + } + return nlohmann::json::parse(response); + } + return nullptr; +} +} // namespace net \ No newline at end of file diff --git a/src/hal/hal_pico.cpp b/src/hal/hal_pico.cpp new file mode 100644 index 0000000..720fc52 --- /dev/null +++ b/src/hal/hal_pico.cpp @@ -0,0 +1,40 @@ +#include "hal/hal.hpp" +#include "pico/cyw43_arch.h" +#include "pico/stdlib.h" +#include "hardware/rtc.h" +#include +#include +#include + +extern "C" u32_t lwip_rand(void) { return get_rand_32(); } + +namespace hal { +int init() { + stdio_init_all(); + if (cyw43_arch_init()) { + return 1; + } + rtc_init(); + return 0; +} + +std::tuple get_screen_size() { + return {0,0}; +} +int8_t sec; +void start_frame() { + datetime_t dt; + rtc_get_datetime(&dt); + sec = dt.sec; +} +void end_frame() { + datetime_t dt; + while (true) { + rtc_get_datetime(&dt); + if(sec != dt.sec) { + return; + } + sleep_ms(5); + } +} +} // namespace hal diff --git a/src/hal/net.hpp b/src/hal/net.hpp new file mode 100644 index 0000000..7ba413f --- /dev/null +++ b/src/hal/net.hpp @@ -0,0 +1,7 @@ +#pragma once +#include +#include + +namespace net { + nlohmann::json http_get_json(const std::string &url); +} diff --git a/src/lwipopts.h b/src/lwipopts.h new file mode 100644 index 0000000..32fa885 --- /dev/null +++ b/src/lwipopts.h @@ -0,0 +1,268 @@ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +/** + * NO_SYS==1: Bare metal lwIP + */ +#define NO_SYS 1 +/** + * LWIP_NETCONN==0: Disable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN 0 +/** + * LWIP_SOCKET==0: Disable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET 0 + +/** + * SYS_LIGHTWEIGHT_PROT==1: enable inter-task protection (and task-vs-interrupt + * protection) for certain critical regions during buffer allocation, + * deallocation and memory allocation and deallocation. ATTENTION: This is + * required when using lwIP from more than one context! If you disable this, you + * must be sure what you are doing! + */ +/** + * SYS_LIGHTWEIGHT_PROT==0: + */ +#define SYS_LIGHTWEIGHT_PROT 0 + +/* ---------- Memory options ---------- */ +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 4 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE (22 * 1024) +#endif + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 15 +#endif +/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + per active UDP "connection". */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 6 +#endif +/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP + connections. */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 10 +#endif +/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP + connections. */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 6 +#endif +/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP + segments. */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 22 +#endif +/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active + timeouts. */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT 10 +#endif + +/* ---------- Pbuf options ---------- */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 9 +#endif + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ +/* Default value is defined in lwip\src\include\lwip\opt.h as + * LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)*/ + +/* ---------- TCP options ---------- */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +#ifndef TCP_TTL +#define TCP_TTL 255 +#endif + +/* Controls if TCP should queue segments that arrive out of + order. Define to 0 if your device is low on memory. */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ 0 +#endif + +/* TCP Maximum segment size. */ +#ifndef TCP_MSS +#define TCP_MSS \ + (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) \ + */ +#endif + +/* TCP sender buffer space (bytes). */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF (6 * TCP_MSS) // 2 +#endif + +/* TCP sender buffer space (pbufs). This must be at least = 2 * + TCP_SND_BUF/TCP_MSS for things to work. */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN (3 * TCP_SND_BUF) / TCP_MSS // 6 +#endif + +/* TCP receive window. */ +#ifndef TCP_WND +#define TCP_WND (2 * TCP_MSS) +#endif + +/* Enable backlog*/ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 1 +#endif + +/* ---------- Network Interfaces options ---------- */ +/* Support netif api (in netifapi.c). */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/* ---------- ICMP options ---------- */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/* ---------- DHCP options ---------- */ +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + interfaces. DHCP is not implemented in lwIP 0.5.1, however, so + turning this on does currently not work. */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 1 +#endif + +/* ---------- UDP options ---------- */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif +#ifndef UDP_TTL +#define UDP_TTL 255 +#endif + +/* ---------- Statistics options ---------- */ +#ifndef LWIP_STATS +#define LWIP_STATS 0 +#endif +#ifndef LWIP_PROVIDE_ERRNO +#define LWIP_PROVIDE_ERRNO 1 +#endif + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ + +/* +Some MCU allow computing and verifying the IP, UDP, TCP and ICMP checksums by +hardware: + - To use this feature let the following define uncommented. + - To disable it and process by CPU comment the the checksum. +*/ +// #define CHECKSUM_BY_HARDWARE + +#ifdef CHECKSUM_BY_HARDWARE +/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ +#define CHECKSUM_GEN_IP 0 +/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP + * packets.*/ +#define CHECKSUM_GEN_UDP 0 +/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP + * packets.*/ +#define CHECKSUM_GEN_TCP 0 +/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/ +#define CHECKSUM_CHECK_IP 0 +/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP + * packets.*/ +#define CHECKSUM_CHECK_UDP 0 +/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP + * packets.*/ +#define CHECKSUM_CHECK_TCP 0 +#else +/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/ +#define CHECKSUM_GEN_IP 1 +/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP + * packets.*/ +#define CHECKSUM_GEN_UDP 1 +/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP + * packets.*/ +#define CHECKSUM_GEN_TCP 1 +/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/ +#define CHECKSUM_CHECK_IP 1 +/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP + * packets.*/ +#define CHECKSUM_CHECK_UDP 1 +/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP + * packets.*/ +#define CHECKSUM_CHECK_TCP 1 +#endif + +/* + ------------------------------------ + ---------- Debugging options ---------- + ------------------------------------ +*/ + +// #define LWIP_DEBUG + +// TODO: map these to + +#ifdef LWIP_DEBUG +#define U8_F "c" +#define S8_F "c" +#define X8_F "02x" +#define U16_F "u" +#define S16_F "d" +#define X16_F "x" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" +#define SZT_F "u" +#endif + +#define LWIP_DNS 1 + +#if (LWIP_DNS || LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND) +/* When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function + * returning an u32_t random value*/ +#include "lwip/arch.h" +#ifdef __cplusplus +extern "C" { +#endif +u32_t lwip_rand(void); +#ifdef __cplusplus +} +#endif +#define LWIP_RAND() lwip_rand() +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void sync_system_time(unsigned int sec, unsigned int usec); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIPOPTS_H__ */ + +/*****END OF FILE****/ diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..4664849 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,56 @@ +#include "../res/station.h" +#include "core/const.hpp" +#include "hal/draw.hpp" +#include "hal/hal.hpp" +#include +#include + +int main() { + if (hal::init() != 0) { + return 1; + } + const auto [screen_w, screen_h] = hal::get_screen_size(); + + const float pixels_per_km = static_cast(screen_h > screen_w ? screen_w : screen_h) / (max_range*2); + bool odd_even = true; + + const uint16_t middle_x = (screen_w / 2); + const uint16_t middle_y = (screen_h / 2); + + while (true) { + hal::start_frame(); + + { // sing of life + draw::rect_t rect = {10, 10, static_cast(screen_w - 10), 0}; + draw::filled_rect(&rect, + {static_cast(odd_even ? 0x0 : 0xff), 0, 0xff}); + odd_even = !odd_even; + } + + { // draw station + + uint16_t y = middle_y - STATION_HEIGHT / 2; + for (uint8_t i = 0; i < STATION_HEIGHT; i++) { + uint16_t x = middle_x - STATION_WIDTH / 2; + for (uint8_t j = 0; j < STATION_WIDTH; j++) { + uint8_t byte = station[i * STATION_BYTES_PER_ROW + j / 8]; + + if((byte >> (7 - (j % 8))) & 1) { + draw::pixel(x, y, {0xff,0xff,0xff}); + } + x++; + } + y++; + } + } + + { // draw rings + for(uint16_t r = first_ring_distance; r <= max_range; r *=2) { + draw::circle(middle_x, middle_y, r*pixels_per_km, {0xff,0xff,0xff}); + } + } + + + hal::end_frame(); + } +} \ No newline at end of file