Added multiple uBASIC program objects to stm32f4xx example port. (#995)

This commit is contained in:
Steve Karg
2025-05-19 14:57:43 -05:00
committed by GitHub
parent 62bf8274f7
commit b5b2fd5b7b
9 changed files with 218 additions and 80 deletions
+87 -44
View File
@@ -8,37 +8,15 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "bacnet/basic/object/program.h"
#include "bacnet/basic/program/ubasic/ubasic.h"
#include "bacnet/basic/sys/mstimer.h"
/* uBASIC-Plus program object */
static struct ubasic_data UBASIC_DATA = { 0 };
/* timer for the task */
static struct mstimer UBASIC_Timer;
static uint32_t UBASIC_Instance = 0;
static const char *UBASIC_Program =
/* program listing with either \0, \n, or ';' at the end of each line.
note: indentation is not required */
"println 'Demo - BACnet & GPIO';"
"bac_create(0, 1, 'ADC-1');"
"bac_create(0, 2, 'ADC-2');"
"bac_create(4, 1, 'LED-1');"
"bac_create(4, 2, 'LED-2');"
":startover;"
" a = aread(1);"
" c = avgw(a, c, 10);"
" bac_write(0, 1, 85, c);"
" b = aread(2);"
" d = avgw(b, d, 10);"
" bac_write(0, 2, 85, d);"
" h = bac_read(4, 1, 85);"
" dwrite(1, (h % 2));"
" i = bac_read(4, 2, 85);"
" dwrite(2, (i % 2));"
" sleep (0.2);"
"goto startover;"
"end;";
/* context structure */
/**
* @brief Load the program into the uBASIC interpreter
@@ -47,9 +25,14 @@ static const char *UBASIC_Program =
*/
static int Program_Load(void *context)
{
if (!context) {
return -1;
}
struct ubasic_data *data = (struct ubasic_data *)context;
ubasic_load_program(data, UBASIC_Program);
ubasic_load_program(data, NULL);
(void)ubasic_program_location(data);
return 0;
}
@@ -61,6 +44,9 @@ static int Program_Load(void *context)
*/
static int Program_Run(void *context)
{
if (!context) {
return -1;
}
struct ubasic_data *data = (struct ubasic_data *)context;
int result = 0;
@@ -68,6 +54,7 @@ static int Program_Run(void *context)
if (result <= 0) {
return -1;
}
(void)ubasic_program_location(data);
return 0;
}
@@ -79,9 +66,12 @@ static int Program_Run(void *context)
*/
static int Program_Halt(void *context)
{
if (!context) {
return -1;
}
struct ubasic_data *data = (struct ubasic_data *)context;
data->status.bit.isRunning = 0;
ubasic_halt_program(data);
return 0;
}
@@ -93,10 +83,14 @@ static int Program_Halt(void *context)
*/
static int Program_Restart(void *context)
{
if (!context) {
return -1;
}
struct ubasic_data *data = (struct ubasic_data *)context;
ubasic_clear_variables(data);
ubasic_load_program(data, UBASIC_Program);
ubasic_load_program(data, NULL);
(void)ubasic_program_location(data);
return 0;
}
@@ -108,9 +102,13 @@ static int Program_Restart(void *context)
*/
static int Program_Unload(void *context)
{
if (!context) {
return -1;
}
struct ubasic_data *data = (struct ubasic_data *)context;
ubasic_clear_variables(data);
return 0;
}
@@ -119,29 +117,74 @@ static int Program_Unload(void *context)
*/
void Program_UBASIC_Task(void)
{
size_t index, max_index;
uint32_t instance;
if (mstimer_expired(&UBASIC_Timer)) {
mstimer_reset(&UBASIC_Timer);
Program_Timer(UBASIC_Instance, mstimer_interval(&UBASIC_Timer));
max_index = Program_Count();
for (index = 0; index < max_index; index++) {
instance = Program_Index_To_Instance(index);
Program_Timer(instance, mstimer_interval(&UBASIC_Timer));
}
}
}
/**
* @brief Initialize the uBASIC program object
* @param instance Instance number of the program object
* @brief Create one uBASIC program object
* @param requested_instance Instance number of the program object
* @param context Pointer to the uBASIC data structure
* @param program Pointer to the uBASIC program
* @return 0 on success, non-zero on error
*/
void Program_UBASIC_Init(uint32_t instance)
int Program_UBASIC_Create(
uint32_t requested_instance,
struct ubasic_data *context,
const char *program)
{
ubasic_port_init(&UBASIC_DATA);
UBASIC_Instance = Program_Create(instance);
Program_Context_Set(UBASIC_Instance, &UBASIC_DATA);
Program_Load_Set(UBASIC_Instance, Program_Load);
Program_Run_Set(UBASIC_Instance, Program_Run);
Program_Halt_Set(UBASIC_Instance, Program_Halt);
Program_Restart_Set(UBASIC_Instance, Program_Restart);
Program_Unload_Set(UBASIC_Instance, Program_Unload);
/* auto-run the program */
Program_Change_Set(UBASIC_Instance, PROGRAM_REQUEST_RUN);
/* start the cyclic 10ms run timer for the program object */
mstimer_set(&UBASIC_Timer, 10);
uint32_t instance = 0;
if (!context) {
return -1;
}
if (Program_Valid_Instance(requested_instance)) {
instance = requested_instance;
if (program) {
context->program = program;
}
Program_Change_Set(instance, PROGRAM_REQUEST_RESTART);
} else {
instance = Program_Create(requested_instance);
if (instance == BACNET_MAX_INSTANCE) {
return -1;
}
if (program) {
context->program = program;
} else {
context->program = "end;";
}
Program_Context_Set(instance, context);
Program_Load_Set(instance, Program_Load);
Program_Run_Set(instance, Program_Run);
Program_Halt_Set(instance, Program_Halt);
Program_Restart_Set(instance, Program_Restart);
Program_Unload_Set(instance, Program_Unload);
Program_Location_Set(instance, context->location);
ubasic_port_init(context);
/* auto-run the program */
Program_Change_Set(instance, PROGRAM_REQUEST_RUN);
}
return 0;
}
/**
* @brief Initialize the uBASIC program object
* @param requested_instance Instance number of the program object
* @return 0 on success, non-zero on error
*/
void Program_UBASIC_Init(unsigned long task_ms)
{
/* start the cyclic 10ms run timer for the program object */
mstimer_set(&UBASIC_Timer, task_ms);
}