Skip to content

Commit

Permalink
adding MLX90394 + app framework
Browse files Browse the repository at this point in the history
  • Loading branch information
karelv committed Sep 6, 2024
1 parent 3d8395e commit 6fcaf79
Show file tree
Hide file tree
Showing 30 changed files with 2,256 additions and 104 deletions.
115 changes: 115 additions & 0 deletions i2c-stick-arduino/app.cpp.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#include "{{app.src_name}}_app.h"
#include "i2c_stick.h"
#include "i2c_stick_dispatcher.h"
#include "i2c_stick_cmd.h"
#include "i2c_stick_hal.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


// Set here the slave address(SA) which the application should use by default
// in the Configure Application command (ca), you can change the SA to be used by this app.
static uint8_t g_sa = 0x05;


uint8_t
cmd_{{app.function_id}}_app_begin(uint8_t channel_mask)
{
uint8_t ok = 1;
char buf[32];

// configure the slave for the {{app.name}} app (and set ok=0 in case it fails).

if (ok)
{
send_answer_chunk(channel_mask, ":", 0);
itoa(APP_{{app.name}}_ID, buf, 10);
send_answer_chunk(channel_mask, buf, 0);
send_answer_chunk(channel_mask, ":OK", 1);
}
else // when failed..
{
send_answer_chunk(channel_mask, ":", 0);
itoa(APP_{{app.name}}_ID, buf, 10);
send_answer_chunk(channel_mask, buf, 0);
send_answer_chunk(channel_mask, ":FAILED (app not started)", 1);
return APP_NONE;
}


// potentially disable the mlx90394 for emitting results in the continuous mode.

return APP_{{app.name}}_ID;
}


void
handle_{{app.function_id}}_app(uint8_t channel_mask)
{
static uint32_t prev_time = hal_get_millis();
char buf[32]; memset(buf, 0, sizeof(buf));
if (hal_get_millis() - prev_time > 100) /* this is an example code to check-in every 100ms with the sensor. */
{
// reset the timer
prev_time = hal_get_millis();

// all apps responds back to the communication channel on its own, therefore we start it ALWAYS with a hastag '#'
// the format is:
// #<app-id>:<value0>,<value1>,...,<valuen>
// value can be integer format or floating point format.
send_answer_chunk(channel_mask, "#", 0);
itoa(APP_{{app.name}}_ID, buf, 10);
send_answer_chunk(channel_mask, buf, 0);

// read sensor values
int raw_value = 1234;

// process sensor values as one would do in the application.
float processed_value = raw_value;
processed_value /= 100;


// report the results
send_answer_chunk(channel_mask, ":", 0); // remember the first separator is ':', after it is only ','!
itoa(raw_value, buf, 10); // note: replace
send_answer_chunk(channel_mask, buf, 0);

send_answer_chunk(channel_mask, ",", 0);
sprintf(buf, "%5.3f", processed_value);
send_answer_chunk(channel_mask, buf, 1); // only the last line will terminate the communication line.

}

}


uint8_t
cmd_{{app.function_id}}_app_end(uint8_t channel_mask)
{
char buf[32];
send_answer_chunk(channel_mask, ":ENDING:", 0);
itoa(APP_{{app.name}}_ID, buf, 10);
send_answer_chunk(channel_mask, buf, 0);

return APP_NONE;
}


void
cmd_{{app.function_id}}_ca(uint8_t channel_mask, const char *input)
{
char buf[16]; memset(buf, 0, sizeof(buf));
send_answer_chunk(channel_mask, "ca:", 0);
itoa(APP_{{app.name}}_ID, buf, 10);
send_answer_chunk(channel_mask, buf, 0);
send_answer_chunk(channel_mask, ":SA=", 0);
uint8_to_hex(buf, g_sa);
send_answer_chunk(channel_mask, buf, 1);
}


void
cmd_{{app.function_id}}_ca_write(uint8_t channel_mask, const char *input)
{
}
20 changes: 20 additions & 0 deletions i2c-stick-arduino/app.h.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef _{{app.name}}_CMD_
#define _{{app.name}}_CMD_

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

uint8_t cmd_{{app.function_id}}_app_begin(uint8_t channel_mask);
void handle_{{app.function_id}}_app(uint8_t channel_mask);
uint8_t cmd_{{app.function_id}}_app_end(uint8_t channel_mask);
void cmd_{{app.function_id}}_ca(uint8_t channel_mask, const char *input);
void cmd_{{app.function_id}}_ca_write(uint8_t channel_mask, const char *input);

#ifdef __cplusplus
}
#endif

#endif
129 changes: 125 additions & 4 deletions i2c-stick-arduino/dodo.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,43 @@
# remove the disabled drivers
context['drivers'] = [driver for driver in context['drivers'] if driver['disable'] == 0]

for index, driver in enumerate(context['drivers']):
driver['id'] = index + 1


# APPLICATIONS
for app in context['applications']:
if 'disable' not in app:
app['disable'] = 0

# Arduino compiles all cpp files in the directory; rename to <ori>.disable
for app in context['applications']:
if app['disable']:
files = list(Path(".").glob(app['src_name'] + "_*.cpp")) + list(Path(".").glob(app['src_name'] + "_*.h"))
for file in files:
shutil.move(file, str(file) + ".disable")

# undo: Arduino compiles all cpp files in the directory; rename to <ori>.disable
for app in context['applications']:
if app['disable'] == 0:
files = list(Path(".").glob(app['src_name'] + "_*.disable"))
for file in files:
shutil.move(file, str(file).replace(".disable", ""))

# remove the disabled applications
context['applications'] = [app for app in context['applications'] if app['disable'] == 0]

for index, app in enumerate(context['applications']):
app['id'] = index + 1


# remove the disabled boards
for board in context['boards']:
if 'disable' not in board:
board['disable'] = 0

context['boards'] = [board for board in context['boards'] if board['disable'] == 0]

for index, driver in enumerate(context['drivers']):
driver['id'] = index + 1


arduino_add_url = " ".join(["--additional-urls {}".format(x) for x in context['board_manager']['additional-urls']])

ARDUINO_CLI = os.path.join('tools', 'arduino-cli' + Path(sys.executable).suffix)
Expand Down Expand Up @@ -474,6 +501,8 @@ def do_upload(board_cfg, port):
if p.vid == vid:
if p.pid == pid:
filtered_ports.append(p)
if len(filtered_ports) <= 0:
return "echo no compatible comport found"
port = filtered_ports[0].name

if method == 'arduino-cli':
Expand Down Expand Up @@ -684,6 +713,98 @@ def do_add_driver(driver, src_name, function_id, sa_list):
}


def task_add_app():
"""Add a templated entry for a new driver for a sensor to the framework"""

def do_generate(template, output, data):
yamlinclude.YamlIncludeConstructor.add_to_loader_class(loader_class=yaml.FullLoader, base_dir=this_dir)
loader = jinja2.FileSystemLoader(this_dir)

env = jinja2.Environment(
loader=loader,
autoescape=jinja2.select_autoescape()
)

tpl = env.get_template(template)
print("output:", output)
with open(output, 'w') as output_f:
output_f.write(tpl.render(data))
output_f.write("\n")

def do_add_app(app, src_name, function_id):
if app is None:
print("Please provide parameters about the application")
print("Run 'doit info add-app' for more information")
return
if src_name is None:
src_name = app.lower()
if function_id is None:
if src_name.startswith('mlx'):
function_id = src_name[3:]
if function_id is None:
print("Please provide parameters about the application")
print("Run 'doit info add-app' for more information")
return

app_data = {'app': {
'name': app,
'src_name': src_name,
'function_id': function_id
},
}

for appli in context['applications']:
if appli['name'] == app:
print("ERROR: App '{}' already exists;".format(appli))
return

do_generate("app.h.jinja2", "{}_app.h".format(src_name), app_data)
do_generate("app.cpp.jinja2", "{}_app.cpp".format(src_name), app_data)
# now update the context.yaml file!

yaml_file = src_name+"_application.yaml"
print("output:", yaml_file)
with open(yaml_file, 'w') as output_f:
output_f.write(yaml.dump({
'name': app,
'src_name': src_name,
'function_id': function_id,
}))
output_f.write("\n")

# and finally re-generate the dispatcher for the newly added driver.
# from doit.doit_cmd import DoitMain
# DoitMain().run(["--always", "generate:i2c_stick_dispatcher.h"])
# DoitMain().run(["--always", "generate:i2c_stick_dispatcher.cpp"])

return {
'basename': 'add-app',
'actions': [(do_add_app,)],
'file_dep': ['app.h.jinja2', 'app.cpp.jinja2'],
'params': [
{'name': 'app',
'short': 'd',
'long': 'app',
'type': str,
'default': None,
},
{'name': 'src_name',
'short': 's',
'long': 'src_name',
'type': str,
'default': None,
},
{'name': 'function_id',
'short': 'f',
'long': 'function_id',
'type': str,
'default': None,
},
],
'uptodate': [False], # make to run the task always
'verbosity': 2,
}

def task_dist():
def make_dist_dir():
if not Path("../dist").is_dir():
Expand Down
9 changes: 5 additions & 4 deletions i2c-stick-arduino/driver_cmd.cpp.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ cmd_{{driver.function_id}}_mw(uint8_t sa, uint16_t *mem_data, uint16_t mem_start

void
cmd_{{driver.function_id}}_is(uint8_t sa, uint8_t *is_ok, char const **error_message)
{ // function to call prior any init, only to check is the connected slave IS a MLX90614.
{ // function to call prior any init, only to check is the connected slave IS a {{driver.name}}.
uint16_t value;
*is_ok = 1; // be optimistic!

Expand All @@ -436,10 +436,11 @@ cmd_{{driver.function_id}}_is(uint8_t sa, uint8_t *is_ok, char const **error_mes

// remember there is no communication initiated yet...

// in this ecample below for MLX90614 we check if the EEPROM reads the slave address at address 0x2E...
// in this example below we check if the EEPROM reads the slave address at address 0x2E,
// and check if that fits with the currently SA in use!

// MLX90614_SMBusInit();
// if (MLX90614_SMBusRead(sa, 0x2E, &value) < 0)
// {{driver.name}}_I2CInit();
// if ({{driver.name}}_I2cRead(sa, 0x2E, &value) < 0)
{
*error_message = {{driver.name}}_ERROR_COMMUNICATION;
*is_ok = 0;
Expand Down
14 changes: 3 additions & 11 deletions i2c-stick-arduino/i2c-stick-arduino.ino
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ hal_write_pin(uint8_t pin, uint8_t state)


uint8_t
hal_read_pin(uint8_t pin, uint8_t pullup)
hal_read_pin(uint8_t pin)
{
pinMode(pin, pullup ? INPUT_PULLUP : INPUT);
pinMode(pin, INPUT);
return digitalRead(pin);
}

Expand Down Expand Up @@ -354,7 +354,7 @@ loop()
{
handle_continuous_mode();
}
handle_applications();
handle_applications(g_channel_mask);
}


Expand Down Expand Up @@ -399,14 +399,6 @@ void msc_flush_cb (void)
#endif // ENABLE_USB_MSC




void
handle_applications()
{
//uint8_t channel_mask = 0xFF;
}

uint16_t
int_uart()
{
Expand Down
Loading

0 comments on commit 6fcaf79

Please sign in to comment.