From 744723b6d48e177355701a15803af1c5c6d47cfa Mon Sep 17 00:00:00 2001 From: Joerg Siebenmorgen Date: Fri, 24 Nov 2023 22:53:49 +0100 Subject: [PATCH 1/5] Improvements for image.save() --- src/ui/image.cpp | 76 ++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/src/ui/image.cpp b/src/ui/image.cpp index b0797ceb..d01d08f1 100644 --- a/src/ui/image.cpp +++ b/src/ui/image.cpp @@ -450,17 +450,19 @@ void cmd_image_hide(var_s *self, var_s *) { } // -// Output the image to a PNG file +// Output the image to a PNG file or an array // // png.save("horse1.png") // png.save(#1) +// png.save(byref var) +// file = "abc.png" : png.save(file) // void cmd_image_save(var_s *self, var_s *) { unsigned id = map_get_int(self, IMG_BID, -1); ImageBuffer *image = get_image(id); dev_file_t *file; - var_t *array; - var_t var; + var_t *var; + var_t str; bool saved = false; if (!prog_error && image != nullptr) { unsigned w = image->_width; @@ -473,37 +475,43 @@ void cmd_image_save(var_s *self, var_s *) { saved = true; } break; - case kwTYPE_VAR: - array = par_getvar_ptr(); - v_tomatrix(array, h, w); - // x0 x1 x2 (w=3,h=2) - // y0 rgba rgba rgba ypos=0 - // y1 rgba rgba rgba ypos=12 - // - for (unsigned y = 0; y < h; y++) { - unsigned yoffs = (y * w * 4); - for (unsigned x = 0; x < w; x++) { - uint8_t a, r, g, b; - GET_IMAGE_ARGB(image->_image, yoffs + (x * 4), a, r, g, b); - pixel_t px = v_get_argb_px(a, r, g, b); - unsigned pos = y * w + x; - v_setint(v_elem(array, pos), px); - } - } - saved = true; + case kwTYPE_STR: + par_getstr(&str); + if (!prog_error && + !encode_png_file(str.v.p.ptr, image->_image, w, h)) { + saved = true; + } + v_free(&str); break; default: - v_init(&var); - eval(&var); - if (var.type == V_STR && !prog_error && - !lodepng_encode32_file(var.v.p.ptr, image->_image, w, h)) { + var = par_getvar_ptr(); + if (var->type == V_STR && !prog_error && + !encode_png_file(var->v.p.ptr, image->_image, w, h)) { saved = true; - } - v_free(&var); - break; + } else if (!prog_error) { + u_int32_t offsetLeft = map_get_int(self, IMG_OFFSET_LEFT, -1); + u_int32_t offsetTop = map_get_int(self, IMG_OFFSET_TOP, -1); + u_int32_t wClip = map_get_int(self, IMG_WIDTH, -1); + u_int32_t hClip = map_get_int(self, IMG_HEIGHT, -1); + v_tomatrix(var, hClip, wClip); + // x0 x1 x2 (w=3,h=2) + // y0 rgba rgba rgba ypos=0 + // y1 rgba rgba rgba ypos=12 + // + for (unsigned y = offsetTop; y < offsetTop + hClip; y++) { + unsigned yoffs = (y * w * 4); + for (unsigned x = offsetLeft; x < offsetLeft + wClip; x++) { + uint8_t a, r, g, b; + GET_IMAGE_ARGB(image->_image, yoffs + (x * 4), a, r, g, b); + pixel_t px = v_get_argb_px(a, r, g, b); + unsigned pos = (y - offsetTop ) * wClip + (x - offsetLeft); + v_setint(v_elem(var, pos), px); + } + } + saved = true; + } } } - if (!saved) { err_throw(ERR_IMAGE_SAVE); } @@ -512,7 +520,7 @@ void cmd_image_save(var_s *self, var_s *) { // // Reduces the size of the image -// arguments: left, top, right, bottom +// arguments: left, top, width, height // // png.clip(10, 10, 10, 10) // @@ -521,12 +529,12 @@ void cmd_image_clip(var_s *self, var_s *) { int bid = map_get_int(self, IMG_BID, -1); if (bid != -1) { ImageBuffer *image = get_image((unsigned)bid); - var_int_t left, top, right, bottom; - if (image != nullptr && par_massget("iiii", &left, &top, &right, &bottom)) { + var_int_t left, top, width, heigth; + if (image != nullptr && par_massget("iiii", &left, &top, &width, &heigth)) { map_set_int(self, IMG_OFFSET_LEFT, left); map_set_int(self, IMG_OFFSET_TOP, top); - map_set_int(self, IMG_WIDTH, right); - map_set_int(self, IMG_HEIGHT, bottom); + map_set_int(self, IMG_WIDTH, width); + map_set_int(self, IMG_HEIGHT, heigth); } } } From 031521b7eea20cc35f18adf15cad2c2ac67ab472 Mon Sep 17 00:00:00 2001 From: Joerg Siebenmorgen Date: Fri, 1 Dec 2023 15:00:26 +0100 Subject: [PATCH 2/5] Bugfix for image.clip() and image.save() --- src/ui/image.cpp | 51 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/ui/image.cpp b/src/ui/image.cpp index d01d08f1..70d92a07 100644 --- a/src/ui/image.cpp +++ b/src/ui/image.cpp @@ -489,24 +489,35 @@ void cmd_image_save(var_s *self, var_s *) { !encode_png_file(var->v.p.ptr, image->_image, w, h)) { saved = true; } else if (!prog_error) { - u_int32_t offsetLeft = map_get_int(self, IMG_OFFSET_LEFT, -1); - u_int32_t offsetTop = map_get_int(self, IMG_OFFSET_TOP, -1); - u_int32_t wClip = map_get_int(self, IMG_WIDTH, -1); - u_int32_t hClip = map_get_int(self, IMG_HEIGHT, -1); - v_tomatrix(var, hClip, wClip); - // x0 x1 x2 (w=3,h=2) - // y0 rgba rgba rgba ypos=0 - // y1 rgba rgba rgba ypos=12 - // - for (unsigned y = offsetTop; y < offsetTop + hClip; y++) { - unsigned yoffs = (y * w * 4); - for (unsigned x = offsetLeft; x < offsetLeft + wClip; x++) { - uint8_t a, r, g, b; - GET_IMAGE_ARGB(image->_image, yoffs + (x * 4), a, r, g, b); - pixel_t px = v_get_argb_px(a, r, g, b); - unsigned pos = (y - offsetTop ) * wClip + (x - offsetLeft); - v_setint(v_elem(var, pos), px); + uint32_t offsetLeft = map_get_int(self, IMG_OFFSET_LEFT, 0); + uint32_t offsetTop = map_get_int(self, IMG_OFFSET_TOP, 0); + uint32_t wClip = map_get_int(self, IMG_WIDTH, w); + uint32_t hClip = map_get_int(self, IMG_HEIGHT, h); + + if (offsetTop < h && offsetLeft < w) { + if (offsetTop + hClip > h) { + hClip = h - offsetTop; } + if (offsetLeft + wClip > w) { + wClip = w - offsetLeft; + } + v_tomatrix(var, hClip, wClip); + // x0 x1 x2 (w=3,h=2) + // y0 rgba rgba rgba ypos=0 + // y1 rgba rgba rgba ypos=12 + // + for (unsigned y = offsetTop; y < offsetTop + hClip; y++) { + unsigned yoffs = (y * w * 4); + for (unsigned x = offsetLeft; x < offsetLeft + wClip; x++) { + uint8_t a, r, g, b; + GET_IMAGE_ARGB(image->_image, yoffs + (x * 4), a, r, g, b); + pixel_t px = v_get_argb_px(a, r, g, b); + unsigned pos = (y - offsetTop ) * wClip + (x - offsetLeft); + v_setint(v_elem(var, pos), px); + } + } + } else { + v_tomatrix(var, hClip, wClip); } saved = true; } @@ -531,6 +542,12 @@ void cmd_image_clip(var_s *self, var_s *) { ImageBuffer *image = get_image((unsigned)bid); var_int_t left, top, width, heigth; if (image != nullptr && par_massget("iiii", &left, &top, &width, &heigth)) { + if (left < 0) { + left = 0; + } + if (top < 0) { + top = 0; + } map_set_int(self, IMG_OFFSET_LEFT, left); map_set_int(self, IMG_OFFSET_TOP, top); map_set_int(self, IMG_WIDTH, width); From 310c3eda3997f1c6faad98738f7306072957c598 Mon Sep 17 00:00:00 2001 From: Joerg Siebenmorgen Date: Fri, 1 Dec 2023 15:13:19 +0100 Subject: [PATCH 3/5] Bugfix for wrong serial port number. --- src/common/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/file.c b/src/common/file.c index e9b5bdaa..b486ab16 100644 --- a/src/common/file.c +++ b/src/common/file.c @@ -183,7 +183,7 @@ int dev_fopen(int sb_handle, const char *name, int flags) { } if (strncmp(f->name, "COM", 3) == 0) { f->type = ft_serial_port; - f->port = f->name[3] - '1'; + f->port = f->name[3] - '0'; if (f->port < 0) { f->port = 10; } From c9ff3267a0f7674214877cf7d3f50dfa8499194b Mon Sep 17 00:00:00 2001 From: Joerg Siebenmorgen <82510480+Joe7M@users.noreply.github.com> Date: Mon, 8 Jan 2024 22:24:35 +0100 Subject: [PATCH 4/5] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1c0efe41..6653506f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Initial setup on linux $ sudo apt-get install git autotools-dev automake gcc g++ libsdl2-dev libfreetype6-dev libfontconfig1-dev xxd $ git clone https://github.com/smallbasic/SmallBASIC.git $ cd SmallBASIC + $ git submodule update --init $ sh autogen.sh ``` Build in linux From 5eca11d07f734b62d568bc10d82e7a4d49bba2f0 Mon Sep 17 00:00:00 2001 From: Joerg Siebenmorgen Date: Sat, 13 Jan 2024 21:09:48 +0100 Subject: [PATCH 5/5] Serial port improvements. --- src/common/file.c | 61 +++++++++++++--------------- src/common/fs_serial.c | 91 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 113 insertions(+), 39 deletions(-) diff --git a/src/common/file.c b/src/common/file.c index b486ab16..7e47c49d 100644 --- a/src/common/file.c +++ b/src/common/file.c @@ -112,34 +112,6 @@ int dev_fstatus(int handle) { return (f->handle != -1); } -/** - * terminal speed - * select the correct system constant - */ -#if USE_TERM_IO -int select_unix_serial_speed(int n) { - switch (n) { - case 300: - return B300; - case 600: - return B600; - case 1200: - return B1200; - case 2400: - return B2400; - case 4800: - return B4800; - case 9600: - return B9600; - case 19200: - return B19200; - case 38400: - return B38400; - } - return B9600; -} -#endif - /** * opens a file * @@ -183,19 +155,14 @@ int dev_fopen(int sb_handle, const char *name, int flags) { } if (strncmp(f->name, "COM", 3) == 0) { f->type = ft_serial_port; + f->devspeed = 9600; f->port = f->name[3] - '0'; if (f->port < 0) { f->port = 10; } if (strlen(f->name) > 5) { f->devspeed = xstrtol(f->name + 5); - } else { - f->devspeed = 9600; } - -#if USE_TERM_IO - f->devspeed = select_unix_serial_speed(f->devspeed); -#endif } else if (strncmp(f->name, "SOCL:", 5) == 0) { f->type = ft_socket_client; } else if (strncasecmp(f->name, "HTTP:", 5) == 0) { @@ -217,6 +184,32 @@ int dev_fopen(int sb_handle, const char *name, int flags) { strcpy(f->name, "SDIN:"); f->type = ft_stream; } + } else if (strncmp(f->name, "/dev/tty", 8) == 0) { + f->type = ft_serial_port; + f->devspeed = 9600; + const char *ptrSpeed = strchr(f->name, ':'); + if(ptrSpeed) { + if(strlen(ptrSpeed) > 1) { + f->devspeed = xstrtol(ptrSpeed + 1); + } + f->name[ptrSpeed - f->name] = '\0'; + } + } + if (f->name[5] == ':') { + for (int i = 0; i < 4; i++) { + f->name[i] = to_upper(f->name[i]); + } + if (strncmp(f->name, "COM", 3) == 0) { + f->type = ft_serial_port; + f->devspeed = 9600; + f->port = (f->name[3] - '0') * 10 + (f->name[4] - '0'); + if (f->port < 0) { + f->port = 10; + } + if (strlen(f->name) > 6) { + f->devspeed = xstrtol(f->name + 6); + } + } } } // device diff --git a/src/common/fs_serial.c b/src/common/fs_serial.c index d0f45520..0d62ca97 100644 --- a/src/common/fs_serial.c +++ b/src/common/fs_serial.c @@ -20,13 +20,75 @@ #include #include +/** + * terminal speed + * select the correct system constant + */ +long select_unix_serial_speed(long n) { + switch (n) { + case 300: + return B300; + case 600: + return B600; + case 1200: + return B1200; + case 2400: + return B2400; + case 4800: + return B4800; + case 9600: + return B9600; + case 19200: + return B19200; + case 38400: + return B38400; + // extra baud rates (but not posix) + case 57600: + return B57600; + case 115200: + return B115200; + case 230400: + return B230400; + case 460800: + return B460800; + case 500000: + return B500000; + case 576000: + return B576000; + case 921600: + return B921600; + case 1000000: + return B1000000; + case 1152000: + return B1152000; + case 1500000: + return B1500000; + case 2000000: + return B2000000; + case 2500000: + return B2500000; + case 3000000: + return B3000000; + case 3500000: + return B3500000; + case 4000000: + return B4000000; + } + return B9600; +} + int serial_open(dev_file_t *f) { - sprintf(f->name, "/dev/ttyS%d", f->port); + if (strncmp(f->name, "COM", 3) == 0) { + sprintf(f->name, "/dev/ttyS%d", f->port); + } f->handle = open(f->name, O_RDWR | O_NOCTTY); if (f->handle < 0) { err_file((f->last_error = errno)); } + + f->devspeed = select_unix_serial_speed(f->devspeed); + // save current port settings tcgetattr(f->handle, &f->oldtio); bzero(&f->newtio, sizeof(f->newtio)); @@ -83,15 +145,20 @@ int serial_open(dev_file_t *f) { HANDLE hCom; DWORD dwer; - sprintf(f->name, "COM%d", f->port); + if (strncmp(f->name, "COM", 3) != 0) { + rt_raise("SERIALFS: Linux serial port was specified. Use COM instead."); + } + // Bug when opening COM-Port > 9: https://support.microsoft.com/en-us/topic/howto-specify-serial-ports-larger-than-com9-db9078a5-b7b6-bf00-240f-f749ebfd913e + sprintf(f->name, "\\\\.\\COM%d", f->port); + hCom = CreateFile(f->name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hCom == INVALID_HANDLE_VALUE) { dwer = GetLastError(); if (dwer != 5) { - rt_raise("SERIALFS: CreateFile() failed (%d)", dwer); + rt_raise("SERIALFS: CreateFile() failed (Error %d)", dwer); } else { rt_raise("SERIALFS: ACCESS DENIED"); } @@ -99,17 +166,31 @@ int serial_open(dev_file_t *f) { } if (!GetCommState(hCom, &dcb)) { - rt_raise("SERIALFS: GetCommState() failed (%d)", GetLastError()); + rt_raise("SERIALFS: GetCommState() failed (Error %d)", GetLastError()); return 0; } + // Default settings from Putty + dcb.fBinary = TRUE; + dcb.fDtrControl = DTR_CONTROL_ENABLE; // This is needed for Raspberry Pi PICO + dcb.fDsrSensitivity = FALSE; + dcb.fTXContinueOnXoff = FALSE; + dcb.fOutX = FALSE; + dcb.fInX = FALSE; + dcb.fErrorChar = FALSE; + dcb.fNull = FALSE; + dcb.fRtsControl = RTS_CONTROL_ENABLE; + dcb.fAbortOnError = FALSE; + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = FALSE; + // Settings SmallBASIC dcb.BaudRate = f->devspeed; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (!SetCommState(hCom, &dcb)) { - rt_raise("SERIALFS: SetCommState() failed (%d)", GetLastError()); + rt_raise("SERIALFS: SetCommState() failed (Error %d)", GetLastError()); return 0; }