Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 5108

General • Re: PT52-Lua The Modern Retro computer

$
0
0
Hello,

Nice work with the RP2350 in 320 x 100 @ 256 colour mode!

I wanted to check in to say today I studied how you add C functions to a LUA library. This is using the C API for LUA, correct?
https://www.lua.org/pil/24.html

To see how it is done, I looked up how to find prime numbers. Using a bit of AI, I got some C code that works, and I made a prime lib. The Sieve of Eratosthenes prime number finder works, but if I send the table to a function to grab the Mersenne, the display cuts out.

I poked around your code and found after adding my lprime.c source to pt52-lua/programs/lua, I needed to add a #define to lualib.h, then add it to the array and function in loadmod.c - this not difficult , very nice! I also saw in linit.c where one adds/deletes the preloaded libs.

lprime.c

Code:

#define lprime_c#define LUA_LIB#include "pico/stdlib.h"#include "lua.h"#include "lauxlib.h"#include "lualib.h"#include <stdlib.h>#include <stdbool.h>//#include <math.h>// Sieve of Eratosthenes to find prime numbersstatic int lua_find_primes(lua_State *L) {    // Get the upper limit `n` from Lua    int n = luaL_checkinteger(L, 1);    if (n < 2) {        return luaL_error(L, "n must be greater than or equal to 2");    }    // Create a dynamic array to avoid VLAs    bool *A = malloc((n + 1) * sizeof(bool));    if (!A) {        return luaL_error(L, "Memory allocation failed");    }    // Initialize all entries as true    for (int i = 2; i <= n; i++) {        A[i] = true;    }    // Apply the Sieve of Eratosthenes    for (int i = 2; i * i <= n; i++) {        if (A[i]) {            for (int j = i * i; j <= n; j += i) {                A[j] = false;            }        }    }    // Create a new Lua table to hold the primes    lua_newtable(L);    // Populate the Lua table with prime numbers    int index = 1; // Lua tables start at 1    for (int i = 2; i <= n; i++) {        if (A[i]) {            lua_pushinteger(L, i); // Push prime number            lua_rawseti(L, -2, index++); // Set it in the Lua table        }    }    // Free allocated memory    free(A);    // Return the Lua table (already on the stack)    return 1;}// CRASHES: Function to find Mersenne primes from the prime tablestatic int lua_find_mersenne_primes(lua_State *L) {    // Check if the first argument is a table    luaL_checktype(L, 1, LUA_TTABLE);    // Create a new Lua table for the results    lua_newtable(L);    int index = 1; // Lua table index for Mersenne primes    // Iterate over the input prime table    lua_pushnil(L); // Initial key for lua_next    while (lua_next(L, 1) != 0) {        // Check if the value is an integer        if (!lua_isinteger(L, -1)) {            lua_pop(L, 1); // Pop the value, keep the key            continue;      // Skip invalid entries        }        int prime = lua_tointeger(L, -1);        // Ensure the prime is in a valid range        if (prime <= 0 || prime > 31) {            lua_pop(L, 1); // Pop the value, keep the key            continue;      // Skip invalid primes        }        // Calculate M_p = 2^p - 1        int32_t mersenne = ((int32_t)1 << prime) - 1;        // Add the Mersenne prime to the result table        lua_pushinteger(L, mersenne); // Push Mersenne prime        lua_rawseti(L, -3, index++);  // Add to Lua table at index        lua_pop(L, 1); // Pop the value, keep the key for the next iteration    }    // Return the result table    return 1;}// Register the function in the Lua librarystatic const struct luaL_Reg prime_lib[] = {    {"find", lua_find_primes},    {"find_mersenne", lua_find_mersenne_primes}, // Mersenne prime function    {NULL, NULL}};// Open the libraryLUAMOD_API int luaopen_prime(lua_State *L) {    luaL_newlib(L, prime_lib);    return 1;}
Say, what are these macros for?
#define lprime_c
#define LUA_LIB

then add the macro to lualib.h

Code:

#define LUA_PRIMELIBNAME "prime"LUAMOD_API int luaopen_prime (lua_State *L);
then edit loadmod.c

Code:

/*#define LUA_PRIMELIBNAME "prime"LUAMOD_API int luaopen_prime (lua_State *L);*/static const luaL_Reg loadablelibs[] = {  {LUA_LOADLIBNAME, luaopen_package}, // 0  {LUA_COLIBNAME, luaopen_coroutine},  {LUA_TABLIBNAME, luaopen_table},  {LUA_IOLIBNAME, luaopen_io},  {LUA_OSLIBNAME, luaopen_os},        // 4  {LUA_STRLIBNAME, luaopen_string},  {LUA_MATHLIBNAME, luaopen_math},  {LUA_UTF8LIBNAME, luaopen_utf8},  {LUA_DBLIBNAME, luaopen_debug},  {LUA_PTLIBNAME, luaopen_pt},  {LUA_DRAWLIBNAME, luaopen_draw},  {LUA_SPRITESLIBNAME, luaopen_sprites},  {LUA_VRAMLIBNAME, luaopen_vram},  {LUA_FSLIBNAME, luaopen_fs},  {LUA_UARTLIBNAME, luaopen_uart},  {LUA_OVERLAYLIBNAME, luaopen_overlay},  {LUA_GPIOLIBNAME, luaopen_gpio},  {LUA_PRIMELIBNAME, luaopen_prime},};static int mod_uses (lua_State *L) {  const char *name = luaL_checkstring(L, 1);  static const char *const opts[] = {LUA_LOADLIBNAME, LUA_COLIBNAME, LUA_TABLIBNAME, LUA_IOLIBNAME,     LUA_OSLIBNAME, LUA_STRLIBNAME, LUA_MATHLIBNAME, LUA_UTF8LIBNAME, LUA_DBLIBNAME, LUA_PTLIBNAME,     LUA_DRAWLIBNAME, LUA_SPRITESLIBNAME, LUA_VRAMLIBNAME, LUA_FSLIBNAME, LUA_UARTLIBNAME,    LUA_OVERLAYLIBNAME, LUA_GPIOLIBNAME, LUA_PRIMELIBNAME, NULL };
Why are you not using null in the array like the others, that is, having the last element:
{NULL, NULL} // Sentinel value indicating the end of the array

Oh, I also made a silly GPIO one for fun, even though none are really available. I know your project uses the Pico LED, but with this I can control it from the LUA REPL (I wanted to do like in micropython shell for fun). Anyway, I know the VGA stuff is the fun stuff, but I'm playing around.

lgpio.c

Code:

#define lgpio_c#define LUA_LIB#include "pico/stdlib.h"#include "lua.h"#include "lauxlib.h"#include "lualib.h"// Set GPIO pin as outputstatic int lua_gpio_set_output(lua_State *L) {    int pin = luaL_checkinteger(L, 1);    if (pin < 0 || pin > 29) {        return luaL_error(L, "Invalid GPIO pin: %d", pin);    }    gpio_init(pin);    gpio_set_dir(pin, GPIO_OUT);}// Set GPIO pin highstatic int lua_gpio_set_high(lua_State *L) {    int pin = luaL_checkinteger(L, 1);    gpio_put(pin, 1);}// Set GPIO pin lowstatic int lua_gpio_set_low(lua_State *L) {    int pin = luaL_checkinteger(L, 1);    gpio_put(pin, 0);}// Delay functionstatic int lua_delay(lua_State *L) {    int ms = luaL_checkinteger(L, 1);    sleep_ms(ms);    return 0;}// GPIO library functionsstatic const struct luaL_Reg gpio_lib[] = {    {"set_output", lua_gpio_set_output},    {"set_high", lua_gpio_set_high},    {"set_low", lua_gpio_set_low},    {"delay", lua_delay},    {NULL, NULL}};LUAMOD_API int luaopen_gpio(lua_State *L) {    luaL_newlib(L, gpio_lib); // Create the library table    return 1;}
Here is a pic of the regular prime finder
Image

Oh, and your FEATURE-USB-overhaul and RP2350_Support do the unlink error when building, but not UPGRADE-Use_newlib_syscalls, that one build without that error.

I will try those LUA libs you added to the repo for the SD card! Are the loaded with require? I still need to really learn LUA.

Again, nice work!

Statistics: Posted by breaker — Thu Jan 23, 2025 11:41 pm



Viewing all articles
Browse latest Browse all 5108

Trending Articles