diff --git a/build/devices/esp32/targets/m5stick_c/host/provider.js b/build/devices/esp32/targets/m5stick_c/host/provider.js
index 322e03b724..ea42177d89 100644
--- a/build/devices/esp32/targets/m5stick_c/host/provider.js
+++ b/build/devices/esp32/targets/m5stick_c/host/provider.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Moddable Tech, Inc.
+ * Copyright (c) 2021-2026 Moddable Tech, Inc. ,Satoshi Tanaka
*
* This file is part of the Moddable SDK Runtime.
*
@@ -27,6 +27,11 @@ import PWM from "embedded:io/pwm";
import Serial from "embedded:io/serial";
import SMBus from "embedded:io/smbus";
import SPI from "embedded:io/spi";
+import PulseWidth from "embedded:io/pulsewidth";
+import AXP192 from "embedded:peripheral/Power/axp192";
+import SH200Q from "embedded:sensor/Accelerometer-Gyroscope/SH200Q";
+import MPU6886 from "embedded:sensor/Accelerometer-Gyroscope/MPU6886";
+import RTC from "embedded:RTC/BM8563";
const device = {
I2C: {
@@ -68,12 +73,95 @@ const device = {
pin: 36
}
},
- io: {Analog, Digital, DigitalBank, I2C, PulseCount, PWM, Serial, SMBus, SPI},
+ io: { Analog, Digital, DigitalBank, I2C, PulseCount, PWM, Serial, SMBus, SPI, PulseWidth },
pin: {
button: 37,
led: 10,
displayDC: 23,
displaySelect: 5
+ },
+ sensor: {
+ IMU: class {
+ constructor(options) {
+ let isMPU6886 = true;
+ let probe;
+ try {
+ probe = new SMBus({
+ ...device.I2C.internal,
+ io: SMBus,
+ hz: 400_000,
+ address: 0x68, // MPU6886
+ });
+ probe.readUint8(0x74);
+ } catch {
+ isMPU6886 = false;
+ } finally {
+ probe?.close();
+ }
+
+ const IMUBase = isMPU6886 ? MPU6886 : SH200Q;
+ const IMUClass = class extends IMUBase {
+ sample() {
+ const result = super.sample();
+ result.accelerometer.x *= -1;
+ result.accelerometer.y *= -1;
+ result.gyroscope.y *= -1;
+ return result;
+ }
+ };
+
+ return new IMUClass({
+ ...options,
+ sensor: {
+ ...device.I2C.internal,
+ io: device.io.SMBus
+ }
+ });
+ }
+ }
+ },
+ peripheral: {
+ Power: class extends AXP192 {
+ constructor(options) {
+ super({
+ ...options,
+ peripheral: {
+ ...device.I2C.internal,
+ io: device.io.SMBus
+ }
+ });
+ this.writeByte(0x10, 0xff); // OLED VPP Enable
+ this.writeByte(0x28, 0xff); // Enable LDO2&LDO3, LED&TFT 3.3V
+ this.writeByte(0x82, 0xff); // Enable all the ADCs
+ this.writeByte(0x33, 0xc0); // Enable Charging, 100mA, 4.2V End at 0.9
+ this.writeByte(0xb8, 0x80); // Enable Colume Counter
+ this.writeByte(0x12, 0x4d); // Enable DC-DC1, OLED VDD, 5B V EXT
+ this.writeByte(0x36, 0x5c); // PEK
+ this.writeByte(0x91, 0xA0); // Set MIC voltage to 2.8V
+ this.writeByte(0x90, 0x02); // gpio0
+ }
+ // value 0 - 100 %
+ set brightness(value) {
+ if (value <= 0)
+ value = 7;
+ else if (value >= 100)
+ value = 15;
+ else
+ value = (value / 100) * 8 + 7;
+ this.writeByte(0x28, (this.readByte(0x28) & 0x0F) | (value << 4));
+ }
+ },
+ RTC: class {
+ constructor(options) {
+ return new RTC({
+ ...options,
+ clock: {
+ ...device.I2C.internal,
+ io: SMBus,
+ },
+ });
+ }
+ },
}
};
diff --git a/build/devices/esp32/targets/m5stick_c/manifest.json b/build/devices/esp32/targets/m5stick_c/manifest.json
index e2e46af543..cc4576db84 100644
--- a/build/devices/esp32/targets/m5stick_c/manifest.json
+++ b/build/devices/esp32/targets/m5stick_c/manifest.json
@@ -4,19 +4,19 @@
"DEBUGGER_SPEED": "1500000"
},
"include": [
- "$(MODDABLE)/modules/drivers/st7735/manifest.json",
- "$(MODDABLE)/modules/drivers/axp192/manifest.json",
- "$(MODDABLE)/modules/pins/smbus/manifest.json"
+ "$(MODDABLE)/modules/io/manifest.json",
+ "$(MODULES)/pins/digital/monitor/manifest.json",
+ "$(MODULES)/drivers/st7735/manifest.json",
+ "$(MODULES)/drivers/sensors/mpu6886/manifest.json",
+ "$(MODULES)/drivers/sensors/sh200q/manifest.json",
+ "$(MODULES)/drivers/peripherals/axp192/manifest.json",
+ "$(MODULES)/drivers/peripherals/bm8563/manifest.json"
],
"config": {
"screen": "st7735",
"touch": ""
},
"defines": {
- "i2c": {
- "sda_pin": 21,
- "scl_pin": 22
- },
"spi": {
"mosi_pin": 15,
"sck_pin": 13
@@ -75,19 +75,14 @@
},
"modules": {
"*": [
- "$(MODULES)/pins/digital/monitor/*",
- "$(MODULES)/pins/digital/monitor/esp32/*",
- "$(MODULES)/drivers/mpu6886/*",
- "$(MODULES)/drivers/sh200q/*"
-
+ "../m5stack_fire/m5button"
],
"setup/target": "./setup-target"
},
"preload": [
"monitor",
"setup/target",
- "mpu6886",
- "sh200q"
+ "m5button"
],
"creation": {
"static": 0,
diff --git a/build/devices/esp32/targets/m5stick_c/setup-target.js b/build/devices/esp32/targets/m5stick_c/setup-target.js
index 61e393f38b..df16b44d2d 100644
--- a/build/devices/esp32/targets/m5stick_c/setup-target.js
+++ b/build/devices/esp32/targets/m5stick_c/setup-target.js
@@ -1,183 +1,37 @@
-import Digital from "pins/digital";
-import Monitor from "monitor";
-import AXP192 from "axp192";
-import SH200Q from "sh200q";
-import MPU6886 from "mpu6886";
-import I2C from "pins/i2c";
-import Timer from "timer";
-
+import M5Button from "m5button";
import config from "mc/config";
-
-const state = {
- handleRotation: nop
-};
+import Timer from "timer";
export default function (done) {
- global.button = {
- a: new Monitor({
- pin: 37,
- mode: Digital.InputPullUp,
- edge: Monitor.Rising | Monitor.Falling
- }),
- b: new Monitor({
- pin: 39,
- mode: Digital.InputPullUp,
- edge: Monitor.Rising | Monitor.Falling
- }),
+ globalThis.button = {
+ a: new M5Button(37),
+ b: new M5Button(39)
};
- button.a.onChanged = button.b.onChanged = nop;
-
- global.power = new Power();
-
- state.accelerometerGyro = new IMU();
-
- global.accelerometer = {
- onreading: nop
- }
- global.gyro = {
- onreading: nop
- }
-
- //trace('The Temp:', state.accelerometerGyro.sampleTemp(), '\n');
-
- accelerometer.start = function (frequency) {
- accelerometer.stop();
- state.accelerometerTimerID = Timer.repeat(id => {
- state.accelerometerGyro.configure({
- operation: "accelerometer"
- });
- const sample = state.accelerometerGyro.sample();
- if (sample) {
- sample.y *= -1;
- sample.z *= -1;
- state.handleRotation(sample);
- accelerometer.onreading(sample);
- }
- }, frequency);
- }
-
- gyro.start = function (frequency) {
- gyro.stop();
- state.gyroTimerID = Timer.repeat(id => {
- state.accelerometerGyro.configure({
- operation: "gyroscope"
- });
- const sample = state.accelerometerGyro.sample();
- if (sample) {
- let {
- x,
- y,
- z
- } = sample;
- const temp = x;
- x = y * -1;
- y = temp * -1;
- z *= -1;
- gyro.onreading({
- x,
- y,
- z
- });
- }
- }, frequency);
- }
-
- accelerometer.stop = function () {
- if (undefined !== state.accelerometerTimerID)
- Timer.clear(state.accelerometerTimerID);
- delete state.accelerometerTimerID;
- }
-
- gyro.stop = function () {
- if (undefined !== state.gyroTimerID)
- Timer.clear(state.gyroTimerID);
- delete state.gyroTimerID;
- }
-
- if (config.autorotate && global.Application) {
- state.handleRotation = function (reading) {
- if (Math.abs(reading.y) > Math.abs(reading.x)) {
- if (reading.y < -0.7 && application.rotation != 90) {
- application.rotation = 90;
- } else if (reading.y > 0.7 && application.rotation != 270) {
+ globalThis.power = new device.peripheral.Power();
+
+ if (config.autorotate && globalThis.Application) {
+ const imu = new device.sensor.IMU();
+ Timer.repeat(id => {
+ const sample = imu.sample();
+ const {x, y } = sample.accelerometer;
+ if (Math.abs(y) > Math.abs(x)) {
+ if (y < -0.7 && application.rotation !== 270) {
application.rotation = 270;
+ } else if (y > 0.7 && application.rotation !== 90) {
+ application.rotation = 90;
}
} else {
- if (reading.x < -0.7 && application.rotation != 180) {
+ if (x < -0.7 && application.rotation !== 180) {
application.rotation = 180;
- } else if (reading.x > 0.7 && application.rotation != 0) {
+ } else if (x > 0.7 && application.rotation !== 0) {
application.rotation = 0;
}
}
- }
- accelerometer.start(300);
+ }, 300);
}
done();
}
-function nop() {}
-
-class Power extends AXP192 {
- constructor() {
- super({
- sda: 21,
- scl: 22,
- });
- // TODO: Use class method rather than directly accessing register
- this.write(0x10, 0xff); // OLED VPP Enable
- this.write(0x28, 0xff); // Enable LDO2&LDO3, LED&TFT 3.3V
- this.write(0x82, 0xff); // Enable all the ADCs
- this.write(0x33, 0xc0); // Enable Charging, 100mA, 4.2V End at 0.9
- this.write(0xb8, 0x80); // Enable Colume Counter
- this.write(0x12, 0x4d); // Enable DC-DC1, OLED VDD, 5B V EXT
- this.write(0x36, 0x5c); // PEK
- this.write(0x91, 0xA0); // Set MIC voltage to 2.8V
- this.write(0x90, 0x02); // gpio0
- }
- // value 0 - 100 %
- set brightness(value) {
- if (value <= 0)
- value = 7;
- else if (value >= 100)
- value = 15;
- else
- value = (value / 100) * 8 + 7;
- this.writeByte(0x28, (this.readByte(0x28) & 0x0F) | (value << 4));
- }
-
- /**
- * sets the screen brightness
- * @param {*} brightness brightness between 7-15
- * @deprecated Use setter
- */
- setBrightness(brightness) {
- brightness=Math.floor((brightness-6)*12.5);
- trace(`WARNING: AXP192#setBrightness is deprecated. use setter, range now 0-100, now ${brightness}\n`);
- this.brightness = brightness;
- }
-
- /**
- * @deprecated
- */
- initialize() {
- trace(
- "WARNING: AXP192#initialize is deprecated. no need to initialize explicitly"
- );
- }
-}
-
-class IMU {
- constructor() {
- const probe = new I2C({
- address: 0x68, // MPU6886
- throw: false
- });
- const result = probe.write(0x75);
- probe.close();
-
- return (result instanceof Error) ? new SH200Q : new MPU6886;
- }
-}
diff --git a/build/devices/esp32/targets/m5stick_cplus/host/provider.js b/build/devices/esp32/targets/m5stick_cplus/host/provider.js
index 4d2f3b408d..e96f37218b 100644
--- a/build/devices/esp32/targets/m5stick_cplus/host/provider.js
+++ b/build/devices/esp32/targets/m5stick_cplus/host/provider.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Moddable Tech, Inc.
+ * Copyright (c) 2021-2026 Moddable Tech, Inc.
*
* This file is part of the Moddable SDK Runtime.
*
@@ -28,6 +28,9 @@ import Serial from "embedded:io/serial";
import SMBus from "embedded:io/smbus";
import SPI from "embedded:io/spi";
import PulseWidth from "embedded:io/pulsewidth";
+import AXP192 from "embedded:peripheral/Power/axp192";
+import MPU6886 from "embedded:sensor/Accelerometer-Gyroscope/MPU6886";
+import RTC from "embedded:RTC/BM8563";
const device = {
I2C: {
@@ -75,6 +78,69 @@ const device = {
led: 10,
displayDC: 23,
displaySelect: 5
+ },
+ sensor: {
+ IMU: class extends MPU6886 {
+ constructor(options) {
+ super({
+ ...options,
+ sensor: {
+ ...device.I2C.internal,
+ io: device.io.SMBus
+ }
+ });
+ }
+ sample() {
+ const sample = super.sample();
+ sample.accelerometer.x *= -1;
+ sample.accelerometer.y *= -1;
+ sample.gyroscope.y *= -1;
+ return sample;
+ }
+ }
+ },
+ peripheral: {
+ Power: class extends AXP192 {
+ constructor(options) {
+ super({
+ ...options,
+ peripheral:{
+ ...device.I2C.internal,
+ io: device.io.SMBus
+ }
+ });
+ this.writeByte(0x10, 0xff); // OLED VPP Enable
+ this.writeByte(0x28, 0xff); // Enable LDO2&LDO3, LED&TFT 3.3V
+ this.writeByte(0x82, 0xff); // Enable all the ADCs
+ this.writeByte(0x33, 0xc0); // Enable Charging, 100mA, 4.2V End at 0.9
+ this.writeByte(0xb8, 0x80); // Enable Colume Counter
+ this.writeByte(0x12, 0x4d); // Enable DC-DC1, OLED VDD, 5B V EXT
+ this.writeByte(0x36, 0x5c); // PEK
+ this.writeByte(0x91, 0xA0); // Set MIC voltage to 2.8V
+ this.writeByte(0x90, 0x02); // gpio0
+ }
+ // value 0 - 100 %
+ set brightness(value) {
+ if (value <= 0)
+ value = 7;
+ else if (value >= 100)
+ value = 15;
+ else
+ value = (value / 100) * 8 + 7;
+ this.writeByte(0x28, (this.readByte(0x28) & 0x0F) | (value << 4));
+ }
+ },
+ RTC: class {
+ constructor(options) {
+ return new RTC({
+ ...options,
+ clock: {
+ ...device.I2C.internal,
+ io: SMBus,
+ },
+ });
+ }
+ },
}
};
diff --git a/build/devices/esp32/targets/m5stick_cplus/manifest.json b/build/devices/esp32/targets/m5stick_cplus/manifest.json
index b571f27e85..4fc7310219 100644
--- a/build/devices/esp32/targets/m5stick_cplus/manifest.json
+++ b/build/devices/esp32/targets/m5stick_cplus/manifest.json
@@ -4,20 +4,20 @@
"DEBUGGER_SPEED": "1500000"
},
"include": [
- "$(MODDABLE)/modules/drivers/st7789/manifest.json",
- "$(MODDABLE)/modules/drivers/axp192/manifest.json",
- "$(MODDABLE)/modules/pins/smbus/manifest.json"
+ "$(MODDABLE)/modules/io/manifest.json",
+ "$(MODULES)/pins/digital/monitor/manifest.json",
+ "$(MODULES)/drivers/st7789/manifest.json",
+ "$(MODULES)/drivers/sensors/mpu6886/manifest.json",
+ "$(MODULES)/drivers/peripherals/axp192/manifest.json",
+ "$(MODULES)/drivers/peripherals/bm8563/manifest.json"
],
"config": {
"screen": "st7789",
"touch": "",
- "rotation": 270
+ "rotation": 270,
+ "autorotate": true
},
"defines": {
- "i2c": {
- "sda_pin": 21,
- "scl_pin": 22
- },
"spi": {
"mosi_pin": 15,
"sck_pin": 13
@@ -75,18 +75,14 @@
},
"modules": {
"*": [
- "$(MODULES)/pins/digital/monitor/*",
- "$(MODULES)/pins/digital/monitor/esp32/*",
- "$(MODULES)/drivers/mpu6886/*",
- "$(MODULES)/drivers/sh200q/*"
+ "../m5stack_fire/m5button"
],
- "setup/target": "../m5stick_c/setup-target"
+ "setup/target": "./setup-target"
},
"preload": [
"monitor",
"setup/target",
- "mpu6886",
- "sh200q"
+ "m5button"
],
"creation": {
"static": 0,
diff --git a/build/devices/esp32/targets/m5stick_cplus/setup-target.js b/build/devices/esp32/targets/m5stick_cplus/setup-target.js
new file mode 100644
index 0000000000..52b60c2645
--- /dev/null
+++ b/build/devices/esp32/targets/m5stick_cplus/setup-target.js
@@ -0,0 +1,35 @@
+import M5Button from "m5button";
+import config from "mc/config";
+import Timer from "timer";
+
+export default function (done) {
+ globalThis.button = {
+ a: new M5Button(37),
+ b: new M5Button(39)
+ };
+
+ globalThis.power = new device.peripheral.Power();
+
+ if (config.autorotate && globalThis.Application) {
+ const imu = new device.sensor.IMU();
+ Timer.repeat(id => {
+ const sample = imu.sample();
+ const {x, y } = sample.accelerometer;
+ if (Math.abs(y) > Math.abs(x)) {
+ if (y < -0.7 && application.rotation !== 270) {
+ application.rotation = 270;
+ } else if (y > 0.7 && application.rotation !== 90) {
+ application.rotation = 90;
+ }
+ } else {
+ if (x < -0.7 && application.rotation !== 180) {
+ application.rotation = 180;
+ } else if (x > 0.7 && application.rotation !== 0) {
+ application.rotation = 0;
+ }
+ }
+ }, 300);
+ }
+
+ done();
+}
diff --git a/examples/drivers/m5stickc-axp192/main.js b/examples/drivers/m5stickc-axp192/main.js
index 3d7def294c..1681f1574b 100644
--- a/examples/drivers/m5stickc-axp192/main.js
+++ b/examples/drivers/m5stickc-axp192/main.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2025 Moddable Tech, Inc.
+ * Copyright (c) 2016-2026 Moddable Tech, Inc. , Satoshi Tanaka
*
* This file is part of the Moddable SDK.
*
@@ -18,21 +18,21 @@ import Poco from "commodetto/Poco";
import Resource from "Resource";
import config from "mc/config";
-let render = new Poco(screen, {rotation:config?.rotation});
+const render = new Poco(screen, {rotation:config?.rotation});
-let white = render.makeColor(255, 255, 255);
-let blue = render.makeColor(0, 0, 255);
+const white = render.makeColor(255, 255, 255);
+const blue = render.makeColor(0, 0, 255);
-let font = parseBMF(new Resource("OpenSans-Semibold-18.bf4"));
-let text = "Press button A to change brightness... ";
-let textWidth = render.getTextWidth(text, font);
+const font = parseBMF(new Resource("OpenSans-Semibold-18.bf4"));
+const text = "Press button A to change brightness... ";
+const textWidth = render.getTextWidth(text, font);
let x = render.width;
let y = (render.height - font.height) >> 1;
-let loop = true; // set false to scroll text once across the screen
+const loop = true; // set false to scroll text once across the screen
let brightness = 50; // screen brightness %
-button.a.onChanged = function() {
- if (button.a.read()) {
+globalThis.button.a.onChanged = () =>{
+ if (globalThis.button.a.read()) {
return;
}
brightness+=10;
@@ -51,14 +51,14 @@ Timer.repeat(id => {
render.fillRectangle(blue, 0, 0, render.width, render.height);
render.drawText(text, font, white, x, y);
if (!loop) {
- if (x + textWidth == 0)
+ if (x + textWidth === 0)
Timer.clear(id);
}
else {
if (x + textWidth < render.width)
render.drawText(text, font, white, x + textWidth, y);
}
- if (x + textWidth == 0)
+ if (x + textWidth === 0)
x = 0;
else
--x;
diff --git a/examples/drivers/m5stickc-imu/main.js b/examples/drivers/m5stickc-imu/main.js
index e4b8e3b166..5d06892792 100644
--- a/examples/drivers/m5stickc-imu/main.js
+++ b/examples/drivers/m5stickc-imu/main.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2022 Moddable Tech, Inc.
+ * Copyright (c) 2016-2026 Moddable Tech, Inc. , Satoshi Tanaka
*
* This file is part of the Moddable SDK.
*
@@ -17,15 +17,16 @@ import parseBMP from "commodetto/parseBMP";
import Poco from "commodetto/Poco";
import Resource from "Resource";
import config from "mc/config";
+import Timer from "timer";
const GYRO_SCALER = 0.002;
-let render = new Poco(screen, {rotation: config?.rotation ?? screen.rotation});
+const render = new Poco(screen, {rotation: config?.rotation ?? screen.rotation});
const width = render.width, height = render.height;
-let font = parseBMF(new Resource("OpenSans-Semibold-16.bf4"));
+const font = parseBMF(new Resource("OpenSans-Semibold-16.bf4"));
-let ball = parseBMP(new Resource("ball-color.bmp"));
+const ball = parseBMP(new Resource("ball-color.bmp"));
ball.alpha = parseBMP(new Resource("ball-alpha.bmp"));
ball.x = width >> 1;
ball.y = height >> 1;
@@ -43,49 +44,48 @@ render.begin();
render.fillRectangle(ball.backgroundColor, 0, ball.yMin, width, height);
render.end();
-accelerometer.onreading = function(values){
- onReading(values, "a");
-}
-
-gyro.onreading = function(values){
- let {x, y, z} = values;
- x *= GYRO_SCALER;
- y *= GYRO_SCALER;
- z *= GYRO_SCALER;
- onReading({x,y,z}, "g");
-}
+const imu = new device.sensor.IMU()
+imu.configure({
+ "GYRO_SCALER": (2000.0 / 32768.0) * GYRO_SCALER
+})
+
+Timer.repeat(() => {
+ const sample = imu.sample();
+ if(flag) {
+ onReading(sample.accelerometer, "a");
+ } else {
+ onReading(sample.gyroscope, "g");
+ }
+}, 17)
-accelerometer.start(17);
+let flag = true;
-button.a.onChanged = function(){
- let value = button.a.read();
+globalThis.button.a.onChanged = () =>{
+ const value = globalThis.button.a.read();
if (value) {
- accelerometer.stop();
- gyro.stop();
- accelerometer.start(17);
+ flag = true
}
}
-button.b.onChanged = function(){
- let value = button.b.read();
- if (value){
- accelerometer.stop();
- gyro.stop();
- gyro.start(17);
+globalThis.button.b.onChanged = () =>{
+ const value = globalThis.button.b.read();
+ if (value) {
+ flag = false
}
}
function onReading(values, labelPrefix){
- let { x, y, z } = values;
+ const { x, y, z } = values;
+ trace(`${labelPrefix}X: ${formatValue(x)} - ${labelPrefix}Y: ${formatValue(y)} - ${labelPrefix}Z: ${formatValue(z)}\n`);
render.begin(0, 0, width, ball.yMin);
render.fillRectangle(backgroundColor, 0, 0, width, height);
- drawBar(labelPrefix + "X", x, 0, 0, width, font.height);
- drawBar(labelPrefix + "Y", y, 0, font.height, width, font.height);
- drawBar(labelPrefix + "Z", z, 0, font.height * 2, width, font.height);
+ drawBar(`${labelPrefix}X`, x, 0, 0, width, font.height);
+ drawBar(`${labelPrefix}Y`, y, 0, font.height, width, font.height);
+ drawBar(`${labelPrefix}Z`, z, 0, font.height * 2, width, font.height);
render.end();
- ball.vx = (ball.vx - x) * 0.98;
+ ball.vx = (ball.vx + x) * 0.98;
ball.vy = (ball.vy - y) * 0.98;
let nx = ball.x + ball.vx;
let ny = ball.y + ball.vy;
@@ -114,7 +114,7 @@ function formatValue(value) {
return value;
if (value < 0)
return value.toFixed(3);
- return "+" + value.toFixed(3);
+ return `+${value.toFixed(3)}`;
}
function drawBar(label, value, x, y, width, height) {
diff --git a/examples/drivers/m5stickc-pedometer/main.js b/examples/drivers/m5stickc-pedometer/main.js
index 5c1ea47ddc..09e8e787e3 100644
--- a/examples/drivers/m5stickc-pedometer/main.js
+++ b/examples/drivers/m5stickc-pedometer/main.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Moddable Tech, Inc.
+ * Copyright (c) 2022-2026 Moddable Tech, Inc., Satoshi Tanaka
*
* This file is part of the Moddable SDK.
*
@@ -24,7 +24,7 @@ const STARTING_STEPS = 123;
const GOAL = 200;
const SHAKEVALUE = 3;
-let render = new Poco(screen, {rotation: config.rotation});
+const render = new Poco(screen, {rotation: config.rotation});
const black = render.makeColor(0, 0, 0);
const white = render.makeColor(255, 255, 255);
@@ -59,7 +59,7 @@ function redraw() {
let offset = (render.width-32)/2;
render.drawGray(steps, stepColor, 20, 7);
render.fillRectangle(stepColor, 10, render.height-17, render.width-20, render.height-17);
- let fraction = stepCount / GOAL;
+ const fraction = stepCount / GOAL;
render.fillRectangle(barColor, 10, render.height-17, (render.width-20)*fraction, render.height-17);
render.drawGray(progressOverlay, backgroundColor, 0, render.height-17);
offset = (render.width-(render.getTextWidth(stepCount, bigFont)))/2;
@@ -69,30 +69,31 @@ function redraw() {
}
-accelerometer.oldData = {x: 0, y: 0, z: 0, init: false};
-accelerometer.onreading = function(values) {
+const imu = new device.sensor.IMU();
+let oldData = {x: 0, y: 0, z: 0, init: false};
+function onReading(values) {
const {x,y,z} = values;
- if (this.oldData.init){
- const delta = Math.abs(x - this.oldData.x) + Math.abs(y - this.oldData.y) + Math.abs(z - this.oldData.z);
+ if (oldData.init){
+ const delta = Math.abs(x - oldData.x) + Math.abs(y - oldData.y) + Math.abs(z - oldData.z);
if (delta > SHAKEVALUE) {
stepCount++;
redraw();
}
}
- this.oldData.x = x;
- this.oldData.y = y;
- this.oldData.z = z;
- this.oldData.init = true;
+ oldData.x = x;
+ oldData.y = y;
+ oldData.z = z;
+ oldData.init = true;
}
-button.a.onChanged = function() {
+globalThis.button.a.onChanged = function() {
if (this.read()) {
lightMode = !lightMode;
redraw();
}
}
-button.b.onChanged = function() {
+globalThis.button.b.onChanged = function() {
if (this.read()) {
stepCount = 0;
redraw();
@@ -100,4 +101,7 @@ button.b.onChanged = function() {
}
redraw();
-accelerometer.start(17);
+Timer.repeat(() => {
+ const sample = imu.sample();
+ onReading(sample.accelerometer)
+}, 17)
diff --git a/examples/drivers/m5stickc-rtc/main.js b/examples/drivers/m5stickc-rtc/main.js
index 46da9f59ba..2e0bd213ce 100644
--- a/examples/drivers/m5stickc-rtc/main.js
+++ b/examples/drivers/m5stickc-rtc/main.js
@@ -12,43 +12,29 @@
*
*/
-import BM8563 from "bm8563";
import Time from "time";
+import Timer from "timer";
+import parseBMF from "commodetto/parseBMF";
+import Poco from "commodetto/Poco";
+import Resource from "Resource";
+import config from "mc/config";
+const rtc = new device.peripheral.RTC();
-let rtc = new BM8563;
-let enabled = 1;
-
-// Main button: enable/disable RTC
-button.a.onChanged = function () {
- if (button.a.read()) {
- return;
- }
- enabled = !enabled;
- rtc.enabled = enabled;
- globalThis.power.brightness = 20 + enabled * 70;
-}
-
-// Side button: set time from sntp
-button.b.onChanged = function () {
- if (button.b.read()) {
+// Main button: set time from sntp
+globalThis.button.a.onChanged = () => {
+if (globalThis.button.a.read()) {
return;
}
setRTCTimeLocal();
}
-import Timer from "timer";
-import parseBMF from "commodetto/parseBMF";
-import Poco from "commodetto/Poco";
-import Resource from "Resource";
-import config from "mc/config";
-
function setRTCTimeLocal() {
- let d = new Date();
+ const d = new Date();
trace(`Set time: ${d.getTime()} ${d.toString()} tz:${Time.timezone} dst:${Time.dst}\n`);
- rtc.seconds = d.getTime() / 1000;
- let read = rtc.seconds;
- let s = new Date(read * 1000);
+ rtc.time = d.getTime();
+ const read = rtc.time;
+ const s = new Date(read);
trace(`Get time: ${read} ${s.toString()}\n`)
}
@@ -56,29 +42,27 @@ const render = new Poco(screen, {
rotation: config.rotation
});
-let white = render.makeColor(255, 255, 255);
-let grey = render.makeColor(170, 170, 170);
-let blue = render.makeColor(0, 0, 255);
+const white = render.makeColor(255, 255, 255);
+const grey = render.makeColor(170, 170, 170);
+const blue = render.makeColor(0, 0, 255);
-let font = parseBMF(new Resource("OpenSans-Semibold-16.bf4"));
-let text = "Press button A to set Time";
-let textWidth = render.getTextWidth(text, font);
-let x = 1;
-let y = 1;
+const font = parseBMF(new Resource("OpenSans-Semibold-16.bf4"));
+const x = 1;
+const y = 1;
render.begin();
render.fillRectangle(blue, 0, 0, render.width, render.height);
render.end();
-Timer.repeat(id => {
+Timer.repeat(_id => {
let now = 'setting..';
try {
- now = rtc.seconds;
+ now = rtc.time;
} catch (e) {
trace(e);
}
- let rtc_clock = new Date(now * 1000);
- let actual_clock = new Date();
+ const rtc_clock = new Date(now);
+ const actual_clock = new Date();
render.begin(0, y, render.width, render.height);
render.fillRectangle(blue, 0, 0, render.width, render.height);
render.drawText(rtc_clock.toString().slice(4, 24), font, white, x, y);
diff --git a/examples/drivers/m5stickc-rtc/manifest.json b/examples/drivers/m5stickc-rtc/manifest.json
index 7dec6a3df4..f940821939 100644
--- a/examples/drivers/m5stickc-rtc/manifest.json
+++ b/examples/drivers/m5stickc-rtc/manifest.json
@@ -4,15 +4,11 @@
},
"include": [
"$(MODDABLE)/examples/manifest_base.json",
- "$(MODDABLE)/examples/manifest_net.json",
- "$(MODULES)/pins/i2c/manifest.json",
+ "$(MODDABLE)/examples/manifest_net.json",
"$(MODDABLE)/examples/manifest_commodetto.json"
],
"modules": {
- "pins/smbus": "$(MODULES)/pins/smbus/smbus",
"*": [
- "$(MODULES)/drivers/rtc/rtc",
- "$(MODULES)/drivers/rtc/bm8563",
"$(MODULES)/network/sntp/*",
"./main"
]
@@ -21,10 +17,7 @@
"*-mask": "$(MODDABLE)/examples/assets/fonts/OpenSans-Semibold-16"
},
"preload": [
- "sntp",
- "bm8563",
- "rtc",
- "smbus"
+ "sntp"
],
"platforms": {
"esp32/m5stick_c" :{
diff --git a/modules/drivers/peripherals/axp192/axp192.js b/modules/drivers/peripherals/axp192/axp192.js
new file mode 100644
index 0000000000..325a200113
--- /dev/null
+++ b/modules/drivers/peripherals/axp192/axp192.js
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2019-2026 Shinya Ishikawa, Satoshi Tanaka
+ *
+ * This file is part of the Moddable SDK Runtime.
+ *
+ * The Moddable SDK Runtime is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Moddable SDK Runtime is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the Moddable SDK Runtime. If not, see .
+ *
+ */
+
+class DCDC {
+ #parent;
+ #register;
+ constructor({ register, parent }) {
+ this.#parent = parent;
+ this.#register = register;
+ }
+ set voltage(v) {
+ const vdata = v < 700 ? 0 : (v - 700) / 25;
+ this.#parent.writeByte(
+ this.#register,
+ (this.#parent.readByte(this.#register) & 0x80) | (vdata & 0x7f)
+ );
+ }
+ get voltage() {
+ return (this.#parent.readByte(this.#register) & 0x7f) * 25 + 700;
+ }
+}
+
+class LDO {
+ #parent;
+ #register;
+ #offsetV;
+ #offsetEn;
+ constructor({ register, parent, offsetV, offsetEn }) {
+ this.#parent = parent;
+ this.#register = register;
+ this.#offsetV = offsetV;
+ this.#offsetEn = offsetEn;
+ }
+
+ set voltage(v) {
+ const vdata = v > 3300 ? 15 : v / 100 - 18;
+ const mask = ~(0xff << this.#offsetV);
+ this.#parent.writeByte(
+ this.#register,
+ (this.#parent.readByte(this.#register) & mask) | (vdata << this.#offsetV)
+ );
+ }
+
+ get voltage() {
+ return (
+ ((this.#parent.readByte(this.#register) >> this.#offsetV) + 18) * 100
+ );
+ }
+
+ set enable(enable) {
+ const mask = 0x01 << this.#offsetEn;
+ if (enable) {
+ this.#parent.writeByte(0x12, this.#parent.readByte(0x12) | mask);
+ } else {
+ this.#parent.writeByte(0x12, this.#parent.readByte(0x12) & ~mask);
+ }
+ }
+
+ get enable() {
+ return Boolean((this.#parent.readByte(0x12) >> this.#offsetEn) & 1);
+ }
+}
+
+class GPIO {
+ #register;
+ #parent;
+ #mask;
+ constructor({ register, parent, offset }) {
+ this.#parent = parent;
+ this.#register = register;
+ this.#mask = 0x01 << offset;
+ }
+
+ get enable() {
+ return Boolean(this.#parent.readByte(this.#register) & this.#mask);
+ }
+
+ set enable(enable) {
+ let data = this.#parent.readByte(this.#register);
+ if (enable) {
+ data |= this.#mask;
+ } else {
+ data &= ~this.#mask;
+ }
+ this.#parent.writeByte(this.#register, data);
+ }
+}
+
+export default class AXP192 {
+ #io;
+ constructor(options) {
+ this.#io = new options.peripheral.io({
+ hz: 400_000,
+ address: 0x34,
+ ...options.peripheral,
+ });
+
+ this._dcdc1 = new DCDC({ register: 0x26, parent: this });
+ this._dcdc2 = new DCDC({ register: 0x23, parent: this });
+ this._dcdc3 = new DCDC({ register: 0x27, parent: this });
+ this._ldo2 = new LDO({
+ register: 0x34,
+ parent: this,
+ offsetV: 4,
+ offsetEn: 2,
+ });
+ this._ldo3 = new LDO({
+ register: 0x34,
+ parent: this,
+ offsetV: 0,
+ offsetEn: 3,
+ });
+ this._gpio0 = new GPIO({ register: 0x94, parent: this, offset: 0 });
+ this._gpio1 = new GPIO({ register: 0x94, parent: this, offset: 1 });
+ this._gpio2 = new GPIO({ register: 0x94, parent: this, offset: 2 });
+ this._gpio3 = new GPIO({ register: 0x96, parent: this, offset: 0 });
+ this._gpio4 = new GPIO({ register: 0x96, parent: this, offset: 1 });
+ }
+
+ readByte(address) {
+ return this.#io.readUint8(address);
+ }
+
+ writeByte(address, value) {
+ return this.#io.writeUint8(address, value);
+ }
+
+ set chargeCurrent(state) {
+ this.writeByte(0x33, (this.readByte(0x33) & 0xf0) | (state & 0x0f));
+ }
+ get batteryVoltage() {
+ let data = this.readByte(0x78) << 4;
+ data |= this.readByte(0x79);
+ return data * 1.1 / 1000;
+ }
+ get batteryCurrent() {
+ let currentIn = this.readByte(0x7a) << 5;
+ currentIn |= this.readByte(0x7b);
+ let currentOut = this.readByte(0x7c) << 5;
+ currentOut |= this.readByte(0x7d);
+
+ return (currentIn - currentOut) * 0.5;
+ }
+}
+
+AXP192.CHARGE_CURRENT = {
+ Ch_100mA: 0b0000,
+ Ch_190mA: 0b0001,
+ Ch_280mA: 0b0010,
+ Ch_360mA: 0b0011,
+ Ch_450mA: 0b0100,
+ Ch_550mA: 0b0101,
+ Ch_630mA: 0b0110,
+ Ch_700mA: 0b0111,
+ Ch_780mA: 0b1000,
+ Ch_880mA: 0b1001,
+ Ch_960mA: 0b1010,
+ Ch_1000mA: 0b1011,
+ Ch_1080mA: 0b1100,
+ Ch_1160mA: 0b1101,
+ Ch_1240mA: 0b1110,
+ Ch_1320mA: 0b1111,
+};
diff --git a/modules/drivers/peripherals/axp192/manifest.json b/modules/drivers/peripherals/axp192/manifest.json
new file mode 100644
index 0000000000..553d194599
--- /dev/null
+++ b/modules/drivers/peripherals/axp192/manifest.json
@@ -0,0 +1,8 @@
+{
+ "modules": {
+ "embedded:peripheral/Power/axp192": "./axp192"
+ },
+ "preload": [
+ "embedded:peripheral/Power/axp192"
+ ]
+}
diff --git a/modules/drivers/sensors/sh200q/manifest.json b/modules/drivers/sensors/sh200q/manifest.json
new file mode 100644
index 0000000000..5df9585837
--- /dev/null
+++ b/modules/drivers/sensors/sh200q/manifest.json
@@ -0,0 +1,9 @@
+{
+ "modules": {
+ "embedded:sensor/Accelerometer-Gyroscope/SH200Q": "$(MODDABLE)/modules/drivers/sensors/sh200q/sh200q"
+ },
+ "preload": [
+ "embedded:sensor/Accelerometer-Gyroscope/SH200Q"
+ ]
+}
+
diff --git a/modules/drivers/sensors/sh200q/sh200q.js b/modules/drivers/sensors/sh200q/sh200q.js
new file mode 100644
index 0000000000..006be6f2f1
--- /dev/null
+++ b/modules/drivers/sensors/sh200q/sh200q.js
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) Wilberforce
+
+ * Copyright (c) 2019-2020 Moddable Tech, Inc.
+ *
+ * This file is part of the Moddable SDK Runtime.
+ *
+ * The Moddable SDK Runtime is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Moddable SDK Runtime is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the Moddable SDK Runtime. If not, see .
+ *
+ */
+/*
+ sh200q Accelerometer + Gyro
+ Datasheet: http://senodia.com/Uploads/Product/5b2b6ef1216e8.pdf
+ Register Map: https://github.com/m5stack/M5StickC/blob/master/src/utility/SH200Q.h#L7-L22
+ https://github.com/m5stack/M5StickC/blob/master/src/utility/SH200Q.cpp
+
+*/
+
+import Timer from "timer";
+
+const REGISTERS = {
+ ACCEL_XOUT: 0x00,
+ TEMP_OUT: 0x0C,
+ GYRO_XOUT: 0x06,
+ WHO_AM_I: 0x30,
+
+ ACC_CONFIG: 0x0E,
+ GYRO_CONFIG: 0x0F,
+ GYRO_DLPF: 0x11,
+ FIFO_CONFIG: 0x12,
+ ACC_RANGE: 0x16,
+ GYRO_RANGE: 0x2B,
+ OUTPUT_ACC: 0x00,
+ OUTPUT_GYRO: 0x06,
+ OUTPUT_TEMP: 0x0C,
+ REG_SET1: 0xBA,
+ REG_SET2: 0xCA, //ADC reset
+ ADC_RESET: 0xC2, //drive reset
+ SOFT_RESET: 0x7F,
+ RESET: 0x75
+};
+Object.freeze(REGISTERS);
+
+const EXPECTED_WHO_AM_I = 0x18;
+
+const GYRO_SCALER = {
+ GFS_125DPS: (125.0 / 32768.0),
+ GFS_250DPS: (250.0 / 32768.0),
+ GFS_500DPS: (500.0 / 32768.0),
+ GFS_1000DPS: (1000.0 / 32768.0),
+ GFS_2000DPS: (2000.0 / 32768.0)
+};
+Object.freeze(GYRO_SCALER);
+
+const ACCEL_SCALER = {
+ AFS_2G: (2.0 / 32768.0),
+ AFS_4G: (4.0 / 32768.0),
+ AFS_8G: (8.0 / 32768.0),
+ AFS_16G: (16.0 / 32768.0)
+};
+Object.freeze(ACCEL_SCALER);
+
+class SH200Q {
+ #io;
+ #view;
+ #gyroScale = GYRO_SCALER.GFS_2000DPS;
+ #accelScale = ACCEL_SCALER.AFS_8G;
+
+ constructor(options) {
+ const io = this.#io = new options.sensor.io({
+ hz: 400_000,
+ address: 0x6C,
+ ...options.sensor
+ });
+
+ this.#view = new DataView(new ArrayBuffer(6));
+
+ if (io.readUint8(REGISTERS.WHO_AM_I) !== EXPECTED_WHO_AM_I)
+ throw new Error("unrecognized");
+
+ this.enable();
+ }
+
+ close() {
+ this.#io?.close();
+ this.#io = undefined;
+ }
+
+ configure(dictionary) {
+ for (const property in dictionary) {
+ switch (property) {
+ case "GYRO_SCALER":
+ this.#gyroScale = dictionary.GYRO_SCALER;
+ break;
+ case "ACCEL_SCALER":
+ this.#accelScale = dictionary.ACCEL_SCALER;
+ break;
+ }
+ }
+ }
+
+ enable() {
+ const io = this.#io;
+
+ Timer.delay(1);
+
+ // set acc odr 256hz
+ // 0x81 1024hz //0x89 512hz //0x91 256hz
+ io.writeUint8(REGISTERS.ACC_CONFIG, 0x91);
+
+ // set gyro odr 500hz
+ // 0x11 1000hz //0x13 500hz //0x15 256hz
+ io.writeUint8(REGISTERS.GYRO_CONFIG, 0x13);
+
+ // set gyro dlpf 50hz
+ // 0x00 250hz //0x01 200hz //0x02 100hz //0x03 50hz //0x04 25hz
+ io.writeUint8(REGISTERS.GYRO_DLPF, 0x03);
+
+ // set no buffer mode
+ io.writeUint8(REGISTERS.FIFO_CONFIG, 0x00);
+
+ // set acc range +-8G
+ io.writeUint8(REGISTERS.ACC_RANGE, 0x01);
+
+ // set gyro range +-2000/s
+ io.writeUint8(REGISTERS.GYRO_RANGE, 0x00);
+
+ io.writeUint8(REGISTERS.REG_SET1, 0xC0);
+
+ // ADC Reset
+ const temp = io.readUint8(REGISTERS.REG_SET2);
+ io.writeUint8(REGISTERS.REG_SET2, temp | 0x10);
+
+ Timer.delay(1);
+
+ io.writeUint8(REGISTERS.REG_SET2, temp & 0xEF);
+
+ Timer.delay(10);
+ }
+
+ sample() {
+ const io = this.#io;
+ const view = this.#view;
+
+ io.readBuffer(REGISTERS.ACCEL_XOUT, view);
+ const accelerometer = {
+ x: view.getInt16(0) * this.#accelScale,
+ y: view.getInt16(2) * this.#accelScale,
+ z: view.getInt16(4) * this.#accelScale
+ };
+
+ io.readBuffer(REGISTERS.GYRO_XOUT, view);
+ const gyroscope = {
+ x: view.getInt16(0) * this.#gyroScale,
+ y: view.getInt16(2) * this.#gyroScale,
+ z: view.getInt16(4) * this.#gyroScale
+ };
+
+ io.readBuffer(REGISTERS.TEMP_OUT, 2, view.buffer);
+ const thermometer = {
+ temperature: view.getInt16(0, true) / 333.87 + 21.0
+ };
+
+ return {
+ accelerometer,
+ gyroscope,
+ thermometer
+ };
+ }
+}
+Object.freeze(SH200Q.prototype);
+
+export default SH200Q;