diff --git a/extra_script.py b/extra_script.py new file mode 100644 index 0000000..795f8bb --- /dev/null +++ b/extra_script.py @@ -0,0 +1,14 @@ +import os + +Import("env") + +# Add incbin dependencies since Platformio doesn't know about those +env.Depends( + os.path.join("$BUILD_DIR", "src", "pico-plat.o"), + os.path.join("$PROJECT_DIR", "src", "pico-program.lsp") +) + +env.Depends( + os.path.join("$BUILD_DIR", "src", "native-plat.o"), + os.path.join("$PROJECT_DIR", "src", "native-program.lsp") +) diff --git a/platformio.ini b/platformio.ini index 7470bc4..6ba7d17 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,6 +12,7 @@ ;; TODO: Make uclisp to a remote git repo lib_deps = ../uclisp/ + [common] build_flags = -Wall @@ -28,7 +29,8 @@ debug_build_flags = src_filter = + -[env:pico-debug] + +[env:pico-repl-debug] platform = https://github.com/Wiz-IO/wizio-pico.git framework = baremetal board = raspberry-pi-pico @@ -38,13 +40,33 @@ build_flags = -D PLATFORM_PICO_SDK -D LIB_PICO_STDIO_USB -D PICO_USB + -D REPL_APPLICATION build_src_filter = ${common.src_filter} - + - + + upload_protocol = uf2 upload_port = /run/media/max/RPI-RP2 lib_deps = /home/max/repos/uclisp/ +extra_scripts = pre:extra_script.py + +[env:pico-lisp-src-debug] +platform = https://github.com/Wiz-IO/wizio-pico.git +framework = baremetal +board = raspberry-pi-pico +build_flags = + ${common.build_flags} + ${common.debug_build_flags} + -D PLATFORM_PICO_SDK + -D LIB_PICO_STDIO_USB + -D PICO_USB + -D LISP_SOURCE_APPLICATION +build_src_filter = + ${common.src_filter} + + +upload_protocol = uf2 +upload_port = /run/media/max/RPI-RP2 +lib_deps = /home/max/repos/uclisp/ +extra_scripts = pre:extra_script.py [env:native-debug] platform = native @@ -56,6 +78,7 @@ build_src_filter = ${common.src_filter} + + [env:native-release] platform = native build_flags = diff --git a/src/incbin.h b/src/incbin.h new file mode 100644 index 0000000..aa5c7e5 --- /dev/null +++ b/src/incbin.h @@ -0,0 +1,30 @@ +#ifndef _INCBIN_H_ +#define _INCBIN_H_ + +/* Import a binary file */ +#define IMPORT_BIN_STRING(sect, file, sym) asm (\ + ".section " #sect "\n" /* Change section */\ + ".balign 4\n" /* Word alignment */\ + ".global " #sym "\n" /* Export the object address */\ + #sym ":\n" /* Define the object label */\ + ".incbin \"" file "\"\n" /* Import the file */\ + ".byte 0\n" /* Add null terminator */ \ + ".global _sizeof_" #sym "\n" /* Export the object size */\ + ".set _sizeof_" #sym ", . - " #sym "\n" /* Define the object size */\ + ".balign 4\n" /* Word alignment */\ + ".section \".text\"\n") /* Restore section */ + +/* Import a binary file */ +#define IMPORT_BIN(sect, file, sym) asm (\ + ".section " #sect "\n" /* Change section */\ + ".balign 4\n" /* Word alignment */\ + ".global " #sym "\n" /* Export the object address */\ + #sym ":\n" /* Define the object label */\ + ".incbin \"" file "\"\n" /* Import the file */\ + ".global _sizeof_" #sym "\n" /* Export the object size */\ + ".set _sizeof_" #sym ", . - " #sym "\n" /* Define the object size */\ + ".balign 4\n" /* Word alignment */\ + ".section \".text\"\n") /* Restore section */ + + +#endif diff --git a/src/main.c b/src/main.c index 1a92bae..d9dd460 100644 --- a/src/main.c +++ b/src/main.c @@ -1,103 +1,31 @@ #include #include -#include "uclisp.h" -#include "types.h" #include "plat.h" -// TODO:remove -#include "pico/stdio.h" -#include "pico/stdlib.h" -#define UNUSED __attribute__((unused)) +#include struct ucl *ucl; // TODO: Get these from a header -struct ucl_object *ucl_car(struct ucl*, struct ucl_object *); void ucl_print_obj(struct ucl_object *); -// TODO: remove -char buffer[1024] = {0}; - -void pico_getline() { - int chr; - char *end = &buffer[0]; - bool done = false; - while (!done) { - while((chr = getchar_timeout_us(0)) != PICO_ERROR_TIMEOUT) - { - if (chr == '\n' || chr == '\r') { - done = true; - break; - } - - chr = chr & 0xFF; - *end = chr; - end++; - - printf("%c", chr); - fflush(stdout); - } - } - *end = '\0'; - printf("\n"); - fflush(stdout); -} - int main() { - platform_init(); ucl = ucl_create(); + platform_ucl_init(ucl); while(1) { - platform_repl_complete(); - - printf("> "); - fflush(stdout); - - pico_getline(); - - struct ucl_object *sexp = ucl_parse(ucl, buffer); - struct ucl_object *result = NULL; - if (sexp->type == UCL_TYPE_ERROR) { - result = sexp; - } else { - result = ucl_evaluate(ucl, ucl_car(ucl, sexp)); - } + const char *text = platform_get_text(); + struct ucl_object *sexp = ucl_parse(ucl, text); + struct ucl_object *result = ucl_evaluate_progn(ucl, sexp); ucl_print_obj(result); + printf("\n"); ucl_gc(ucl); - printf("\n"); + platform_repl_complete(); } return 0; } - -/* int main() { */ - -/* platform_init(); */ -/* ucl = ucl_create(); */ - -/* while(1) { */ -/* platform_repl_complete(); */ - -/* size_t line_len = 512; */ -/* char *line = NULL; */ -/* printf("> "); */ -/* getline(&line, &line_len, stdin); */ - -/* struct ucl_object *sexp = ucl_parse(ucl, line); */ -/* struct ucl_object *result = NULL; */ -/* if (sexp->type == UCL_TYPE_ERROR) { */ -/* result = sexp; */ -/* } else { */ -/* result = ucl_evaluate(ucl, ucl_car(ucl, sexp)); */ -/* } */ -/* ucl_print_obj(result); */ -/* printf("\n"); */ -/* ucl_gc(ucl); */ -/* } */ - -/* return 0; */ -/* } */ diff --git a/src/native-plat.c b/src/native-plat.c index 232a7d1..f2aeba7 100644 --- a/src/native-plat.c +++ b/src/native-plat.c @@ -1,7 +1,29 @@ +#include +#include +#include + #include "plat.h" void platform_init() { } -void platform_repl_complete() { + +void platform_ucl_init(struct ucl* ucl) { + (void) ucl; +} + +static char *line = NULL; + +const char *platform_get_text() { + size_t line_len = 512; + printf("> "); + line = NULL; + getline(&line, &line_len, stdin); + + return line; +} + +void platform_repl_complete() { + free(line); + } diff --git a/src/pico-lisp.c b/src/pico-lisp.c new file mode 100644 index 0000000..591b405 --- /dev/null +++ b/src/pico-lisp.c @@ -0,0 +1,37 @@ + +#include +#include + +#include "lisp.h" +#include "common.h" +#include "hardware/gpio.h" + +LISP_FUNC_0(pico_lisp_time_millis, state, scope) { + uint32_t millis = to_ms_since_boot(get_absolute_time()); + return ucl_int_create(state, millis); +} + +LISP_FUNC_1(pico_lisp_sleep_millis, state, scope, millis) { + sleep_ms(millis->integer); + return ucl_nil_create(state); +} + +LISP_FUNC_1(pico_lisp_gpio_read, state, scope, gpio) { + gpio_init(gpio->integer); + gpio_set_dir(gpio->integer, GPIO_IN); + return ucl_int_create(state, gpio_get(gpio->integer)); +} + +LISP_FUNC_2(pico_lisp_gpio_write, state, scope, gpio, value) { + gpio_init(gpio->integer); + gpio_set_dir(gpio->integer, GPIO_OUT); + gpio_put(gpio->integer, value->integer); + return ucl_nil_create(state); +} + +void platform_ucl_init(struct ucl* ucl) { + ucl_add_builtin(ucl, "time-millis", pico_lisp_time_millis); + ucl_add_builtin(ucl, "sleep-millis", pico_lisp_sleep_millis); + ucl_add_builtin(ucl, "gpio-read", pico_lisp_gpio_read); + ucl_add_builtin(ucl, "gpio-write", pico_lisp_gpio_write); +} diff --git a/src/pico-plat.c b/src/pico-plat.c index 3275d96..fed3a96 100644 --- a/src/pico-plat.c +++ b/src/pico-plat.c @@ -1,6 +1,8 @@ +#include + +#include "incbin.h" #include "plat.h" -#include #include "pico/stdio.h" #include "pico/stdlib.h" @@ -10,9 +12,61 @@ void platform_init() { stdio_init_all(); gpio_init(PICO_DEFAULT_LED_PIN); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); +#ifndef NDEBUG + // Add a delay to make it easier to connect to serial before the application starts + sleep_ms(1000); +#endif +} + +#ifdef REPL_APPLICATION +char buffer[1024] = {0}; +void pico_getline() { + int chr; + char *end = &buffer[0]; + bool done = false; + while (!done) { + while((chr = getchar_timeout_us(0)) != PICO_ERROR_TIMEOUT) + { + if (chr == '\n' || chr == '\r') { + done = true; + break; + } + + chr = chr & 0xFF; + *end = chr; + end++; + + printf("%c", chr); + fflush(stdout); + } + } + *end = '\0'; + printf("\n"); + fflush(stdout); +} + +const char *platform_get_text() { + pico_getline(); + return buffer; } void platform_repl_complete() { gpio_put(PICO_DEFAULT_LED_PIN, gpio_state); gpio_state = !gpio_state; } + +#endif + +#ifdef LISP_SOURCE_APPLICATION + +IMPORT_BIN_STRING(".rodata.lsp", "pico-program.lsp", lisp_program_src); +extern const char lisp_program_src[]; +const char *platform_get_text() { + return lisp_program_src; +} + +void platform_repl_complete() { + +} + +#endif diff --git a/src/pico-program.lsp b/src/pico-program.lsp new file mode 100644 index 0000000..97a4188 --- /dev/null +++ b/src/pico-program.lsp @@ -0,0 +1,4 @@ +(gpio-write 0 1) +(sleep-millis 100) +(gpio-write 0 0) +(sleep-millis 100) diff --git a/src/pico-program.lsp.in b/src/pico-program.lsp.in new file mode 100644 index 0000000..b2bf0f9 --- /dev/null +++ b/src/pico-program.lsp.in @@ -0,0 +1,9 @@ +unsigned char src_pico_program_lsp[] = { + 0x28, 0x67, 0x70, 0x69, 0x6f, 0x2d, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, + 0x30, 0x20, 0x31, 0x29, 0x0a, 0x28, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x2d, + 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x20, 0x31, 0x30, 0x30, 0x29, 0x0a, + 0x28, 0x67, 0x70, 0x69, 0x6f, 0x2d, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, + 0x30, 0x20, 0x30, 0x29, 0x0a, 0x28, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x2d, + 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x20, 0x31, 0x30, 0x30, 0x29, 0x0a +}; +unsigned int src_pico_program_lsp_len = 72; diff --git a/src/plat.h b/src/plat.h index 78ae69b..5b2aea7 100644 --- a/src/plat.h +++ b/src/plat.h @@ -9,7 +9,12 @@ #include "native-plat.h" #endif +struct ucl; + void platform_init(); +void platform_ucl_init(struct ucl *ucl); +const char* platform_get_text(); void platform_repl_complete(); + #endif