diff --git a/src/html/web_portal.html b/src/html/web_portal.html
index 593b82a..c475977 100644
--- a/src/html/web_portal.html
+++ b/src/html/web_portal.html
@@ -111,6 +111,7 @@
+
diff --git a/src/jm_science_scale.c b/src/jm_science_scale.c
new file mode 100644
index 0000000..8e98df7
--- /dev/null
+++ b/src/jm_science_scale.c
@@ -0,0 +1,109 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "hardware/uart.h"
+#include "configuration.h"
+#include "scale.h"
+#include "app.h"
+
+
+typedef union {
+ struct __attribute__((__packed__)){
+ char header;
+ char _space;
+ char stable_state;
+ char symbol;
+ char weighing_data[9];
+ char _space2;
+ char weighing_unit[3];
+ char terminator[2];
+ };
+ char bytes[19];
+} jm_science_frame_data_format_t;
+
+
+const static char JM_SCIENCE_FRAME_HEADER = 'E';
+
+
+// Forward declaration
+void _jm_science_scale_listener_task(void *p);
+static void force_zero();
+
+extern scale_config_t scale_config;
+
+// Instance of the scale handle for JM Sciense FA series
+scale_handle_t jm_science_scale_handle = {
+ .read_loop_task = _jm_science_scale_listener_task,
+ .force_zero = force_zero,
+};
+
+
+static float _decode_measurement_msg(jm_science_frame_data_format_t * frame) {
+ // decode sign
+ int sign = 1;
+ if (frame->symbol == '-') {
+ sign = -1;
+ }
+
+ // Decode weight information
+ char *endptr;
+ float weight = strtof(frame->weighing_data, &endptr);
+
+ if( endptr == frame->weighing_data ) {
+ // Conversion failed
+ return nanf(frame->weighing_data);
+ }
+
+ weight *= sign;
+
+ return weight;
+}
+
+
+void _jm_science_scale_listener_task(void *p) {
+ jm_science_frame_data_format_t frame;
+ uint8_t byte_idx = 0;
+
+ while (true) {
+ // Read all data
+ while (uart_is_readable(SCALE_UART)) {
+ char ch = uart_getc(SCALE_UART);
+
+ // Determine if the frame header is received
+ // If a header is received then we should reset the decode sequence
+ if (ch == JM_SCIENCE_FRAME_HEADER) {
+ byte_idx = 0;
+ }
+
+ frame.bytes[byte_idx++] = ch;
+
+ // If we have received 17 bytes then we can decode the message
+ if (byte_idx == sizeof(jm_science_frame_data_format_t)) {
+ // Data is ready, send to decode
+ scale_config.current_scale_measurement = _decode_measurement_msg(&frame);
+
+ // Signal the data is ready
+ if (scale_config.scale_measurement_ready) {
+ xSemaphoreGive(scale_config.scale_measurement_ready);
+ }
+
+ // Reset buffer index to avoid overflow
+ byte_idx = 0;
+ }
+ }
+
+ vTaskDelay(pdMS_TO_TICKS(20));
+ }
+}
+
+
+static void force_zero() {
+ // Unsupported
+}
+
diff --git a/src/scale.c b/src/scale.c
index 5436c8f..f566af6 100644
--- a/src/scale.c
+++ b/src/scale.c
@@ -16,6 +16,8 @@ extern scale_handle_t and_fxi_scale_handle;
extern scale_handle_t steinberg_scale_handle;
extern scale_handle_t ussolid_scale_handle;
extern scale_handle_t gng_scale_handle;
+extern scale_handle_t jm_science_scale_handle;
+
scale_config_t scale_config;
@@ -35,14 +37,19 @@ void set_scale_driver(scale_driver_t scale_driver) {
scale_config.scale_handle = &steinberg_scale_handle;
break;
}
+ case SCALE_DRIVER_GNG_JJB:
+ {
+ scale_config.scale_handle = &gng_scale_handle;
+ break;
+ }
case SCALE_DRIVER_USSOLID_JFDBS:
{
scale_config.scale_handle = &ussolid_scale_handle;
break;
}
- case SCALE_DRIVER_GNG_JJB:
+ case SCALE_DRIVER_JM_SCIENCE:
{
- scale_config.scale_handle = &gng_scale_handle;
+ scale_config.scale_handle = &jm_science_scale_handle;
break;
}
default:
@@ -88,6 +95,8 @@ const char * get_scale_driver_string() {
case SCALE_DRIVER_GNG_JJB:
scale_driver_string = "GNG JJB";
break;
+ case SCALE_DRIVER_JM_SCIENCE:
+ scale_driver_string = "JM SCIENCE";
default:
break;
}
diff --git a/src/scale.h b/src/scale.h
index e66e881..14f0a68 100644
--- a/src/scale.h
+++ b/src/scale.h
@@ -31,6 +31,7 @@ typedef enum {
SCALE_DRIVER_STEINBERG_SBS = 1,
SCALE_DRIVER_GNG_JJB = 2,
SCALE_DRIVER_USSOLID_JFDBS = 3,
+ SCALE_DRIVER_JM_SCIENCE = 4,
} scale_driver_t;