Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
63 changes: 28 additions & 35 deletions src/common/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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->port = f->name[3] - '1';
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) {
Expand All @@ -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

Expand Down
91 changes: 86 additions & 5 deletions src/common/fs_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,75 @@
#include <sys/select.h>
#include <errno.h>

/**
* 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));
Expand Down Expand Up @@ -83,33 +145,52 @@ 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");
}
return 0;
}

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;
}

Expand Down
93 changes: 59 additions & 34 deletions src/ui/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -473,37 +475,54 @@ 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) {
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;
}
}
}

if (!saved) {
err_throw(ERR_IMAGE_SAVE);
}
Expand All @@ -512,7 +531,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)
//
Expand All @@ -521,12 +540,18 @@ 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)) {
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, right);
map_set_int(self, IMG_HEIGHT, bottom);
map_set_int(self, IMG_WIDTH, width);
map_set_int(self, IMG_HEIGHT, heigth);
}
}
}
Expand Down