Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 89-apps-should-be-able-to-specify-if-they-want-wifi-to-be-disabled-when-entering-them
  • 9Rmain
  • allow-reloading-sunmenu
  • always-have-a-wifi-instance
  • anon/gpndemo
  • anon/update-sim
  • anon/webflasher
  • app_text_viewer
  • audio_input
  • audio_io
  • blm_dev_chan
  • ch3/bl00mbox_docs
  • ci-1690580595
  • dev_p4
  • dev_p4-iggy
  • dev_p4-iggy-rebased
  • dx/dldldld
  • dx/fb-save-restore
  • dx/hint-hint
  • dx/jacksense-headset-mic-only
  • events
  • fil3s-limit-filesize
  • fil3s-media
  • fpletz/flake
  • gr33nhouse-improvements
  • history-rewrite
  • icon-flower
  • iggy/stemming
  • iggy/stemming_merge
  • led_fix_fix
  • main
  • main+schneider
  • media_has_video_has_audio
  • micropython_api
  • mixer2
  • moon2_demo_temp
  • moon2_migrate_apps
  • more-accurate-battery
  • pippin/ctx_sprite_sheet_support
  • pippin/display-python-errors-on-display
  • pippin/make_empty_drawlists_skip_render_and_blit
  • pippin/more-accurate-battery
  • pippin/tcp_redirect_hack
  • pippin/tune_ctx_config_update_from_upstream
  • pippin/uhm_flash_access_bust
  • pressable_bugfix
  • py_only_update_fps_overlay_when_changing
  • q3k/doom-poc
  • q3k/render-to-texture
  • rahix/flow3rseeds
  • raw_captouch_new
  • raw_captouch_old
  • release/1.0.0
  • release/1.1.0
  • release/1.1.1
  • release/1.2.0
  • release/1.3.0
  • release/1.4.0
  • restore_blit
  • return_of_melodic_demo
  • rev4_micropython
  • schneider/application-remove-name
  • schneider/bhi581
  • schneider/factory_test
  • schneider/recovery
  • scope_hack
  • sdkconfig-spiram-tinyusb
  • sec/auto-nick
  • sec/blinky
  • sector_size_512
  • shoegaze-fps
  • smaller_gradient_lut
  • store_delta_ms_and_ins_as_class_members
  • task_cleanup
  • uctx-wip
  • w1f1-in-sim
  • widgets_draw
  • wifi-json-error-handling
  • wip-docs
  • wip-tinyusb
  • v1.0.0
  • v1.0.0+rc1
  • v1.0.0+rc2
  • v1.0.0+rc3
  • v1.0.0+rc4
  • v1.0.0+rc5
  • v1.0.0+rc6
  • v1.1.0
  • v1.1.0+rc1
  • v1.1.1
  • v1.2.0
  • v1.2.0+rc1
  • v1.3.0
  • v1.4.0
94 results

Target

Select target project
  • flow3r/flow3r-firmware
  • Vespasian/flow3r-firmware
  • alxndr42/flow3r-firmware
  • pl/flow3r-firmware
  • Kari/flow3r-firmware
  • raimue/flow3r-firmware
  • grandchild/flow3r-firmware
  • mu5tach3/flow3r-firmware
  • Nervengift/flow3r-firmware
  • arachnist/flow3r-firmware
  • TheNewCivilian/flow3r-firmware
  • alibi/flow3r-firmware
  • manuel_v/flow3r-firmware
  • xeniter/flow3r-firmware
  • maxbachmann/flow3r-firmware
  • yGifoom/flow3r-firmware
  • istobic/flow3r-firmware
  • EiNSTeiN_/flow3r-firmware
  • gnudalf/flow3r-firmware
  • 999eagle/flow3r-firmware
  • toerb/flow3r-firmware
  • pandark/flow3r-firmware
  • teal/flow3r-firmware
  • x42/flow3r-firmware
  • alufers/flow3r-firmware
  • dos/flow3r-firmware
  • yrlf/flow3r-firmware
  • LuKaRo/flow3r-firmware
  • ThomasElRubio/flow3r-firmware
  • ai/flow3r-firmware
  • T_X/flow3r-firmware
  • highTower/flow3r-firmware
  • beanieboi/flow3r-firmware
  • Woazboat/flow3r-firmware
  • gooniesbro/flow3r-firmware
  • marvino/flow3r-firmware
  • kressnerd/flow3r-firmware
  • quazgar/flow3r-firmware
  • aoid/flow3r-firmware
  • jkj/flow3r-firmware
  • naomi/flow3r-firmware
41 results
Select Git revision
  • 89-apps-should-be-able-to-specify-if-they-want-wifi-to-be-disabled-when-entering-them
  • 9Rmain
  • allow-reloading-sunmenu
  • always-have-a-wifi-instance
  • anon/gpndemo
  • anon/update-sim
  • anon/webflasher
  • app_text_viewer
  • audio_input
  • audio_io
  • blm_dev_chan
  • ch3/bl00mbox_docs
  • ci-1690580595
  • dev_p4
  • dev_p4-iggy
  • dev_p4-iggy-rebased
  • dx/dldldld
  • dx/fb-save-restore
  • dx/hint-hint
  • dx/jacksense-headset-mic-only
  • events
  • fil3s-limit-filesize
  • fil3s-media
  • fpletz/flake
  • gr33nhouse-improvements
  • history-rewrite
  • icon-flower
  • iggy/stemming
  • iggy/stemming_merge
  • led_fix_fix
  • main
  • main+schneider
  • media_has_video_has_audio
  • micropython_api
  • mixer2
  • moon2_demo_temp
  • moon2_migrate_apps
  • more-accurate-battery
  • pippin/ctx_sprite_sheet_support
  • pippin/display-python-errors-on-display
  • pippin/make_empty_drawlists_skip_render_and_blit
  • pippin/more-accurate-battery
  • pippin/tcp_redirect_hack
  • pippin/tune_ctx_config_update_from_upstream
  • pippin/uhm_flash_access_bust
  • pressable_bugfix
  • py_only_update_fps_overlay_when_changing
  • q3k/doom-poc
  • q3k/render-to-texture
  • rahix/flow3rseeds
  • raw_captouch_new
  • raw_captouch_old
  • release/1.0.0
  • release/1.1.0
  • release/1.1.1
  • release/1.2.0
  • release/1.3.0
  • release/1.4.0
  • restore_blit
  • return_of_melodic_demo
  • rev4_micropython
  • schneider/application-remove-name
  • schneider/bhi581
  • schneider/factory_test
  • schneider/recovery
  • scope_hack
  • sdkconfig-spiram-tinyusb
  • sec/auto-nick
  • sec/blinky
  • sector_size_512
  • shoegaze-fps
  • smaller_gradient_lut
  • store_delta_ms_and_ins_as_class_members
  • task_cleanup
  • uctx-wip
  • w1f1-in-sim
  • widgets_draw
  • wifi-json-error-handling
  • wip-docs
  • wip-tinyusb
  • v1.0.0
  • v1.0.0+rc1
  • v1.0.0+rc2
  • v1.0.0+rc3
  • v1.0.0+rc4
  • v1.0.0+rc5
  • v1.0.0+rc6
  • v1.1.0
  • v1.1.0+rc1
  • v1.1.1
  • v1.2.0
  • v1.2.0+rc1
  • v1.3.0
  • v1.4.0
94 results
Show changes
Showing
with 2774 additions and 1389 deletions
......@@ -36,13 +36,17 @@ void flow3r_bsp_display_init(void) {
}
}
void flow3r_bsp_display_send_fb(uint16_t *fb_data) {
void flow3r_bsp_display_send_fb_osd(void *fb_data, int bits, int scale,
void *osd_data, int osd_x0, int osd_y0,
int osd_x1, int osd_y1) {
if (!gc9a01_initialized) {
return;
}
static bool had_error = false;
esp_err_t ret = flow3r_bsp_gc9a01_blit_full(&gc9a01, fb_data);
esp_err_t ret =
flow3r_bsp_gc9a01_blit_osd(&gc9a01, fb_data, bits, scale, osd_data,
osd_x0, osd_y0, osd_x1, osd_y1);
if (ret != ESP_OK) {
if (!had_error) {
ESP_LOGE(TAG, "display blit failed: %s", esp_err_to_name(ret));
......@@ -56,6 +60,10 @@ void flow3r_bsp_display_send_fb(uint16_t *fb_data) {
}
}
void flow3r_bsp_display_send_fb(void *fb_data, int bits) {
flow3r_bsp_display_send_fb_osd(fb_data, bits, 1, NULL, 0, 0, 0, 0);
}
void flow3r_bsp_display_set_backlight(uint8_t percent) {
if (!gc9a01_initialized) {
return;
......
......@@ -99,7 +99,16 @@ typedef struct {
typedef struct {
flow3r_bsp_gc9a01_t *gc9a01;
const uint8_t *fb;
const uint8_t *osd_fb;
int osd_x0;
int osd_y0;
int osd_x1;
int osd_y1;
uint16_t *pal_16;
int bits;
int scale;
size_t left;
size_t off; // current pixel offset in blit
flow3r_bsp_gc9a01_tx_t gc9a01_tx;
spi_transaction_t spi_tx;
......@@ -219,7 +228,7 @@ esp_err_t flow3r_bsp_gc9a01_cmd_sync(flow3r_bsp_gc9a01_t *gc9a01, uint8_t cmd) {
* mode for higher speed. The overhead of interrupt transactions is more than
* just waiting for the transaction to complete.
*/
esp_err_t flow3r_bsp_gc9a01_data_sync(flow3r_bsp_gc9a01_t *gc9a01,
static esp_err_t flow3r_bsp_gc9a01_data_sync(flow3r_bsp_gc9a01_t *gc9a01,
const uint8_t *data, int len) {
if (len == 0) {
return ESP_OK;
......@@ -260,7 +269,7 @@ esp_err_t flow3r_bsp_gc9a01_data_sync(flow3r_bsp_gc9a01_t *gc9a01,
return ESP_OK;
}
esp_err_t flow3r_bsp_gc9a01_data_byte_sync(flow3r_bsp_gc9a01_t *gc9a01,
static esp_err_t flow3r_bsp_gc9a01_data_byte_sync(flow3r_bsp_gc9a01_t *gc9a01,
const uint8_t data) {
return flow3r_bsp_gc9a01_data_sync(gc9a01, &data, 1);
}
......@@ -517,7 +526,7 @@ esp_err_t flow3r_bsp_gc9a01_init(flow3r_bsp_gc9a01_t *gc9a01,
ix++;
}
ret = flow3r_bsp_gc9a01_mem_access_mode_set(gc9a01, 0, 0, 0, 1);
ret = flow3r_bsp_gc9a01_mem_access_mode_set(gc9a01, 3, 0, 0, 1);
if (ret != ESP_OK) {
goto cleanup_spi_device;
}
......@@ -560,11 +569,438 @@ cleanup_spi_bus:
return ret;
}
static esp_err_t flow3r_bsp_gc9a01_blit_next(flow3r_bsp_gc9a01_blit_t *blit) {
/* branchless 8bit add that maxes out at 255 */
static inline uint8_t ctx_sadd8(uint8_t a, uint8_t b) {
uint16_t s = (uint16_t)a + b;
return -(s >> 8) | (uint8_t)s;
}
static EXT_RAM_BSS_ATTR uint16_t temp_blit[SPI_MAX_DMA_LEN / 2];
static inline uint32_t ctx_565_unpack_32(const uint16_t pixel,
const int byteswap) {
uint16_t byteswapped;
if (byteswap) {
byteswapped = (pixel >> 8) | (pixel << 8);
} else {
byteswapped = pixel;
}
uint32_t b = (byteswapped & 31) << 3;
uint32_t g = ((byteswapped >> 5) & 63) << 2;
uint32_t r = ((byteswapped >> 11) & 31) << 3;
#if 0
b = (b > 248) * 255 + (b <= 248) * b;
g = (g > 248) * 255 + (g <= 248) * g;
r = (r > 248) * 255 + (r <= 248) * r;
#endif
return r + (g << 8) + (b << 16) + (0xff << 24);
}
static inline uint16_t ctx_565_pack(uint8_t red, uint8_t green, uint8_t blue,
const int byteswap) {
#if 0
// is this extra precision warranted?
// for 332 it gives more pure white..
// it might be the case also for generic 565
red = ctx_sadd8(red, 4);
green = ctx_sadd8(green, 3);
blue = ctx_sadd8(blue, 4);
#endif
uint32_t c = (red >> 3) << 11;
c |= (green >> 2) << 5;
c |= blue >> 3;
if (byteswap) {
return (c >> 8) | (c << 8);
} /* swap bytes */
return c;
}
#define U8_LERP(a, b, t) ((a) + ((((b) - (a)) * t + 256) >> 8))
extern uint8_t st3m_pal[256 * 3];
EXT_RAM_BSS_ATTR static uint16_t st3m_pal16[256];
// https://pippin.gimp.org/a_dither/
#define a_dither(x, y, divisor) \
((((((x) + (y)*236) * 119) & 255) - 127) / divisor)
static void flow3r_bsp_prep_blit(flow3r_bsp_gc9a01_blit_t *blit,
int pix_count) {
int scale = blit->scale;
const uint8_t *fb = blit->fb;
const uint8_t *osd_fb = blit->osd_fb;
unsigned int start_off = blit->off;
unsigned int pxstride = 240;
unsigned int end_off = start_off + pix_count;
unsigned int o = 0;
if (scale > 1) {
/* XXX : this code has room for optimization, in particular
when memcpy of preceding scanlines should be used instead
of recomputing the scanline
*/
if (osd_fb && (start_off < blit->osd_y1 * 240)) {
switch (blit->bits) {
case 1:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
// TODO: add OSD
temp_blit[o++] =
blit->pal_16[(fb[j / 8] >> ((j & 7))) & 0x1];
}
break;
case 2:
for (unsigned int i = start_off; i < end_off; i++) {
// TODO: add OSD
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
temp_blit[o++] =
blit->pal_16[(fb[j / 4] >> ((j & 3) * 2)) & 0x3];
}
break;
case 4:
for (unsigned int i = start_off; i < end_off; i++) {
// TODO: add OSD
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
temp_blit[o++] =
blit->pal_16[(fb[j / 2] >> ((j & 1) * 4)) & 0xf];
}
break;
case 8:
case 9:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * pxstride) + x / scale;
int j2 = ((y / scale) * 240) + x / scale;
int idx = fb[j];
uint8_t r = (((idx >> 5) & 7) * 255) / 7;
uint8_t g = (((idx >> 2) & 7) * 255) / 7;
uint8_t b =
((((idx & 3) << 1) | ((idx >> 2) & 1)) * 255) / 7;
uint8_t ya = osd_fb[j2 * 4 + 3];
r = U8_LERP(r, osd_fb[j2 * 4 + 0], ya);
g = U8_LERP(g, osd_fb[j2 * 4 + 1], ya);
b = U8_LERP(b, osd_fb[j2 * 4 + 2], ya);
idx = ((ctx_sadd8(r, 15) >> 5) << 5) |
((ctx_sadd8(g, 15) >> 5) << 2) |
(ctx_sadd8(b, 15) >> 6);
temp_blit[o++] = blit->pal_16[idx];
}
break;
case 24:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
int j4 = j * 4;
uint8_t sr = osd_fb[j4 + 0];
uint8_t sg = osd_fb[j4 + 1];
uint8_t sb = osd_fb[j4 + 2];
uint8_t sa = osd_fb[j4 + 3];
int j3 = j * 3;
uint8_t r = U8_LERP(fb[j3 + 0], sr, sa);
uint8_t g = U8_LERP(fb[j3 + 1], sg, sa);
uint8_t b = U8_LERP(fb[j3 + 2], sb, sa);
temp_blit[o++] = ctx_565_pack(r, g, b, 1);
}
break;
case 32:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
int j4 = j * 4;
uint8_t sr = osd_fb[j4 + 0];
uint8_t sg = osd_fb[j4 + 1];
uint8_t sb = osd_fb[j4 + 2];
uint8_t sa = osd_fb[j4 + 3];
uint8_t r = U8_LERP(fb[j4 + 0], sr, sa);
uint8_t g = U8_LERP(fb[j4 + 1], sg, sa);
uint8_t b = U8_LERP(fb[j4 + 2], sb, sa);
temp_blit[o++] = ctx_565_pack(r, g, b, 1);
}
break;
case 16:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * pxstride) + x / scale;
int j2 = ((y / scale) * 240) + x / scale;
uint32_t col =
ctx_565_unpack_32(((uint16_t *)fb)[j], 1);
uint8_t *rgba = (uint8_t *)&col;
j2 *= 4;
uint8_t sr = osd_fb[j2];
uint8_t sg = osd_fb[j2 + 1];
uint8_t sb = osd_fb[j2 + 2];
uint8_t sa = osd_fb[j2 + 3];
uint8_t dr = U8_LERP(rgba[0], sr, sa);
uint8_t dg = U8_LERP(rgba[1], sg, sa);
uint8_t db = U8_LERP(rgba[2], sb, sa);
temp_blit[o++] = ctx_565_pack(dr, dg, db, 1);
}
break;
}
} else {
switch (blit->bits) {
case 1:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
temp_blit[o++] =
blit->pal_16[(fb[j / 8] >> ((j & 7))) & 0x1];
}
break;
case 2:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
temp_blit[o++] =
blit->pal_16[(fb[j / 4] >> ((j & 3) * 2)) & 0x3];
}
break;
case 4:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
temp_blit[o++] =
blit->pal_16[(fb[j / 2] >> ((j & 1) * 4)) & 0xf];
}
break;
case 16:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * pxstride) + x / scale;
temp_blit[o++] = ((uint16_t *)fb)[j];
}
break;
case 8:
case 9:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * pxstride) + x / scale;
temp_blit[o++] = blit->pal_16[fb[j]];
}
break;
case 24:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
temp_blit[o++] = ctx_565_pack(
fb[j * 3 + 0], fb[j * 3 + 1], fb[j * 3 + 2], 1);
}
break;
case 32:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = ((y / scale) * 240) + x / scale;
temp_blit[o++] = ctx_565_pack(
fb[j * 4 + 0], fb[j * 4 + 1], fb[j * 4 + 2], 1);
}
break;
}
}
}
else { // 1x scale
if (osd_fb && ((start_off < blit->osd_y1 * 240))) switch (blit->bits) {
case 1:
// TODO: OSD
for (unsigned int i = start_off; i < end_off; i++)
temp_blit[o++] =
blit->pal_16[(fb[i / 8] >> ((i & 7))) & 0x1];
break;
case 2:
// TODO: OSD
for (unsigned int i = start_off; i < end_off; i++)
temp_blit[o++] =
blit->pal_16[(fb[i / 4] >> ((i & 3) * 2)) & 0x3];
break;
case 4:
// TODO: OSD
for (unsigned int i = start_off; i < end_off; i++) {
temp_blit[o++] =
blit->pal_16[(fb[i / 2] >> ((i & 1) * 4)) & 0xf];
}
break;
case 8:
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = (y * 240) + x;
temp_blit[o++] = blit->pal_16[U8_LERP(
fb[j], osd_fb[i * 4 + 1], osd_fb[i * 4 + 3])];
}
break;
case 9: // RGB332
for (unsigned int i = start_off; i < end_off; i++) {
int x = i % 240;
int y = i / 240;
int j = (y * 240) + x;
int idx = fb[j];
uint8_t r = (((idx >> 5) & 7) * 255) / 7;
uint8_t g = (((idx >> 2) & 7) * 255) / 7;
uint8_t b =
((((idx & 3) << 1) | ((idx >> 2) & 1)) * 255) / 7;
uint8_t ya = osd_fb[i * 4 + 3];
r = U8_LERP(r, osd_fb[i * 4 + 0], ya);
g = U8_LERP(g, osd_fb[i * 4 + 1], ya);
b = U8_LERP(b, osd_fb[i * 4 + 2], ya);
idx = ((ctx_sadd8(r, 15) >> 5) << 5) |
((ctx_sadd8(g, 15) >> 5) << 2) |
(ctx_sadd8(b, 15) >> 6);
temp_blit[o++] = blit->pal_16[idx];
}
break;
case 24:
for (unsigned int i = start_off; i < end_off; i++) {
unsigned int i4 = i * 4;
uint8_t sr = osd_fb[i4 + 0];
uint8_t sg = osd_fb[i4 + 1];
uint8_t sb = osd_fb[i4 + 2];
uint8_t sa = osd_fb[i4 + 3];
unsigned int i3 = i * 3;
uint8_t r = U8_LERP(fb[i3 + 0], sr, sa);
uint8_t g = U8_LERP(fb[i3 + 1], sg, sa);
uint8_t b = U8_LERP(fb[i3 + 2], sb, sa);
temp_blit[o++] = ctx_565_pack(r, g, b, 1);
}
break;
case 32:
for (unsigned int i = start_off; i < end_off; i++) {
unsigned int i4 = i * 4;
uint8_t sr = osd_fb[i4 + 0];
uint8_t sg = osd_fb[i4 + 1];
uint8_t sb = osd_fb[i4 + 2];
uint8_t sa = osd_fb[i4 + 3];
uint8_t r = U8_LERP(fb[i4 + 0], sr, sa);
uint8_t g = U8_LERP(fb[i4 + 1], sg, sa);
uint8_t b = U8_LERP(fb[i4 + 2], sb, sa);
temp_blit[o++] = ctx_565_pack(r, g, b, 1);
}
break;
case 16: {
int y = start_off / 240;
int x = start_off % 240;
int j = y * 240 + x;
for (unsigned int i = start_off; i < end_off; i++) {
uint32_t col =
ctx_565_unpack_32(((uint16_t *)fb)[j], 1);
uint8_t *rgba = (uint8_t *)&col;
int i4 = i * 4;
uint8_t sr = osd_fb[i4];
uint8_t sg = osd_fb[i4 + 1];
uint8_t sb = osd_fb[i4 + 2];
uint8_t sa = osd_fb[i4 + 3];
uint8_t dr = U8_LERP(rgba[0], sr, sa);
uint8_t dg = U8_LERP(rgba[1], sg, sa);
uint8_t db = U8_LERP(rgba[2], sb, sa);
temp_blit[o++] = ctx_565_pack(dr, dg, db, 1);
j++;
}
} break;
}
else {
switch (blit->bits) {
case 16:
blit->spi_tx.tx_buffer = &blit->fb[start_off * 2];
break;
case 1:
for (unsigned int i = start_off; i < end_off; i++)
temp_blit[o++] =
blit->pal_16[(fb[i / 8] >> ((i & 7))) & 0x1];
break;
case 2:
for (unsigned int i = start_off; i < end_off; i++)
temp_blit[o++] =
blit->pal_16[(fb[i / 4] >> ((i & 3) * 2)) & 0x3];
break;
case 4:
for (unsigned int i = start_off; i < end_off; i++) {
temp_blit[o++] =
blit->pal_16[(fb[i / 2] >> ((i & 1) * 4)) & 0xf];
}
break;
case 8:
case 9:
for (unsigned int i = start_off; i < end_off; i++)
temp_blit[o++] = blit->pal_16[fb[i]];
break;
case 24:
for (unsigned int i = start_off; i < end_off; i++)
temp_blit[o++] = ctx_565_pack(
fb[i * 3 + 0], fb[i * 3 + 1], fb[i * 3 + 2], 1);
break;
case 32: {
int x = start_off % 240;
int y = start_off / 240;
uint8_t *src = (uint8_t *)&fb[start_off * 4];
for (unsigned int i = start_off; i < end_off; i++) {
uint8_t rgba[4];
{
int val = src[0] + a_dither(x, y, 32);
if (val < 0) val = 0;
if (val > 255) val = 255;
rgba[0] = val;
}
{
int val = src[1] + a_dither(x, y, 16);
if (val < 0) val = 0;
if (val > 255) val = 255;
rgba[1] = val;
}
{
int val = src[2] + a_dither(x, y, 32);
if (val < 0) val = 0;
if (val > 255) val = 255;
rgba[2] = val;
}
temp_blit[o++] =
ctx_565_pack(rgba[0], rgba[1], rgba[2], 1);
src += 4;
x++;
if (x == 240) {
x = 0;
y++;
}
}
} break;
}
}
}
blit->off += pix_count;
}
static inline esp_err_t flow3r_bsp_gc9a01_blit_next(
flow3r_bsp_gc9a01_blit_t *blit) {
size_t size = blit->left;
if (size > SPI_MAX_DMA_LEN) {
size = SPI_MAX_DMA_LEN;
}
unsigned int pix_count = size / 2;
blit->gc9a01_tx.gc9a01 = blit->gc9a01;
blit->gc9a01_tx.dc = 1;
......@@ -572,12 +1008,11 @@ static esp_err_t flow3r_bsp_gc9a01_blit_next(flow3r_bsp_gc9a01_blit_t *blit) {
// Memzero spi_tx as it gets written by the SPI driver after each
// transaction.
memset(&blit->spi_tx, 0, sizeof(spi_transaction_t));
blit->spi_tx.length = size * 8;
blit->spi_tx.tx_buffer = blit->fb;
blit->spi_tx.length = pix_count * 16;
blit->spi_tx.tx_buffer = temp_blit;
blit->spi_tx.user = &blit->gc9a01_tx;
flow3r_bsp_prep_blit(blit, pix_count);
blit->left -= size;
blit->fb += size;
esp_err_t res =
spi_device_queue_trans(blit->gc9a01->spi, &blit->spi_tx, portMAX_DELAY);
......@@ -594,12 +1029,29 @@ static esp_err_t flow3r_bsp_gc9a01_blit_next(flow3r_bsp_gc9a01_blit_t *blit) {
static esp_err_t flow3r_bsp_gc9a01_blit_start(flow3r_bsp_gc9a01_t *gc9a01,
flow3r_bsp_gc9a01_blit_t *blit,
const uint16_t *fb) {
const uint16_t *fb, int bits,
int scale, const void *osd_fb,
int osd_x0, int osd_y0,
int osd_x1, int osd_y1) {
memset(blit, 0, sizeof(flow3r_bsp_gc9a01_blit_t));
blit->gc9a01 = gc9a01;
blit->fb = (const uint8_t *)fb;
blit->left = 2 * 240 * 240;
blit->bits = bits;
blit->osd_fb = (const uint8_t *)osd_fb;
blit->osd_x0 = osd_x0;
blit->osd_x1 = osd_x1;
blit->osd_y0 = osd_y0;
blit->osd_y1 = osd_y1;
blit->scale = scale;
blit->left = 2 * 240 * 240; // left in native bytes (16bpp)
if (bits < 16) {
uint8_t *pal_24 = st3m_pal;
blit->pal_16 = st3m_pal16;
for (int i = 0; i < 256; i++)
blit->pal_16[i] = ctx_565_pack(pal_24[i * 3 + 0], pal_24[i * 3 + 1],
pal_24[i * 3 + 2], 1);
}
return flow3r_bsp_gc9a01_cmd_sync(gc9a01, Cmd_RAMWR);
}
......@@ -613,15 +1065,16 @@ static esp_err_t flow3r_bsp_gc9a01_blit_wait_done(
spi_transaction_t *tx_done;
esp_err_t ret =
spi_device_get_trans_result(blit->gc9a01->spi, &tx_done, ticks_to_wait);
// TODO(q3k): validate that tx_done corresponds to the spi_transaction_tx in
// bilt. If not, this means we got some sequencing failure to deal with.
return ret;
}
esp_err_t flow3r_bsp_gc9a01_blit_full(flow3r_bsp_gc9a01_t *gc9a01,
const uint16_t *fb) {
esp_err_t flow3r_bsp_gc9a01_blit_osd(flow3r_bsp_gc9a01_t *gc9a01,
const void *fb, int bits, int scale,
const void *osd_fb, int osd_x0, int osd_y0,
int osd_x1, int osd_y1) {
flow3r_bsp_gc9a01_blit_t blit;
esp_err_t res = flow3r_bsp_gc9a01_blit_start(gc9a01, &blit, fb);
esp_err_t res = flow3r_bsp_gc9a01_blit_start(
gc9a01, &blit, fb, bits, scale, osd_fb, osd_x0, osd_y0, osd_x1, osd_y1);
if (res != ESP_OK) {
return res;
}
......@@ -638,3 +1091,8 @@ esp_err_t flow3r_bsp_gc9a01_blit_full(flow3r_bsp_gc9a01_t *gc9a01,
}
return ESP_OK;
}
esp_err_t flow3r_bsp_gc9a01_blit_full(flow3r_bsp_gc9a01_t *gc9a01,
const void *fb, int bits) {
return flow3r_bsp_gc9a01_blit_osd(gc9a01, fb, bits, 1, NULL, 0, 0, 0, 0);
}
......@@ -64,8 +64,15 @@ esp_err_t flow3r_bsp_gc9a01_init(flow3r_bsp_gc9a01_t *gc9a01,
// This must not be called if another blit is being performed. The user code
// should sequence access and make sure not more than one blit is performed
// simultaneously.
//
// if overlay is provided we want it composited in, the pixel format of overlay
// depends on bits - it is presumed to be the same size as fb.
esp_err_t flow3r_bsp_gc9a01_blit_full(flow3r_bsp_gc9a01_t *gc9a01,
const uint16_t *fb);
const void *fb, int bits);
esp_err_t flow3r_bsp_gc9a01_blit_osd(flow3r_bsp_gc9a01_t *gc9a01,
const void *fb, int bits, int scale,
const void *osd_fb, int osd_x0, int osd_y0,
int osd_x1, int osd_y1);
// Set backlight for display, using integer percent value (0-100, clamped).
esp_err_t flow3r_bsp_gc9a01_backlight_set(flow3r_bsp_gc9a01_t *gc9a01,
......
......@@ -210,7 +210,7 @@ esp_err_t flow3r_bsp_imu_init(flow3r_bsp_imu_t *imu) {
rslt = bmp5_init(&imu->bmp);
bmp5_error_codes_print_result("bmp5_init", rslt);
if (rslt != BMP5_OK) return ESP_FAIL;
if (rslt != BMP5_OK && rslt != BMP5_E_POWER_UP) return ESP_FAIL;
rslt = set_bmp_config(&imu->osr_odr_press_cfg, &imu->bmp);
if (rslt != BMP5_OK) return ESP_FAIL;
......
#include "flow3r_bsp_max98091.h"
#include <sys/param.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
......@@ -11,6 +13,69 @@
static const char *TAG = "flow3r-bsp-max98091";
/* values generated with
* https://www.earlevel.com/main/2021/09/02/biquad-calculator-v3/ note: a and b
* are flipped in this calculator. a0 must be 1.0
*/
static flow3r_bsp_max98091_biquad_t speaker_eq[7] = {
// soft bass cut below 250Hz. The speakers can't go much
// lower so you just burn power and add unnecessary distortion
// at high volumes. q = 0.71 for a mild resonance around cutoff.
{ .is_active = true,
.gain = 1,
.a1 = -1.953907993635898,
.a2 = 0.9549547008658794,
.b0 = 0.9772156736254444,
.b1 = -1.9544313472508887,
.b2 = 0.9772156736254444 },
// bass boost test, 300Hz q = 2 resonant low pass, doesn't do much
{ .is_active = false,
.gain = 0.5,
.a1 = -1.9790339454615058,
.a2 = 0.9805608861277517,
.b0 = 0.9898987078973144,
.b1 = -1.9797974157946288,
.b2 = 0.9898987078973144 },
// first order high shelf at 1.4KHz/-4.5dB to mellow out
{ .is_active = true,
.gain = 1.,
.a1 = -0.8962133020718939,
.a2 = 0.,
.b0 = 0.6166445890142367,
.b1 = -0.5128578910861306,
.b2 = 0. },
// 2nd order high shelf at 9kHz/-9dB to remove fizz
{ .is_active = true,
.gain = 1.,
.a1 = -0.49825909435330995,
.a2 = 0.,
.b0 = 0.6263246182012638,
.b1 = -0.12458371255457386,
.b2 = 0. },
{ .is_active = false,
.gain = 1.,
.a1 = 0.,
.a2 = 0.,
.b0 = 0.,
.b1 = 0.,
.b2 = 0. },
{ .is_active = false,
.gain = 1.,
.a1 = 0.,
.a2 = 0.,
.b0 = 0.,
.b1 = 0.,
.b2 = 0. },
{ .is_active = false,
.gain = 1.,
.a1 = 0.,
.a2 = 0.,
.b0 = 0.,
.b1 = 0.,
.b2 = 0. }
};
static uint8_t max98091_read(const uint8_t reg) {
const uint8_t tx[] = { reg };
uint8_t rx[1];
......@@ -42,6 +107,10 @@ static esp_err_t max98091_check(const uint8_t reg, const uint8_t data) {
case MAX98091_LINE_TO_ADC:
return ESP_OK;
}
// EQ registers are write only
if ((reg >= 0x46) && (reg <= 0xAE)) return ESP_OK;
uint8_t readback = max98091_read(reg);
if (readback != data) {
ESP_LOGE(TAG, "Write of %02X failed: wanted %02x, got %02x", reg, data,
......@@ -50,6 +119,86 @@ static esp_err_t max98091_check(const uint8_t reg, const uint8_t data) {
return ESP_OK;
}
void flow3r_bsp_max98091_set_speaker_eq(bool enable) {
if (!enable) {
max98091_check(0x41, 0);
return;
}
uint8_t reg = 0x46;
for (uint8_t i = 0; i < 7; i++) {
flow3r_bsp_max98091_biquad_t *bq = &(speaker_eq[i]);
float a1 = 0;
float a2 = 0;
float b0 = 1;
float b1 = 0;
float b2 = 0;
if (bq->is_active && enable) {
a1 = bq->a1;
a2 = bq->a2;
b0 = bq->b0 * bq->gain;
b1 = bq->b1 * bq->gain;
b2 = bq->b2 * bq->gain;
}
for (uint8_t j = 0; j < 5; j++) {
uint32_t data;
switch (j) {
case 0:
data = b0 * (1UL << 20);
break;
case 1:
data = b1 * (1UL << 20);
break;
case 2:
data = b2 * (1UL << 20);
break;
case 3:
data = a1 * (1UL << 20);
break;
case 4:
data = a2 * (1UL << 20);
break;
}
for (uint8_t k = 0; k < 3; k++) {
uint8_t shift = 16 - (k * 8);
if ((reg >= 0x46) && (reg <= 0xAE)) {
// ^tiny safety net
max98091_check(reg, (data >> shift) & 0xFF);
}
reg++;
}
}
}
max98091_check(0x41, 1);
}
void flow3r_bsp_max98091_configure_dynamic_range_control(
bool enable, uint8_t attack, uint8_t release, uint8_t make_up_gain_dB,
uint8_t comp_ratio, uint8_t comp_threshold_dB, uint8_t exp_ratio,
uint8_t exp_threshold_dB) {
if (!enable) {
max98091_check(MAX98091_DRC_TIMING, 0);
return;
}
// clamp some values to datasheet ranges
attack = MIN(7, attack);
release = MIN(7, release);
make_up_gain_dB = MIN(12, make_up_gain_dB);
comp_ratio = MIN(4, comp_ratio);
comp_threshold_dB = MIN(31, comp_threshold_dB);
exp_ratio = MIN(2, exp_ratio);
// the range for this one is -35 to -66dB
uint8_t exp_threshold_internal = MIN(31, MAX(35, exp_threshold_dB) - 35);
max98091_check(MAX98091_DRC_TIMING, attack | release << 4 | enable << 7);
max98091_check(MAX98091_DRC_GAIN, make_up_gain_dB);
max98091_check(MAX98091_DRC_COMPRESSOR,
comp_threshold_dB | comp_ratio << 5);
max98091_check(MAX98091_DRC_EXPANDER,
exp_threshold_internal | exp_ratio << 5);
}
void flow3r_bsp_max98091_register_poke(uint8_t reg, uint8_t data) {
max98091_check(reg, data);
}
......@@ -100,12 +249,12 @@ void flow3r_bsp_max98091_speaker_line_in_set_hardware_thru(bool enable) {
onboard_mic_set_power(false);
}
// TODO(q3k): left/right DAC seem to have been swapped before, double-check.
// Line A -> Left Speaker
// The badge speakers are not stereo so we don't care about channel
// assignment here Line A -> Speaker 1
max98091_check(MAX98091_LEFT_SPK_MIXER,
MAX98091_BOOL(LEFT_SPK_MIXER_LINE_A, enable) |
MAX98091_ON(LEFT_SPK_MIXER_LEFT_DAC));
// Line B -> Right Speaker
// Line B -> Speaker 2
max98091_check(MAX98091_RIGHT_SPK_MIXER,
MAX98091_BOOL(RIGHT_SPK_MIXER_LINE_B, enable) |
MAX98091_ON(RIGHT_SPK_MIXER_RIGHT_DAC));
......@@ -146,20 +295,23 @@ void flow3r_bsp_max98091_input_set_source(
}
}
void flow3r_bsp_max98091_headset_set_gain_dB(uint8_t gain_dB) {
int8_t flow3r_bsp_max98091_headset_set_gain_dB(int8_t gain_dB) {
if (gain_dB > 50) gain_dB = 50;
if (gain_dB < 0) gain_dB = 0;
uint8_t g = gain_dB;
uint8_t pa1en = 0b01;
if (gain_dB > 30) {
gain_dB -= 30;
if (g > 30) {
g -= 30;
pa1en = 0b11;
} else if (gain_dB > 20) {
gain_dB -= 20;
} else if (g > 20) {
g -= 20;
pa1en = 0b10;
}
max98091_check(MAX98091_MIC1_INPUT_LEVEL,
MAX98091_BITS(MIC1_INPUT_LEVEL_PGAM1, 0x14 - gain_dB) |
MAX98091_BITS(MIC1_INPUT_LEVEL_PGAM1, 0x14 - g) |
MAX98091_BITS(MIC1_INPUT_LEVEL_PA1EN, pa1en));
return gain_dB;
}
void flow3r_bsp_max98091_read_jacksense(
......
......@@ -7,10 +7,17 @@
#include "flow3r_bsp.h"
typedef struct {
bool is_active;
float gain;
float a1, a2, b0, b1, b2;
} flow3r_bsp_max98091_biquad_t;
void flow3r_bsp_max98091_init(void);
float flow3r_bsp_max98091_headphones_set_volume(bool mute, float dB);
float flow3r_bsp_max98091_speaker_set_volume(bool mute, float dB);
void flow3r_bsp_max98091_headset_set_gain_dB(uint8_t gain_dB);
int8_t flow3r_bsp_max98091_headset_set_gain_dB(int8_t gain_dB);
void flow3r_bsp_max98091_read_jacksense(flow3r_bsp_audio_jacksense_state_t *st);
void flow3r_bsp_max98091_input_set_source(
flow3r_bsp_audio_input_source_t source);
......@@ -18,3 +25,4 @@ void flow3r_bsp_max98091_headphones_line_in_set_hardware_thru(bool enable);
void flow3r_bsp_max98091_speaker_line_in_set_hardware_thru(bool enable);
void flow3r_bsp_max98091_line_in_set_hardware_thru(bool enable);
void flow3r_bsp_max98091_register_poke(uint8_t reg, uint8_t data);
void flow3r_bsp_max98091_set_speaker_eq(bool enable);
......@@ -140,6 +140,11 @@
#define MAX98091_RIGHT_SPK_VOLUME_SPRM_BASE 7
#define MAX98091_RIGHT_SPK_VOLUME_SPRM_WIDTH 1
#define MAX98091_DRC_TIMING 0x33
#define MAX98091_DRC_COMPRESSOR 0x34
#define MAX98091_DRC_EXPANDER 0x35
#define MAX98091_DRC_GAIN 0x36
#define MAX98091_JACK_DETECT 0x3D
#define MAX98091_INPUT_ENABLE 0x3E
......
......@@ -47,6 +47,7 @@ set(MICROPY_SOURCE_PORT
${MICROPY_PORT_DIR}/gccollect.c
${MICROPY_PORT_DIR}/mphalport.c
${MICROPY_PORT_DIR}/fatfs_port.c
${MICROPY_PORT_DIR}/flow3r_statvfs.c
${MICROPY_PORT_DIR}/help.c
${MICROPY_PORT_DIR}/modutime.c
${MICROPY_PORT_DIR}/machine_pin.c
......@@ -102,11 +103,13 @@ set(IDF_COMPONENTS
esp_timer
esp_netif
esp_psram
fatfs
freertos
hal
heap
log
lwip
mbedtls
newlib
nvs_flash
sdmmc
......@@ -114,6 +117,7 @@ set(IDF_COMPONENTS
spi_flash
ulp
vfs
wear_levelling
xtensa
)
......
......@@ -4,8 +4,8 @@
#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_PY_MACHINE_DAC (0)
#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_HW_I2C0_SCL (9)
#define MICROPY_HW_I2C0_SDA (8)
#define MICROPY_HW_I2C1_SCL (45)
#define MICROPY_HW_I2C1_SDA (17)
#define MICROPY_HW_ESP32S3_EXTENDED_IO (0)
#define MICROPY_ESP_IDF_4 1
......
include("vendor/ports/esp32/boards")
include("vendor/lib/micropython-lib/python-stdlib/os-path")
include("vendor/lib/micropython-lib/python-stdlib/stat")
include("vendor/lib/micropython-lib/python-stdlib/gzip")
include("vendor/lib/micropython-lib/micropython/utarfile")
include("vendor/lib/micropython-lib/micropython/bluetooth/aioble")
include("frozen")
......@@ -16,6 +16,10 @@ target_sources(usermod_badge23 INTERFACE
${CMAKE_CURRENT_LIST_DIR}/mp_sys_display.c
${CMAKE_CURRENT_LIST_DIR}/mp_sys_kernel.c
${CMAKE_CURRENT_LIST_DIR}/mp_uctx.c
${CMAKE_CURRENT_LIST_DIR}/mp_media.c
${CMAKE_CURRENT_LIST_DIR}/mp_sys_mode.c
${CMAKE_CURRENT_LIST_DIR}/mp_sys_colors.c
${CMAKE_CURRENT_LIST_DIR}/mp_sys_scope.c
)
target_include_directories(usermod_badge23 INTERFACE
......
......@@ -28,11 +28,19 @@ STATIC mp_obj_t mp_headphones_are_connected() {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_headphones_are_connected_obj,
mp_headphones_are_connected);
STATIC mp_obj_t mp_headphones_detection_override(mp_obj_t enable) {
st3m_audio_headphones_detection_override(mp_obj_get_int(enable));
STATIC mp_obj_t mp_headphones_detection_override(size_t n_args,
const mp_obj_t *args) {
bool enable = mp_obj_get_int(args[0]);
bool override_state = true;
if (n_args > 1) {
override_state = mp_obj_get_int(args[1]);
}
st3m_audio_headphones_detection_override(enable, override_state);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_headphones_detection_override_obj,
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_headphones_detection_override_obj,
1, 2,
mp_headphones_detection_override);
STATIC mp_obj_t mp_headphones_set_volume_dB(mp_obj_t vol_dB) {
......@@ -195,22 +203,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_volume_relative_obj,
mp_get_volume_relative);
STATIC mp_obj_t mp_headphones_line_in_set_hardware_thru(mp_obj_t enable) {
st3m_audio_headphones_line_in_set_hardware_thru(mp_obj_get_int(enable));
return mp_const_none;
// st3m_audio_headphones_line_in_set_hardware_thru(mp_obj_get_int(enable));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_headphones_line_in_set_hardware_thru_obj,
mp_headphones_line_in_set_hardware_thru);
STATIC mp_obj_t mp_speaker_line_in_set_hardware_thru(mp_obj_t enable) {
st3m_audio_speaker_line_in_set_hardware_thru(mp_obj_get_int(enable));
return mp_const_none;
// st3m_audio_speaker_line_in_set_hardware_thru(mp_obj_get_int(enable));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_speaker_line_in_set_hardware_thru_obj,
mp_speaker_line_in_set_hardware_thru);
STATIC mp_obj_t mp_line_in_set_hardware_thru(mp_obj_t enable) {
st3m_audio_line_in_set_hardware_thru(mp_obj_get_int(enable));
return mp_const_none;
// st3m_audio_line_in_set_hardware_thru(mp_obj_get_int(enable));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_line_in_set_hardware_thru_obj,
mp_line_in_set_hardware_thru);
......@@ -219,29 +227,111 @@ STATIC mp_obj_t mp_line_in_is_connected() {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_line_in_is_connected_obj,
mp_line_in_is_connected);
STATIC mp_obj_t mp_input_set_source(mp_obj_t source) {
st3m_audio_input_set_source(mp_obj_get_int(source));
// <INPUT SETUP>
// engines
STATIC mp_obj_t mp_input_engines_set_source(mp_obj_t source) {
st3m_audio_input_engines_set_source(mp_obj_get_int(source));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_input_engines_set_source_obj,
mp_input_engines_set_source);
STATIC mp_obj_t mp_input_engines_get_source(void) {
return mp_obj_new_int(st3m_audio_input_engines_get_source());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_input_engines_get_source_obj,
mp_input_engines_get_source);
STATIC mp_obj_t mp_input_engines_get_target_source(void) {
return mp_obj_new_int(st3m_audio_input_engines_get_target_source());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_input_engines_get_target_source_obj,
mp_input_engines_get_target_source);
STATIC mp_obj_t mp_input_engines_get_source_avail(mp_obj_t source) {
return mp_obj_new_int(
st3m_audio_input_engines_get_source_avail(mp_obj_get_int(source)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_input_engines_get_source_avail_obj,
mp_input_engines_get_source_avail);
// thru
STATIC mp_obj_t mp_input_thru_set_source(mp_obj_t source) {
st3m_audio_input_thru_set_source(mp_obj_get_int(source));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_input_set_source_obj, mp_input_set_source);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_input_thru_set_source_obj,
mp_input_thru_set_source);
STATIC mp_obj_t mp_input_thru_get_source(void) {
return mp_obj_new_int(st3m_audio_input_thru_get_source());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_input_thru_get_source_obj,
mp_input_thru_get_source);
STATIC mp_obj_t mp_input_thru_get_target_source(void) {
return mp_obj_new_int(st3m_audio_input_thru_get_target_source());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_input_thru_get_target_source_obj,
mp_input_thru_get_target_source);
STATIC mp_obj_t mp_input_thru_get_source_avail(mp_obj_t source) {
return mp_obj_new_int(
st3m_audio_input_thru_get_source_avail(mp_obj_get_int(source)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_input_thru_get_source_avail_obj,
mp_input_thru_get_source_avail);
// actual source
STATIC mp_obj_t mp_input_get_source(void) {
return mp_obj_new_int(st3m_audio_input_get_source());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_input_get_source_obj, mp_input_get_source);
STATIC mp_obj_t mp_headset_set_gain_dB(mp_obj_t gain_dB) {
st3m_audio_headset_set_gain_dB(mp_obj_get_int(gain_dB));
return mp_const_none;
// gain
STATIC mp_obj_t mp_headset_mic_set_gain_dB(mp_obj_t gain_dB) {
float ret = st3m_audio_headset_mic_set_gain_dB(mp_obj_get_float(gain_dB));
return mp_obj_new_float(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_headset_set_gain_dB_obj,
mp_headset_set_gain_dB);
STATIC mp_obj_t mp_headset_get_gain_dB(void) {
return mp_obj_new_int(st3m_audio_headset_get_gain_dB());
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_headset_mic_set_gain_dB_obj,
mp_headset_mic_set_gain_dB);
STATIC mp_obj_t mp_headset_mic_get_gain_dB(void) {
return mp_obj_new_float(st3m_audio_headset_mic_get_gain_dB());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_headset_mic_get_gain_dB_obj,
mp_headset_mic_get_gain_dB);
STATIC mp_obj_t mp_onboard_mic_set_gain_dB(mp_obj_t gain_dB) {
float ret = st3m_audio_onboard_mic_set_gain_dB(mp_obj_get_float(gain_dB));
return mp_obj_new_float(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_headset_get_gain_dB_obj,
mp_headset_get_gain_dB);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_onboard_mic_set_gain_dB_obj,
mp_onboard_mic_set_gain_dB);
STATIC mp_obj_t mp_onboard_mic_get_gain_dB(void) {
return mp_obj_new_float(st3m_audio_onboard_mic_get_gain_dB());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_onboard_mic_get_gain_dB_obj,
mp_onboard_mic_get_gain_dB);
STATIC mp_obj_t mp_line_in_set_gain_dB(mp_obj_t gain_dB) {
float ret = st3m_audio_line_in_set_gain_dB(mp_obj_get_float(gain_dB));
return mp_obj_new_float(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_line_in_set_gain_dB_obj,
mp_line_in_set_gain_dB);
STATIC mp_obj_t mp_line_in_get_gain_dB(void) {
return mp_obj_new_float(st3m_audio_line_in_get_gain_dB());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_line_in_get_gain_dB_obj,
mp_line_in_get_gain_dB);
STATIC mp_obj_t mp_input_thru_set_volume_dB(mp_obj_t vol_dB) {
return mp_obj_new_float(
......@@ -269,6 +359,94 @@ STATIC mp_obj_t mp_input_thru_get_mute() {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_input_thru_get_mute_obj,
mp_input_thru_get_mute);
// eq
STATIC mp_obj_t mp_speaker_get_eq_on() {
return mp_obj_new_int(st3m_audio_speaker_get_eq_on());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_speaker_get_eq_on_obj,
mp_speaker_get_eq_on);
STATIC mp_obj_t mp_speaker_set_eq_on(mp_obj_t eq_on) {
st3m_audio_speaker_set_eq_on(mp_obj_get_int(eq_on));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_speaker_set_eq_on_obj,
mp_speaker_set_eq_on);
// permissions
STATIC mp_obj_t mp_headset_mic_set_allowed(mp_obj_t allowed) {
st3m_audio_headset_mic_set_allowed(mp_obj_get_int(allowed));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_headset_mic_set_allowed_obj,
mp_headset_mic_set_allowed);
STATIC mp_obj_t mp_headset_mic_get_allowed() {
return mp_obj_new_int(st3m_audio_headset_mic_get_allowed());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_headset_mic_get_allowed_obj,
mp_headset_mic_get_allowed);
STATIC mp_obj_t mp_onboard_mic_set_allowed(mp_obj_t allowed) {
st3m_audio_onboard_mic_set_allowed(mp_obj_get_int(allowed));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_onboard_mic_set_allowed_obj,
mp_onboard_mic_set_allowed);
STATIC mp_obj_t mp_onboard_mic_get_allowed() {
return mp_obj_new_int(st3m_audio_onboard_mic_get_allowed());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_onboard_mic_get_allowed_obj,
mp_onboard_mic_get_allowed);
STATIC mp_obj_t mp_line_in_set_allowed(mp_obj_t allowed) {
st3m_audio_line_in_set_allowed(mp_obj_get_int(allowed));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_line_in_set_allowed_obj,
mp_line_in_set_allowed);
STATIC mp_obj_t mp_line_in_get_allowed() {
return mp_obj_new_int(st3m_audio_line_in_get_allowed());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_line_in_get_allowed_obj,
mp_line_in_get_allowed);
STATIC mp_obj_t mp_onboard_mic_to_speaker_set_allowed(mp_obj_t allowed) {
st3m_audio_onboard_mic_to_speaker_set_allowed(mp_obj_get_int(allowed));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_onboard_mic_to_speaker_set_allowed_obj,
mp_onboard_mic_to_speaker_set_allowed);
STATIC mp_obj_t mp_onboard_mic_to_speaker_get_allowed() {
return mp_obj_new_int(st3m_audio_onboard_mic_to_speaker_get_allowed());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_onboard_mic_to_speaker_get_allowed_obj,
mp_onboard_mic_to_speaker_get_allowed);
// </INPUT SETUP>
STATIC mp_obj_t mp_codec_configure_dynamic_range_control(size_t n_args,
const mp_obj_t *args) {
flow3r_bsp_max98091_configure_dynamic_range_control(
(bool)mp_obj_get_int(args[0]), // enable
(uint8_t)mp_obj_get_int(args[1]), // attack
(uint8_t)mp_obj_get_int(args[2]), // release
(uint8_t)mp_obj_get_int(args[3]), // make_up_gain_dB
(uint8_t)mp_obj_get_int(args[4]), // comp_ratio
(uint8_t)abs(mp_obj_get_int(args[5])), // comp_threshold_dB
(uint8_t)mp_obj_get_int(args[6]), // exp_ratio
(uint8_t)abs(mp_obj_get_int(args[7])) // exp_threshold_dB
);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
mp_codec_configure_dynamic_range_control_obj, 8, 8,
mp_codec_configure_dynamic_range_control);
STATIC mp_obj_t mp_codec_i2c_write(mp_obj_t reg_in, mp_obj_t data_in) {
#if defined(CONFIG_FLOW3R_HW_GEN_P3) || defined(CONFIG_FLOW3R_HW_GEN_P4) || \
defined(CONFIG_FLOW3R_HW_GEN_C23)
......@@ -359,15 +537,44 @@ STATIC const mp_rom_map_elem_t mp_module_audio_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_line_in_is_connected),
MP_ROM_PTR(&mp_line_in_is_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_set_source),
MP_ROM_PTR(&mp_input_set_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_engines_set_source),
MP_ROM_PTR(&mp_input_engines_set_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_engines_get_source),
MP_ROM_PTR(&mp_input_engines_get_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_engines_get_target_source),
MP_ROM_PTR(&mp_input_engines_get_target_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_engines_get_source_avail),
MP_ROM_PTR(&mp_input_engines_get_source_avail_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_set_source),
MP_ROM_PTR(&mp_input_thru_set_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_get_source),
MP_ROM_PTR(&mp_input_thru_get_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_get_target_source),
MP_ROM_PTR(&mp_input_thru_get_target_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_get_source_avail),
MP_ROM_PTR(&mp_input_thru_get_source_avail_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_get_source),
MP_ROM_PTR(&mp_input_get_source_obj) },
// TODO: DEPRECATE
{ MP_ROM_QSTR(MP_QSTR_input_set_source),
MP_ROM_PTR(&mp_input_engines_set_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_mic_set_gain_dB),
MP_ROM_PTR(&mp_headset_mic_set_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_mic_get_gain_dB),
MP_ROM_PTR(&mp_headset_mic_get_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_set_gain_dB),
MP_ROM_PTR(&mp_onboard_mic_set_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_get_gain_dB),
MP_ROM_PTR(&mp_onboard_mic_get_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_set_gain_dB),
MP_ROM_PTR(&mp_headset_set_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_get_gain_dB),
MP_ROM_PTR(&mp_headset_get_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_set_gain_dB),
MP_ROM_PTR(&mp_line_in_set_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_get_gain_dB),
MP_ROM_PTR(&mp_line_in_get_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_set_volume_dB),
MP_ROM_PTR(&mp_input_thru_set_volume_dB_obj) },
......@@ -381,6 +588,9 @@ STATIC const mp_rom_map_elem_t mp_module_audio_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_codec_i2c_write),
MP_ROM_PTR(&mp_codec_i2c_write_obj) },
{ MP_ROM_QSTR(MP_QSTR__codec_configure_dynamic_range_control),
MP_ROM_PTR(&mp_codec_configure_dynamic_range_control_obj) },
{ MP_ROM_QSTR(MP_QSTR_INPUT_SOURCE_NONE),
MP_ROM_INT(st3m_audio_input_source_none) },
{ MP_ROM_QSTR(MP_QSTR_INPUT_SOURCE_LINE_IN),
......@@ -389,6 +599,30 @@ STATIC const mp_rom_map_elem_t mp_module_audio_globals_table[] = {
MP_ROM_INT(st3m_audio_input_source_headset_mic) },
{ MP_ROM_QSTR(MP_QSTR_INPUT_SOURCE_ONBOARD_MIC),
MP_ROM_INT(st3m_audio_input_source_onboard_mic) },
{ MP_ROM_QSTR(MP_QSTR_INPUT_SOURCE_AUTO),
MP_ROM_INT(st3m_audio_input_source_auto) },
{ MP_ROM_QSTR(MP_QSTR_speaker_get_eq_on),
MP_ROM_PTR(&mp_speaker_get_eq_on_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_set_eq_on),
MP_ROM_PTR(&mp_speaker_set_eq_on_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_mic_get_allowed),
MP_ROM_PTR(&mp_headset_mic_get_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_mic_set_allowed),
MP_ROM_PTR(&mp_headset_mic_set_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_get_allowed),
MP_ROM_PTR(&mp_onboard_mic_get_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_set_allowed),
MP_ROM_PTR(&mp_onboard_mic_set_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_get_allowed),
MP_ROM_PTR(&mp_line_in_get_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_set_allowed),
MP_ROM_PTR(&mp_line_in_set_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_to_speaker_get_allowed),
MP_ROM_PTR(&mp_onboard_mic_to_speaker_get_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_to_speaker_set_allowed),
MP_ROM_PTR(&mp_onboard_mic_to_speaker_set_allowed_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_audio_globals,
......@@ -400,3 +634,175 @@ const mp_obj_module_t mp_module_audio = {
};
MP_REGISTER_MODULE(MP_QSTR_audio, mp_module_audio);
STATIC const mp_rom_map_elem_t mp_module_sys_audio_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys_audio) },
{ MP_ROM_QSTR(MP_QSTR_headset_is_connected),
MP_ROM_PTR(&mp_headset_is_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_are_connected),
MP_ROM_PTR(&mp_headphones_are_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_detection_override),
MP_ROM_PTR(&mp_headphones_detection_override_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_set_volume_dB),
MP_ROM_PTR(&mp_headphones_set_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_set_volume_dB),
MP_ROM_PTR(&mp_speaker_set_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_volume_dB), MP_ROM_PTR(&mp_set_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_adjust_volume_dB),
MP_ROM_PTR(&mp_headphones_adjust_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_adjust_volume_dB),
MP_ROM_PTR(&mp_speaker_adjust_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_adjust_volume_dB),
MP_ROM_PTR(&mp_adjust_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_get_volume_dB),
MP_ROM_PTR(&mp_headphones_get_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_get_volume_dB),
MP_ROM_PTR(&mp_speaker_get_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_volume_dB), MP_ROM_PTR(&mp_get_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_get_mute),
MP_ROM_PTR(&mp_headphones_get_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_get_mute),
MP_ROM_PTR(&mp_speaker_get_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_mute), MP_ROM_PTR(&mp_get_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_set_mute),
MP_ROM_PTR(&mp_headphones_set_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_set_mute),
MP_ROM_PTR(&mp_speaker_set_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_mute), MP_ROM_PTR(&mp_set_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_set_minimum_volume_dB),
MP_ROM_PTR(&mp_headphones_set_minimum_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_set_minimum_volume_dB),
MP_ROM_PTR(&mp_speaker_set_minimum_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_set_maximum_volume_dB),
MP_ROM_PTR(&mp_headphones_set_maximum_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_set_maximum_volume_dB),
MP_ROM_PTR(&mp_speaker_set_maximum_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_get_minimum_volume_dB),
MP_ROM_PTR(&mp_headphones_get_minimum_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_get_minimum_volume_dB),
MP_ROM_PTR(&mp_speaker_get_minimum_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_get_maximum_volume_dB),
MP_ROM_PTR(&mp_headphones_get_maximum_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_get_maximum_volume_dB),
MP_ROM_PTR(&mp_speaker_get_maximum_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_get_volume_relative),
MP_ROM_PTR(&mp_headphones_get_volume_relative_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_get_volume_relative),
MP_ROM_PTR(&mp_speaker_get_volume_relative_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_volume_relative),
MP_ROM_PTR(&mp_get_volume_relative_obj) },
{ MP_ROM_QSTR(MP_QSTR_headphones_line_in_set_hardware_thru),
MP_ROM_PTR(&mp_headphones_line_in_set_hardware_thru_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_line_in_set_hardware_thru),
MP_ROM_PTR(&mp_speaker_line_in_set_hardware_thru_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_set_hardware_thru),
MP_ROM_PTR(&mp_line_in_set_hardware_thru_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_is_connected),
MP_ROM_PTR(&mp_line_in_is_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_engines_set_source),
MP_ROM_PTR(&mp_input_engines_set_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_engines_get_source),
MP_ROM_PTR(&mp_input_engines_get_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_engines_get_target_source),
MP_ROM_PTR(&mp_input_engines_get_target_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_engines_get_source_avail),
MP_ROM_PTR(&mp_input_engines_get_source_avail_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_set_source),
MP_ROM_PTR(&mp_input_thru_set_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_get_source),
MP_ROM_PTR(&mp_input_thru_get_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_get_target_source),
MP_ROM_PTR(&mp_input_thru_get_target_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_get_source_avail),
MP_ROM_PTR(&mp_input_thru_get_source_avail_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_get_source),
MP_ROM_PTR(&mp_input_get_source_obj) },
// TODO: DEPRECATE
{ MP_ROM_QSTR(MP_QSTR_input_set_source),
MP_ROM_PTR(&mp_input_engines_set_source_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_mic_set_gain_dB),
MP_ROM_PTR(&mp_headset_mic_set_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_mic_get_gain_dB),
MP_ROM_PTR(&mp_headset_mic_get_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_set_gain_dB),
MP_ROM_PTR(&mp_onboard_mic_set_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_get_gain_dB),
MP_ROM_PTR(&mp_onboard_mic_get_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_set_gain_dB),
MP_ROM_PTR(&mp_line_in_set_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_get_gain_dB),
MP_ROM_PTR(&mp_line_in_get_gain_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_set_volume_dB),
MP_ROM_PTR(&mp_input_thru_set_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_get_volume_dB),
MP_ROM_PTR(&mp_input_thru_get_volume_dB_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_set_mute),
MP_ROM_PTR(&mp_input_thru_set_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_input_thru_get_mute),
MP_ROM_PTR(&mp_input_thru_get_mute_obj) },
{ MP_ROM_QSTR(MP_QSTR_codec_i2c_write),
MP_ROM_PTR(&mp_codec_i2c_write_obj) },
{ MP_ROM_QSTR(MP_QSTR__codec_configure_dynamic_range_control),
MP_ROM_PTR(&mp_codec_configure_dynamic_range_control_obj) },
{ MP_ROM_QSTR(MP_QSTR_INPUT_SOURCE_NONE),
MP_ROM_INT(st3m_audio_input_source_none) },
{ MP_ROM_QSTR(MP_QSTR_INPUT_SOURCE_LINE_IN),
MP_ROM_INT(st3m_audio_input_source_line_in) },
{ MP_ROM_QSTR(MP_QSTR_INPUT_SOURCE_HEADSET_MIC),
MP_ROM_INT(st3m_audio_input_source_headset_mic) },
{ MP_ROM_QSTR(MP_QSTR_INPUT_SOURCE_ONBOARD_MIC),
MP_ROM_INT(st3m_audio_input_source_onboard_mic) },
{ MP_ROM_QSTR(MP_QSTR_INPUT_SOURCE_AUTO),
MP_ROM_INT(st3m_audio_input_source_auto) },
{ MP_ROM_QSTR(MP_QSTR_speaker_get_eq_on),
MP_ROM_PTR(&mp_speaker_get_eq_on_obj) },
{ MP_ROM_QSTR(MP_QSTR_speaker_set_eq_on),
MP_ROM_PTR(&mp_speaker_set_eq_on_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_mic_get_allowed),
MP_ROM_PTR(&mp_headset_mic_get_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_headset_mic_set_allowed),
MP_ROM_PTR(&mp_headset_mic_set_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_get_allowed),
MP_ROM_PTR(&mp_onboard_mic_get_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_set_allowed),
MP_ROM_PTR(&mp_onboard_mic_set_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_get_allowed),
MP_ROM_PTR(&mp_line_in_get_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_line_in_set_allowed),
MP_ROM_PTR(&mp_line_in_set_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_to_speaker_get_allowed),
MP_ROM_PTR(&mp_onboard_mic_to_speaker_get_allowed_obj) },
{ MP_ROM_QSTR(MP_QSTR_onboard_mic_to_speaker_set_allowed),
MP_ROM_PTR(&mp_onboard_mic_to_speaker_set_allowed_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_sys_audio_globals,
mp_module_sys_audio_globals_table);
const mp_obj_module_t mp_module_sys_audio = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_sys_audio_globals,
};
MP_REGISTER_MODULE(MP_QSTR_sys_audio, mp_module_sys_audio);
#include "py/builtin.h"
#include "py/objstr.h"
#include "py/parsenum.h"
#include "py/runtime.h"
#include "py/smallint.h"
#include "st3m_captouch.h"
#include "esp_timer.h"
#include "flow3r_bsp_captouch.h"
#include <math.h>
#include <string.h>
STATIC mp_obj_t mp_captouch_calibration_active(void) {
return mp_obj_new_int(st3m_captouch_calibrating());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_calibration_active_obj,
mp_captouch_calibration_active);
// :/
typedef struct _mp_obj_complex_t {
mp_obj_base_t base;
mp_float_t real;
mp_float_t imag;
} mp_obj_complex_t;
STATIC mp_obj_t mp_captouch_calibration_request(void) {
st3m_captouch_request_calibration();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_calibration_request_obj,
mp_captouch_calibration_request);
#define LIST_MIN_ALLOC 4
// this looks like the most useless optimization, this is not about caching tho:
// we wanna output data to micropython in floats but!! if we do the conversion
// in the cap touch driver task it can no longer jump between cores and that
// would make us very sad
// so we put the floating point mafh in the micropython task :D
// also we n-e-v-e-r get to use unions and they're so cool :3
typedef union {
float post;
int32_t pre;
} processable;
typedef struct {
processable rad;
processable phi;
processable coverage;
mp_uint_t timestamp;
uint8_t petal : 4;
uint8_t mode : 4;
bool pressed : 1;
bool processed : 1;
} log_frame_data_t;
typedef struct _log_frame_data_ll_t {
log_frame_data_t frame;
struct _log_frame_data_ll_t *next;
} log_frame_data_ll_t;
typedef struct {
mp_obj_base_t base;
mp_obj_t petal;
} mp_captouch_petal_pads_state_t;
log_frame_data_t data;
} mp_captouch_petal_log_frame_t;
const mp_obj_type_t mp_type_captouch_petal_log_frame;
static bool calib_trusted = false;
const mp_obj_type_t captouch_petal_pads_state_type;
// argument: the fastest we can go is like 0.75ms per frame if each chip only
// scans a single pad. we wanna avoid overflowing between thinks and garbage
// collection can be like 50ms (overflowing is somewhat graceish tho we're just
// dropping data) so a total worst case buffer length of 75ms seems reasonable
#define LOG_MAX_LEN 100
typedef struct {
log_frame_data_ll_t *start; // pointer to first (earliest) element in ll
log_frame_data_ll_t *end; // pointer to last (latest) element in ll
int len; // number of elements in log
SemaphoreHandle_t lock; // lock for log
// when we kick the latch with refresh_events we buffer the log slice for
// the next captouch_read here:
log_frame_data_ll_t *latch_buffer_start;
int latch_buffer_len;
SemaphoreHandle_t latch_buffer_lock;
} petal_log_buffer_t;
static uint32_t refresh_time;
static petal_log_buffer_t petal_log[10] = {
0,
};
static bool petal_log_initialized = false;
static bool petal_log_active[10];
static void _add_entry_to_log(uint8_t petal, uint8_t mode, bool pressed,
uint32_t timestamp, int32_t rad, int32_t phi,
int32_t coverage) {
if (petal >= 10) return;
if (!petal_log_active[petal]) return;
// TODO: can't m_new_obj here naively bc different task, fails in
// gc_alloc/mp_thread_get_state there's gotta be a lock, else _threads
// wouldn't work, will look into this sometime soon.
log_frame_data_ll_t *frame_ll = malloc(sizeof(log_frame_data_ll_t));
if (frame_ll == NULL) {
printf("captouch frame init error");
return;
}
frame_ll->next = NULL;
log_frame_data_t *frame = &(frame_ll->frame);
frame->mode = mode;
frame->petal = petal;
frame->processed = false;
frame->pressed = pressed;
frame->timestamp = timestamp & (MICROPY_PY_UTIME_TICKS_PERIOD - 1);
frame->rad.pre = rad;
frame->phi.pre = phi;
frame->coverage.pre = coverage;
// insert into linked list
petal_log_buffer_t *log = &(petal_log[petal]);
log_frame_data_ll_t *runaway = NULL;
xSemaphoreTake(log->lock, portMAX_DELAY);
if (log->len >= LOG_MAX_LEN) {
runaway = log->start;
log->start = log->start->next;
log->len--;
}
if (log->len == 0) {
assert(log->start == NULL);
assert(log->end == NULL);
log->start = frame_ll;
log->end = frame_ll;
} else {
log->end->next = frame_ll;
}
log->len++;
log->end = frame_ll;
xSemaphoreGive(log->lock);
free(runaway);
}
static void _kick_log_latch(uint8_t petal) {
petal_log_buffer_t *log = &(petal_log[petal]);
if (log->lock == NULL) return;
xSemaphoreTake(log->lock, portMAX_DELAY);
int len = log->len;
log_frame_data_ll_t *start = log->start;
log->len = 0;
log->start = NULL;
log->end = NULL;
xSemaphoreGive(log->lock);
xSemaphoreTake(log->latch_buffer_lock, portMAX_DELAY);
log_frame_data_ll_t *runaway = log->latch_buffer_start;
log->latch_buffer_len = len;
log->latch_buffer_start = start;
xSemaphoreGive(log->latch_buffer_lock);
while (runaway) {
log_frame_data_ll_t *runaway_next = runaway->next;
free(runaway);
runaway = runaway_next;
}
}
static mp_obj_t _get_list_from_log(uint8_t petal) {
petal_log_buffer_t *log = &(petal_log[petal]);
mp_obj_list_t *o = m_new_obj(mp_obj_list_t);
if (log->lock == NULL) {
mp_obj_list_init(o, 0);
return MP_OBJ_FROM_PTR(o);
}
xSemaphoreTake(log->latch_buffer_lock, portMAX_DELAY);
const int len = log->latch_buffer_len; // len 0 ok
log_frame_data_ll_t *frame_ll = log->latch_buffer_start;
mp_obj_list_init(o, len);
log_frame_data_ll_t *del[len];
mp_captouch_petal_log_frame_t *frames[len];
for (int i = 0; i < len; i++) {
assert(frame_ll);
frames[i] = m_new(mp_captouch_petal_log_frame_t, 1);
frames[i]->base.type = &mp_type_captouch_petal_log_frame;
memcpy(&(frames[i]->data), &(frame_ll->frame),
sizeof(log_frame_data_t));
del[i] = frame_ll;
frame_ll = frame_ll->next;
}
assert(!frame_ll);
log->latch_buffer_start = NULL;
log->latch_buffer_len = 0;
xSemaphoreGive(log->latch_buffer_lock);
for (int i = 0; i < len; i++) {
o->items[i] = MP_OBJ_FROM_PTR(frames[i]);
free(del[i]);
}
return MP_OBJ_FROM_PTR(o);
}
static void _initialize_log() {
if (petal_log_initialized) return;
for (size_t i = 0; i < 10; i++) {
petal_log_buffer_t *log = &(petal_log[i]);
assert(log->lock == NULL);
assert(log->latch_buffer_lock == NULL);
log->lock = xSemaphoreCreateMutex();
assert(log->lock != NULL);
log->latch_buffer_lock = xSemaphoreCreateMutex();
assert(log->latch_buffer_lock != NULL);
}
flow3r_bsp_captouch_set_data_callback(_add_entry_to_log);
petal_log_initialized = true;
}
typedef struct {
mp_obj_base_t base;
mp_obj_t captouch;
mp_obj_t pads;
mp_obj_t log;
size_t ix;
} mp_captouch_petal_state_t;
......@@ -37,45 +223,95 @@ const mp_obj_type_t captouch_petal_state_type;
typedef struct {
mp_obj_base_t base;
mp_obj_t petals;
st3m_captouch_state_t underlying;
uint32_t timestamp;
flow3r_bsp_captouch_data_t underlying;
} mp_captouch_state_t;
const mp_obj_type_t captouch_state_type;
STATIC void mp_captouch_petal_pads_state_attr(mp_obj_t self_in, qstr attr,
static inline void log_frame_process_data(log_frame_data_t *data) {
if (!data->processed) {
data->rad.post = data->rad.pre / FLOW3R_BSP_CAPTOUCH_RAD_UNIT;
data->phi.post = data->phi.pre / FLOW3R_BSP_CAPTOUCH_PHI_UNIT;
data->coverage.post =
data->coverage.pre / FLOW3R_BSP_CAPTOUCH_COVERAGE_UNIT;
data->processed = true;
}
}
STATIC void mp_captouch_petal_log_frame_attr(mp_obj_t self_in, qstr attr,
mp_obj_t *dest) {
mp_captouch_petal_pads_state_t *self = MP_OBJ_TO_PTR(self_in);
mp_captouch_petal_log_frame_t *self = MP_OBJ_TO_PTR(self_in);
if (dest[0] != MP_OBJ_NULL) {
return;
}
log_frame_data_t *data = &self->data;
log_frame_process_data(data);
mp_captouch_petal_state_t *petal = MP_OBJ_TO_PTR(self->petal);
mp_captouch_state_t *captouch = MP_OBJ_TO_PTR(petal->captouch);
st3m_petal_state_t *state = &captouch->underlying.petals[petal->ix];
bool top = (petal->ix % 2) == 0;
if (top) {
switch (attr) {
case MP_QSTR_base:
dest[0] = mp_obj_new_bool(state->base.pressed);
case MP_QSTR_raw_pos:
dest[0] = mp_obj_new_complex(data->rad.post, data->phi.post);
break;
case MP_QSTR_cw:
dest[0] = mp_obj_new_bool(state->cw.pressed);
case MP_QSTR_pos:
if (data->pressed && data->mode > 1) {
dest[0] = mp_obj_new_complex(data->rad.post, data->phi.post);
} else {
dest[0] = mp_const_none;
}
break;
case MP_QSTR_ccw:
dest[0] = mp_obj_new_bool(state->ccw.pressed);
case MP_QSTR_raw_cap:
dest[0] = mp_obj_new_float(data->coverage.post);
break;
}
} else {
switch (attr) {
case MP_QSTR_tip:
dest[0] = mp_obj_new_bool(state->tip.pressed);
case MP_QSTR_pressed:
dest[0] = mp_obj_new_bool(data->pressed);
break;
case MP_QSTR_base:
dest[0] = mp_obj_new_bool(state->base.pressed);
case MP_QSTR_mode:
dest[0] = mp_obj_new_int(data->mode);
break;
case MP_QSTR_ticks_us:
dest[0] = MP_OBJ_NEW_SMALL_INT(data->timestamp);
break;
}
}
STATIC mp_obj_t mp_captouch_petal_log_frame_make_new(
const mp_obj_type_t *type_in, size_t n_args, size_t n_kw,
const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 2, 4, false);
// args: pressed, position, timestamp (optional, fallback: present time),
// coverage (optional, fallback: 5 if pressed else 0)
mp_captouch_petal_log_frame_t *self =
m_new_obj(mp_captouch_petal_log_frame_t);
self->base.type = type_in;
log_frame_data_t *data = &self->data;
data->processed = true;
data->pressed = mp_obj_is_true(args[0]);
if (mp_obj_is_type(args[1], &mp_type_complex)) {
mp_obj_complex_t *position = MP_OBJ_TO_PTR(args[1]);
data->rad.post = position->real;
data->phi.post = position->imag;
} else {
data->rad.post = mp_obj_get_float(args[1]);
data->phi.post = 0;
}
if (n_args > 2) {
data->timestamp = MP_OBJ_SMALL_INT_VALUE(args[2]);
} else {
data->timestamp =
esp_timer_get_time() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1);
}
if (n_args > 3) {
data->coverage.post = mp_obj_get_float(args[3]);
} else {
data->coverage.post = data->pressed ? 5. : 0.;
}
return MP_OBJ_FROM_PTR(self);
}
STATIC void mp_captouch_petal_state_attr(mp_obj_t self_in, qstr attr,
......@@ -86,11 +322,16 @@ STATIC void mp_captouch_petal_state_attr(mp_obj_t self_in, qstr attr,
}
mp_captouch_state_t *captouch = MP_OBJ_TO_PTR(self->captouch);
st3m_petal_state_t *state = &captouch->underlying.petals[self->ix];
flow3r_bsp_captouch_petal_data_t *state =
&captouch->underlying.petals[self->ix];
bool top = (self->ix % 2) == 0;
switch (attr) {
case MP_QSTR_log: {
mp_obj_list_t *log = MP_OBJ_TO_PTR(self->log);
dest[0] = mp_obj_new_tuple(log->len, log->items);
} break;
case MP_QSTR_top:
dest[0] = mp_obj_new_bool(top);
break;
......@@ -98,22 +339,66 @@ STATIC void mp_captouch_petal_state_attr(mp_obj_t self_in, qstr attr,
dest[0] = mp_obj_new_bool(!top);
break;
case MP_QSTR_pressed:
dest[0] = mp_obj_new_bool(state->pressed);
dest[0] = mp_obj_new_bool(state->press_event);
break;
case MP_QSTR_pressure:
dest[0] = mp_obj_new_int(state->pressure);
case MP_QSTR_raw_cap:
dest[0] = mp_obj_new_float(state->coverage /
FLOW3R_BSP_CAPTOUCH_COVERAGE_UNIT);
break;
case MP_QSTR_pads:
dest[0] = self->pads;
case MP_QSTR_raw_pos:
dest[0] =
mp_obj_new_complex(state->rad / FLOW3R_BSP_CAPTOUCH_RAD_UNIT,
state->phi / FLOW3R_BSP_CAPTOUCH_PHI_UNIT);
break;
case MP_QSTR_position: {
mp_obj_t items[2] = {
mp_obj_new_int(state->pos_distance),
mp_obj_new_int(state->pos_angle),
};
dest[0] = mp_obj_new_tuple(2, items);
case MP_QSTR_pos:
if (state->press_event && state->mode > 1) {
dest[0] = mp_obj_new_complex(
state->rad / FLOW3R_BSP_CAPTOUCH_RAD_UNIT,
state->phi / FLOW3R_BSP_CAPTOUCH_PHI_UNIT);
} else {
dest[0] = mp_const_none;
}
break;
#ifdef FLOW3R_BSP_CAPTOUCH_SECONDARY_OUTPUT
case MP_QSTR__pos2:
if (state->press_event && state->mode > 1) {
dest[0] = mp_obj_new_complex(
state->rad2 / FLOW3R_BSP_CAPTOUCH_RAD_UNIT,
state->phi2 / FLOW3R_BSP_CAPTOUCH_PHI_UNIT);
} else {
dest[0] = mp_const_none;
}
break;
#endif
case MP_QSTR_pressure:
// legacy
if (state->press_event) {
dest[0] = mp_obj_new_int(state->coverage);
} else {
dest[0] = mp_obj_new_int(0);
}
break;
case MP_QSTR_position:
// legacy
{
int32_t ret[2];
ret[0] = state->rad;
ret[1] = state->phi;
mp_obj_t items[2];
// bitshift better than division here due to uneven spacing when
// crossing 0 fix manually when changing RAD_UNIT/PHI_UNIT
if (top) {
ret[0] = (int32_t)((35000 * ret[0]) >> 14);
ret[1] = (int32_t)((35000 * ret[1]) >> 14);
} else {
ret[0] = (int32_t)(((25000 * ret[0]) >> 14) + 5000);
ret[1] = 0;
}
items[0] = mp_obj_new_int(ret[0]);
items[1] = mp_obj_new_int(ret[1]);
dest[0] = mp_obj_new_tuple(2, items);
}
break;
}
}
......@@ -128,12 +413,16 @@ STATIC void mp_captouch_state_attr(mp_obj_t self_in, qstr attr,
case MP_QSTR_petals:
dest[0] = self->petals;
break;
case MP_QSTR_ticks_us:
dest[0] = MP_OBJ_NEW_SMALL_INT(self->timestamp);
break;
}
}
MP_DEFINE_CONST_OBJ_TYPE(captouch_petal_pads_state_type,
MP_QSTR_CaptouchPetalPadsState, MP_TYPE_FLAG_NONE,
attr, mp_captouch_petal_pads_state_attr);
MP_DEFINE_CONST_OBJ_TYPE(mp_type_captouch_petal_log_frame,
MP_QSTR_PetalLogFrame, MP_TYPE_FLAG_NONE, attr,
mp_captouch_petal_log_frame_attr, make_new,
mp_captouch_petal_log_frame_make_new);
MP_DEFINE_CONST_OBJ_TYPE(captouch_petal_state_type, MP_QSTR_CaptouchPetalState,
MP_TYPE_FLAG_NONE, attr, mp_captouch_petal_state_attr);
......@@ -141,44 +430,893 @@ MP_DEFINE_CONST_OBJ_TYPE(captouch_petal_state_type, MP_QSTR_CaptouchPetalState,
MP_DEFINE_CONST_OBJ_TYPE(captouch_state_type, MP_QSTR_CaptouchState,
MP_TYPE_FLAG_NONE, attr, mp_captouch_state_attr);
STATIC mp_obj_t mp_captouch_state_new(const st3m_captouch_state_t *underlying) {
STATIC mp_obj_t
mp_captouch_state_new(const flow3r_bsp_captouch_data_t *underlying) {
mp_captouch_state_t *captouch = m_new_obj(mp_captouch_state_t);
captouch->timestamp = refresh_time;
captouch->base.type = &captouch_state_type;
memcpy(&captouch->underlying, underlying, sizeof(st3m_captouch_state_t));
memcpy(&captouch->underlying, underlying,
sizeof(flow3r_bsp_captouch_data_t));
captouch->petals = mp_obj_new_list(0, NULL);
mp_obj_t petals[10];
for (int i = 0; i < 10; i++) {
mp_captouch_petal_state_t *petal = m_new_obj(mp_captouch_petal_state_t);
petal->base.type = &captouch_petal_state_type;
petal->captouch = MP_OBJ_FROM_PTR(captouch);
petal->ix = i;
mp_captouch_petal_pads_state_t *pads =
m_new_obj(mp_captouch_petal_pads_state_t);
pads->base.type = &captouch_petal_pads_state_type;
pads->petal = MP_OBJ_FROM_PTR(petal);
petal->pads = MP_OBJ_FROM_PTR(pads);
mp_obj_list_append(captouch->petals, MP_OBJ_FROM_PTR(petal));
petal->log = _get_list_from_log(i);
petals[i] = MP_OBJ_FROM_PTR(petal);
}
captouch->petals = mp_obj_new_tuple(10, petals);
return MP_OBJ_FROM_PTR(captouch);
}
STATIC mp_obj_t mp_captouch_read(void) {
st3m_captouch_state_t st;
st3m_captouch_get_all(&st);
return mp_captouch_state_new(&st);
flow3r_bsp_captouch_data_t dat;
flow3r_bsp_captouch_get(&dat);
return mp_captouch_state_new(&dat);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_read_obj, mp_captouch_read);
STATIC const mp_rom_map_elem_t globals_table[] = {
STATIC mp_obj_t mp_captouch_refresh_events(void) {
for (int i = 0; i < 10; i++) {
_kick_log_latch(i);
}
refresh_time = esp_timer_get_time() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1);
flow3r_bsp_captouch_refresh_events();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_refresh_events_obj,
mp_captouch_refresh_events);
STATIC mp_obj_t mp_captouch_calibration_get_trusted(void) {
return mp_obj_new_bool(calib_trusted);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_calibration_get_trusted_obj,
mp_captouch_calibration_get_trusted);
STATIC mp_obj_t mp_captouch_calibration_set_trusted(mp_obj_t mp_data) {
calib_trusted = mp_obj_is_true(mp_data);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_captouch_calibration_set_trusted_obj,
mp_captouch_calibration_set_trusted);
STATIC mp_obj_t mp_captouch_calibration_active(void) {
return mp_obj_new_int(flow3r_bsp_captouch_calibrating());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_calibration_active_obj,
mp_captouch_calibration_active);
STATIC mp_obj_t mp_captouch_calibration_request(void) {
flow3r_bsp_captouch_calibration_request();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_calibration_request_obj,
mp_captouch_calibration_request);
static int get_calibration_index(int petal, int num_dimensions,
int dimension_index) {
int index = petal * 6;
index += ((num_dimensions + 1) * num_dimensions) / 2;
index += dimension_index;
index *= 2;
if (index >= 120)
mp_raise_ValueError(
MP_ERROR_TEXT("target index out of range (our fault)"));
return index;
}
STATIC mp_obj_t mp_captouch_calibration_get_data(void) {
int32_t data[120];
if (!flow3r_bsp_captouch_get_calibration_data(data)) return mp_const_none;
mp_obj_t petal_dicts[10];
mp_obj_t items[3];
mp_obj_t strings[4] = { mp_obj_new_str("0d", 2), mp_obj_new_str("1d", 2),
mp_obj_new_str("2d", 2),
mp_obj_new_str("petal", 5) };
for (int petal = 0; petal < 10; petal++) {
petal_dicts[petal] =
mp_obj_dict_make_new(&mp_type_ordereddict, 0, 0, 0);
mp_obj_dict_store(petal_dicts[petal], strings[3],
mp_obj_new_int(petal));
for (int ndim = 0; ndim < (3 - (petal & 1)); ndim++) {
for (int dim = 0; dim <= ndim; dim++) {
int index = get_calibration_index(petal, ndim, dim);
char buf[25]; // max len of 32bit int decimal is 11 chars
int trunc = snprintf(buf, 25, "%d/%d", (int)data[index],
(int)data[index + 1]);
assert(trunc < 25);
items[dim] = mp_obj_new_str(buf, trunc);
}
mp_obj_dict_store(petal_dicts[petal], strings[ndim],
mp_obj_new_tuple(ndim + 1, items));
}
}
mp_obj_t ret = mp_obj_dict_make_new(&mp_type_ordereddict, 0, 0, 0);
mp_obj_dict_store(ret, mp_obj_new_str("ad7147", 6),
mp_obj_new_tuple(10, petal_dicts));
return ret;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_calibration_get_data_obj,
mp_captouch_calibration_get_data);
static bool parse_calibration_dict(mp_obj_t mp_data, int32_t *data) {
if (!mp_obj_is_dict_or_ordereddict(mp_data)) return false;
mp_map_elem_t *elem;
mp_obj_t len;
mp_obj_dict_t *calib_dict = MP_OBJ_TO_PTR(mp_data);
elem = mp_map_lookup(&calib_dict->map, mp_obj_new_str("ad7147", 6),
MP_MAP_LOOKUP);
if (!elem) return false;
mp_obj_t bias_tuple = elem->value;
len = mp_obj_len_maybe(bias_tuple);
if ((len == MP_OBJ_NULL) || (mp_obj_get_int(len) != 10)) return false;
mp_obj_t strings[4] = { mp_obj_new_str("0d", 2), mp_obj_new_str("1d", 2),
mp_obj_new_str("2d", 2),
mp_obj_new_str("petal", 5) };
uint16_t petals_scanned = 0;
for (int index = 0; index < 10; index++) {
mp_obj_t petal_obj =
mp_obj_subscr(bias_tuple, mp_obj_new_int(index), MP_OBJ_SENTINEL);
if (!mp_obj_is_dict_or_ordereddict(petal_obj)) return false;
mp_obj_dict_t *petal_dict = MP_OBJ_TO_PTR(petal_obj);
elem = mp_map_lookup(&petal_dict->map, strings[3], MP_MAP_LOOKUP);
int petal = elem ? mp_obj_get_int(elem->value) : index;
if (petal > 9 || petal < 0)
mp_raise_ValueError(MP_ERROR_TEXT("petal index out of range"));
if (petals_scanned & 1 << petal)
mp_raise_ValueError(MP_ERROR_TEXT("petal index duplicate"));
petals_scanned |= 1 << petal;
for (int ndim = 0; ndim < (3 - (petal & 1)); ndim++) {
elem =
mp_map_lookup(&petal_dict->map, strings[ndim], MP_MAP_LOOKUP);
if (!elem) return false;
mp_obj_t calib_tuple = elem->value;
len = mp_obj_len_maybe(calib_tuple);
if ((len == MP_OBJ_NULL) || (mp_obj_get_int(len) != ndim + 1))
return false;
for (int dim = 0; dim <= ndim; dim++) {
int index = get_calibration_index(petal, ndim, dim);
mp_obj_t calib_str[2] = { mp_obj_subscr(calib_tuple,
mp_obj_new_int(dim),
MP_OBJ_SENTINEL),
mp_obj_new_str("/", 1) };
mp_obj_t calib_pt = mp_obj_str_split(2, calib_str);
for (int data_index = 0; data_index < 2; data_index++) {
size_t l;
const char *s = mp_obj_str_get_data(
mp_obj_subscr(calib_pt, mp_obj_new_int(data_index),
MP_OBJ_SENTINEL),
&l);
data[index + data_index] =
mp_obj_get_int(mp_parse_num_integer(s, l, 0, NULL));
}
if (data[index] > UINT16_MAX || data[index] < 0 ||
data[index + 1] > 126 || data[index + 1] < 0) {
mp_raise_ValueError(
MP_ERROR_TEXT("calibration data out of range"));
return false; // never reached bc __attribute__((noreturn))
// but leaving it to make clear it doesn't
// return true
}
}
}
}
return true;
}
STATIC mp_obj_t mp_captouch_calibration_set_data(mp_obj_t mp_data) {
int32_t data[120];
if (parse_calibration_dict(mp_data, data)) {
flow3r_bsp_captouch_set_calibration_data(data);
return mp_const_none;
}
mp_raise_TypeError(MP_ERROR_TEXT("calibration data malformed"));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_captouch_calibration_set_data_obj,
mp_captouch_calibration_set_data);
STATIC const MP_DEFINE_STR_OBJ(mp_captouch_calibration_path_obj,
"/flash/captouch_calib.json");
STATIC const mp_rom_map_elem_t sys_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_captouch_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_calibration_active),
MP_ROM_PTR(&mp_captouch_calibration_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_refresh_events),
MP_ROM_PTR(&mp_captouch_refresh_events_obj) },
{ MP_ROM_QSTR(MP_QSTR_calibration_path),
MP_ROM_PTR(&mp_captouch_calibration_path_obj) },
{ MP_ROM_QSTR(MP_QSTR_calibration_request),
MP_ROM_PTR(&mp_captouch_calibration_request_obj) },
{ MP_ROM_QSTR(MP_QSTR_calibration_active),
MP_ROM_PTR(&mp_captouch_calibration_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_calibration_set_trusted),
MP_ROM_PTR(&mp_captouch_calibration_set_trusted_obj) },
{ MP_ROM_QSTR(MP_QSTR_calibration_get_trusted),
MP_ROM_PTR(&mp_captouch_calibration_get_trusted_obj) },
{ MP_ROM_QSTR(MP_QSTR_calibration_set_data),
MP_ROM_PTR(&mp_captouch_calibration_set_data_obj) },
{ MP_ROM_QSTR(MP_QSTR_calibration_get_data),
MP_ROM_PTR(&mp_captouch_calibration_get_data_obj) },
};
STATIC MP_DEFINE_CONST_DICT(sys_globals, sys_globals_table);
const mp_obj_module_t mp_module_sys_captouch_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&sys_globals,
};
MP_REGISTER_MODULE(MP_QSTR_sys_captouch, mp_module_sys_captouch_user_cmodule);
typedef struct {
mp_obj_base_t base;
int8_t index;
int8_t mode;
int8_t logging;
} captouch_petal_config_obj_t;
typedef struct {
mp_obj_base_t base;
mp_obj_t petals;
} captouch_config_obj_t;
static int _check_petal_mode(int mode, int petal) {
if (petal & 1) {
if ((mode < 0) || (mode > 2)) {
mp_raise_ValueError(MP_ERROR_TEXT(
"petal mode not allowed (allowed modes: 0, 1, 2)"));
}
} else if (petal == 4 || petal == 6) {
if ((mode < 0) || (mode > 3)) {
mp_raise_ValueError(MP_ERROR_TEXT(
"petal mode not allowed (allowed modes: 0, 1, 2, 3)"));
}
} else {
if ((mode != 0) && (mode != 3)) {
mp_raise_ValueError(
MP_ERROR_TEXT("petal mode not allowed (allowed modes: 0, 3)"));
}
}
return mode;
}
static int _limit_petal_mode(int mode, int petal) {
if (petal & 1) {
return mode > 2 ? 2 : (mode < 0 ? 0 : mode);
} else if (petal == 4 || petal == 6) {
return mode > 3 ? 3 : (mode < 0 ? 0 : mode);
} else {
return mode > 0 ? 3 : 0;
}
}
STATIC void captouch_petal_config_attr(mp_obj_t self_in, qstr attr,
mp_obj_t *dest) {
captouch_petal_config_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (dest[0] != MP_OBJ_NULL) {
if (attr == MP_QSTR_mode) {
self->mode =
_check_petal_mode(mp_obj_get_int(dest[1]), self->index);
dest[0] = MP_OBJ_NULL;
} else if (attr == MP_QSTR_logging) {
self->logging = mp_obj_is_true(dest[1]);
dest[0] = MP_OBJ_NULL;
}
} else {
if (attr == MP_QSTR_mode) {
dest[0] = mp_obj_new_int(self->mode);
} else if (attr == MP_QSTR_logging) {
dest[0] = self->logging ? mp_const_true : mp_const_false;
} else {
dest[1] = MP_OBJ_SENTINEL;
}
}
}
STATIC mp_obj_t captouch_petal_config_set_default(mp_obj_t self_in) {
captouch_petal_config_obj_t *self = MP_OBJ_TO_PTR(self_in);
self->mode = _limit_petal_mode(3, self->index);
self->logging = false;
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(captouch_petal_config_set_default_obj,
captouch_petal_config_set_default);
STATIC mp_obj_t captouch_petal_config_clear(mp_obj_t self_in) {
captouch_petal_config_obj_t *self = MP_OBJ_TO_PTR(self_in);
self->mode = 0;
self->logging = false;
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(captouch_petal_config_clear_obj,
captouch_petal_config_clear);
STATIC mp_obj_t captouch_petal_config_set_min_mode(mp_obj_t self_in,
mp_obj_t mp_mode) {
captouch_petal_config_obj_t *self = MP_OBJ_TO_PTR(self_in);
int mode = _limit_petal_mode(mp_obj_get_int(mp_mode), self->index);
self->mode = mode > self->mode ? mode : self->mode;
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(captouch_petal_config_set_min_mode_obj,
captouch_petal_config_set_min_mode);
STATIC const mp_rom_map_elem_t captouch_petal_config_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_default),
MP_ROM_PTR(&captouch_petal_config_set_default_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear),
MP_ROM_PTR(&captouch_petal_config_clear_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_min_mode),
MP_ROM_PTR(&captouch_petal_config_set_min_mode_obj) },
};
STATIC MP_DEFINE_CONST_DICT(captouch_petal_config_locals_dict,
captouch_petal_config_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(mp_type_captouch_petal_config, MP_QSTR_PetalConfig,
MP_TYPE_FLAG_NONE, locals_dict,
&captouch_petal_config_locals_dict, attr,
captouch_petal_config_attr);
static mp_obj_t captouch_config_new(int mode, mp_obj_type_t *type) {
captouch_config_obj_t *self = m_new_obj(captouch_config_obj_t);
self->base.type = type;
mp_obj_t petals[10];
flow3r_bsp_captouch_petal_mode_t mode_data[10];
if (mode > 1) flow3r_bsp_captouch_get_petal_modes(mode_data);
for (int petal = 0; petal < 10; petal++) {
captouch_petal_config_obj_t *petalconf =
m_new_obj(captouch_petal_config_obj_t);
petalconf->base.type = &mp_type_captouch_petal_config;
petalconf->index = petal;
if (mode > 1) {
petalconf->logging = petal_log_active[petal];
petalconf->mode = mode_data[petal];
} else {
petalconf->logging = false;
petalconf->mode = mode ? 3 - (petal & 1) : 0;
}
petals[petal] = MP_OBJ_FROM_PTR(petalconf);
}
self->petals = mp_obj_new_tuple(10, petals);
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t captouch_config_empty(mp_obj_t type_in) {
return captouch_config_new(0, MP_OBJ_TO_PTR(type_in));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(captouch_config_empty_fun_obj,
captouch_config_empty);
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(
captouch_config_empty_obj, MP_ROM_PTR(&captouch_config_empty_fun_obj));
STATIC mp_obj_t captouch_config_default(mp_obj_t type_in) {
return captouch_config_new(1, MP_OBJ_TO_PTR(type_in));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(captouch_config_default_fun_obj,
captouch_config_default);
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(
captouch_config_default_obj, MP_ROM_PTR(&captouch_config_default_fun_obj));
STATIC mp_obj_t captouch_config_current(mp_obj_t type_in) {
return captouch_config_new(2, MP_OBJ_TO_PTR(type_in));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(captouch_config_current_fun_obj,
captouch_config_current);
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(
captouch_config_current_obj, MP_ROM_PTR(&captouch_config_current_fun_obj));
STATIC void captouch_config_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
if (dest[0] != MP_OBJ_NULL) {
return;
}
if (attr == MP_QSTR_petals) {
captouch_config_obj_t *self = MP_OBJ_TO_PTR(self_in);
dest[0] = self->petals;
} else {
dest[1] = MP_OBJ_SENTINEL;
}
}
static void captouch_config_verify(captouch_config_obj_t *self) {
for (int petal = 0; petal < 10; petal++) {
mp_obj_t petalconf_obj =
mp_obj_subscr(self->petals, mp_obj_new_int(petal), MP_OBJ_SENTINEL);
if (!mp_obj_is_type(petalconf_obj, &mp_type_captouch_petal_config))
mp_raise_TypeError(MP_ERROR_TEXT("petal data malformed"));
}
}
STATIC mp_obj_t captouch_config_apply(mp_obj_t self_in) {
_initialize_log();
captouch_config_obj_t *self = MP_OBJ_TO_PTR(self_in);
captouch_config_verify(self);
flow3r_bsp_captouch_petal_mode_t mode_data[10];
bool logging_data[10];
for (int petal = 0; petal < 10; petal++) {
captouch_petal_config_obj_t *petalconf = MP_OBJ_TO_PTR(mp_obj_subscr(
self->petals, mp_obj_new_int(petal), MP_OBJ_SENTINEL));
mode_data[petal] = _limit_petal_mode(petalconf->mode, petal);
logging_data[petal] = petalconf->logging;
}
flow3r_bsp_captouch_set_petal_modes(mode_data);
memcpy(petal_log_active, logging_data, sizeof(petal_log_active));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(captouch_config_apply_obj, captouch_config_apply);
STATIC mp_obj_t captouch_config_apply_default(mp_obj_t self_in) {
flow3r_bsp_captouch_petal_mode_t mode_data[10];
bool logging_data[10];
for (int petal = 0; petal < 10; petal++) {
mode_data[petal] = _limit_petal_mode(3, petal);
logging_data[petal] = false;
}
flow3r_bsp_captouch_set_petal_modes(mode_data);
memcpy(petal_log_active, logging_data, sizeof(petal_log_active));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(captouch_config_apply_default_obj,
captouch_config_apply_default);
// dirty hack: struct not exposed, internal to vendor/py/objcomplex.c but if we
// wanna write to ROM this is probably for the better
typedef struct {
mp_obj_base_t base;
mp_float_t real;
mp_float_t imag;
} mp_obj_complex_copy_t;
STATIC const mp_obj_complex_copy_t mp_const_petal_rotors[10] = {
{ { &mp_type_complex }, (mp_float_t)0., (mp_float_t)-1. },
{ { &mp_type_complex },
(mp_float_t)0.5877852522924731,
(mp_float_t)-0.8090169943749475 },
{ { &mp_type_complex },
(mp_float_t)0.9510565162951535,
(mp_float_t)-0.3090169943749474 },
{ { &mp_type_complex },
(mp_float_t)0.9510565162951535,
(mp_float_t)0.3090169943749474 },
{ { &mp_type_complex },
(mp_float_t)0.5877852522924731,
(mp_float_t)0.8090169943749475 },
{ { &mp_type_complex }, (mp_float_t)0., (mp_float_t)1. },
{ { &mp_type_complex },
(mp_float_t)-0.5877852522924731,
(mp_float_t)0.8090169943749475 },
{ { &mp_type_complex },
(mp_float_t)-0.9510565162951535,
(mp_float_t)0.3090169943749474 },
{ { &mp_type_complex },
(mp_float_t)-0.9510565162951535,
(mp_float_t)-0.3090169943749474 },
{ { &mp_type_complex },
(mp_float_t)-0.5877852522924731,
(mp_float_t)-0.8090169943749475 },
};
STATIC const mp_rom_obj_tuple_t mp_petal_rotors_tuple_obj = {
{ &mp_type_tuple },
10,
{
MP_ROM_PTR(&mp_const_petal_rotors[0]),
MP_ROM_PTR(&mp_const_petal_rotors[1]),
MP_ROM_PTR(&mp_const_petal_rotors[2]),
MP_ROM_PTR(&mp_const_petal_rotors[3]),
MP_ROM_PTR(&mp_const_petal_rotors[4]),
MP_ROM_PTR(&mp_const_petal_rotors[5]),
MP_ROM_PTR(&mp_const_petal_rotors[6]),
MP_ROM_PTR(&mp_const_petal_rotors[7]),
MP_ROM_PTR(&mp_const_petal_rotors[8]),
MP_ROM_PTR(&mp_const_petal_rotors[9]),
},
};
// same as with mp_obj_complex_copy_t
typedef struct {
mp_obj_base_t base;
mp_float_t value;
} mp_obj_float_copy_t;
STATIC const mp_obj_float_copy_t mp_const_petal_angles[10] = {
{ { &mp_type_float }, (mp_float_t)-1.570796 },
{ { &mp_type_float }, (mp_float_t)-0.9424778 },
{ { &mp_type_float }, (mp_float_t)-0.3141593 },
{ { &mp_type_float }, (mp_float_t)0.3141593 },
{ { &mp_type_float }, (mp_float_t)0.9424778 },
{ { &mp_type_float }, (mp_float_t)1.570796 },
{ { &mp_type_float }, (mp_float_t)2.199115 },
{ { &mp_type_float }, (mp_float_t)2.827433 },
{ { &mp_type_float }, (mp_float_t)-2.827433 },
{ { &mp_type_float }, (mp_float_t)-2.199115 },
};
STATIC const mp_rom_obj_tuple_t mp_petal_angles_tuple_obj = {
{ &mp_type_tuple },
10,
{
MP_ROM_PTR(&mp_const_petal_angles[0]),
MP_ROM_PTR(&mp_const_petal_angles[1]),
MP_ROM_PTR(&mp_const_petal_angles[2]),
MP_ROM_PTR(&mp_const_petal_angles[3]),
MP_ROM_PTR(&mp_const_petal_angles[4]),
MP_ROM_PTR(&mp_const_petal_angles[5]),
MP_ROM_PTR(&mp_const_petal_angles[6]),
MP_ROM_PTR(&mp_const_petal_angles[7]),
MP_ROM_PTR(&mp_const_petal_angles[8]),
MP_ROM_PTR(&mp_const_petal_angles[9]),
},
};
STATIC const mp_rom_map_elem_t captouch_config_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_empty), MP_ROM_PTR(&captouch_config_empty_obj) },
{ MP_ROM_QSTR(MP_QSTR_default), MP_ROM_PTR(&captouch_config_default_obj) },
{ MP_ROM_QSTR(MP_QSTR_current), MP_ROM_PTR(&captouch_config_current_obj) },
{ MP_ROM_QSTR(MP_QSTR_apply), MP_ROM_PTR(&captouch_config_apply_obj) },
{ MP_ROM_QSTR(MP_QSTR_apply_default),
MP_ROM_PTR(&captouch_config_apply_default_obj) },
};
STATIC MP_DEFINE_CONST_DICT(captouch_config_locals_dict,
captouch_config_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(mp_type_captouch_config, MP_QSTR_Config,
MP_TYPE_FLAG_NONE, locals_dict,
&captouch_config_locals_dict, attr,
captouch_config_attr);
typedef struct {
mp_obj_base_t base;
mp_obj_t frames;
int max_len;
} captouch_petal_log_obj_t;
#define PREALLOC_LIMIT 128
static inline mp_int_t ticks_diff_inner(mp_uint_t end, mp_uint_t start) {
return (((end - start + MICROPY_PY_UTIME_TICKS_PERIOD / 2) &
(MICROPY_PY_UTIME_TICKS_PERIOD - 1)) -
MICROPY_PY_UTIME_TICKS_PERIOD / 2);
}
static int list_multidel_nodealloc(mp_obj_list_t *list, int num_del,
bool from_newest) {
if (num_del <= 0) return 0;
num_del = num_del > list->len ? list->len : num_del;
list->len -= num_del;
if (!from_newest)
memmove(list->items, list->items + num_del,
(list->len) * sizeof(mp_obj_t));
for (int i = 0; i < num_del; i++) {
list->items[list->len + i] = MP_OBJ_NULL;
}
mp_seq_clear(list->items, list->len + 1, list->alloc, sizeof(*list->items));
return num_del;
}
static mp_captouch_petal_log_frame_t *mp_obj_to_frame_ptr(mp_obj_t frame_obj) {
if (!mp_obj_is_type(frame_obj, &mp_type_captouch_petal_log_frame)) {
mp_raise_TypeError(MP_ERROR_TEXT("frame must be PetalLogFrame"));
}
return MP_OBJ_TO_PTR(frame_obj);
}
static void log_crop(mp_obj_list_t *list, int min_frames, float min_time_ms,
bool from_newest) {
int len = list->len;
if (!len) return;
min_frames = min_frames < 0 ? 0 : min_frames;
if (min_time_ms > 0.) {
mp_uint_t min_time_us = min_time_ms * 1000;
mp_captouch_petal_log_frame_t *frame =
mp_obj_to_frame_ptr(list->items[from_newest ? len - 1 : 0]);
mp_uint_t ref_timestamp = frame->data.timestamp;
for (int i = min_frames + 1; i < len; i++) {
int index = from_newest ? len - 1 - i : i;
frame = mp_obj_to_frame_ptr(list->items[index]);
mp_uint_t start =
from_newest ? frame->data.timestamp : ref_timestamp;
mp_uint_t end = from_newest ? ref_timestamp : frame->data.timestamp;
if (ticks_diff_inner(end, start) >= min_time_us) {
min_frames = i - 1;
break;
}
}
}
list_multidel_nodealloc(list, min_frames, from_newest);
}
static inline void get_slice_index(mp_obj_t mp_index, int len, int *ret) {
if (mp_index == mp_const_none) return;
int index = mp_obj_get_int(mp_index);
if (index < 0) index += len;
if (index < 0) {
index = 0;
} else if (index > len) {
index = len;
}
*ret = index;
}
STATIC mp_obj_t captouch_petal_log_average(size_t n_args,
const mp_obj_t *args) {
captouch_petal_log_obj_t *self = MP_OBJ_TO_PTR(args[0]);
mp_obj_list_t *frames = MP_OBJ_TO_PTR(self->frames);
int start = 0;
if (n_args > 1) get_slice_index(args[1], frames->len, &start);
int stop = frames->len;
if (n_args > 2) get_slice_index(args[2], frames->len, &stop);
int len = stop - start;
if (len < 1) return mp_const_none;
float sum_real = 0;
float sum_imag = 0;
for (int i = start; i < stop; i++) {
mp_captouch_petal_log_frame_t *frame =
mp_obj_to_frame_ptr(frames->items[i]);
log_frame_data_t *data = &frame->data;
log_frame_process_data(data);
sum_real += data->rad.post;
sum_imag += data->phi.post;
}
return mp_obj_new_complex(sum_real / len, sum_imag / len);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(captouch_petal_log_average_obj, 1, 3,
captouch_petal_log_average);
STATIC mp_obj_t captouch_petal_log_slope_per_ms(size_t n_args,
const mp_obj_t *args) {
captouch_petal_log_obj_t *self = MP_OBJ_TO_PTR(args[0]);
mp_obj_list_t *frames = MP_OBJ_TO_PTR(self->frames);
int start = 0;
if (n_args > 1) get_slice_index(args[1], frames->len, &start);
int stop = frames->len;
if (n_args > 2) get_slice_index(args[2], frames->len, &stop);
int len = stop - start;
if (len < 2) return mp_const_none;
mp_uint_t timestamp_start;
float sum_real = 0;
float sum_imag = 0;
float sum_t_real = 0;
float sum_t_imag = 0;
float sum_t_sq = 0;
float sum_t = 0;
for (int i = 0; i < len; i++) {
mp_captouch_petal_log_frame_t *frame =
mp_obj_to_frame_ptr(frames->items[i + start]);
log_frame_data_t *data = &frame->data;
log_frame_process_data(data);
sum_real += data->rad.post;
sum_imag += data->phi.post;
if (!i) {
timestamp_start = data->timestamp;
continue;
} else {
float timestamp =
ticks_diff_inner(data->timestamp, timestamp_start);
sum_t_real += data->rad.post * timestamp;
sum_t_imag += data->phi.post * timestamp;
sum_t_sq += timestamp * timestamp;
sum_t += timestamp;
}
}
float div = len * sum_t_sq - sum_t * sum_t;
if (!div) return mp_const_none;
float k_real = (len * sum_t_real - sum_real * sum_t) * 1000 / div;
float k_imag = (len * sum_t_imag - sum_imag * sum_t) * 1000 / div;
return mp_obj_new_complex(k_real, k_imag);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(captouch_petal_log_slope_per_ms_obj, 1, 3,
captouch_petal_log_slope_per_ms);
STATIC mp_obj_t captouch_petal_log_length(mp_obj_t self_in) {
captouch_petal_log_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_list_t *frames = MP_OBJ_TO_PTR(self->frames);
return mp_obj_new_int(frames->len);
}
MP_DEFINE_CONST_FUN_OBJ_1(captouch_petal_log_length_obj,
captouch_petal_log_length);
STATIC mp_obj_t captouch_petal_log_length_ms(size_t n_args,
const mp_obj_t *args) {
captouch_petal_log_obj_t *self = MP_OBJ_TO_PTR(args[0]);
mp_obj_list_t *frames = MP_OBJ_TO_PTR(self->frames);
int start = 0;
if (n_args > 1) get_slice_index(args[1], frames->len, &start);
int stop = frames->len;
if (n_args > 2) get_slice_index(args[2], frames->len, &stop);
if (stop - start < 2) return mp_obj_new_float(0.);
mp_captouch_petal_log_frame_t *oldest =
mp_obj_to_frame_ptr(frames->items[start]);
mp_captouch_petal_log_frame_t *newest =
mp_obj_to_frame_ptr(frames->items[stop - 1]);
float ret =
ticks_diff_inner(newest->data.timestamp, oldest->data.timestamp);
return mp_obj_new_float(ret / 1000);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(captouch_petal_log_length_ms_obj, 1, 3,
captouch_petal_log_length_ms);
STATIC mp_obj_t captouch_petal_log_index_offset_ms(mp_obj_t self_in,
mp_obj_t mp_index,
mp_obj_t mp_min_offset_ms) {
captouch_petal_log_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_list_t *frames = MP_OBJ_TO_PTR(self->frames);
int ref_index = mp_obj_get_int(mp_index);
if (ref_index < 0) ref_index += frames->len;
if (ref_index >= frames->len || ref_index < 0)
mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("index out of range"));
float min_offset_ms = mp_obj_get_float(mp_min_offset_ms);
mp_uint_t ref_timestamp =
mp_obj_to_frame_ptr(frames->items[ref_index])->data.timestamp;
if (!min_offset_ms) return mp_index;
if (min_offset_ms > 0) {
mp_int_t min_offset_us = min_offset_ms * 1000.;
// TODO: Make a smarter search that estimates based on length_ms/length
// and then expands linearily in whichever direction
for (int test_index = ref_index + 1; test_index < frames->len;
test_index++) {
mp_uint_t test_timestamp =
mp_obj_to_frame_ptr(frames->items[test_index])->data.timestamp;
if (ticks_diff_inner(test_timestamp, ref_timestamp) > min_offset_us)
return mp_obj_new_int(test_index);
}
} else {
mp_int_t min_offset_us = -min_offset_ms * 1000.;
for (int test_index = ref_index - 1; test_index >= 0; test_index--) {
mp_uint_t test_timestamp =
mp_obj_to_frame_ptr(frames->items[test_index])->data.timestamp;
if (ticks_diff_inner(ref_timestamp, test_timestamp) > min_offset_us)
return mp_obj_new_int(test_index);
}
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(captouch_petal_log_index_offset_ms_obj,
captouch_petal_log_index_offset_ms);
STATIC mp_obj_t captouch_petal_log_crop(mp_obj_t self_in, mp_obj_t mp_index) {
if (mp_index == mp_const_none) return mp_obj_new_int(0);
captouch_petal_log_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_list_t *frames = MP_OBJ_TO_PTR(self->frames);
int num_del = mp_obj_get_int(mp_index);
if (num_del < 0) num_del += frames->len;
num_del = list_multidel_nodealloc(frames, num_del, false);
return mp_obj_new_int(num_del);
}
MP_DEFINE_CONST_FUN_OBJ_2(captouch_petal_log_crop_obj, captouch_petal_log_crop);
STATIC mp_obj_t captouch_petal_log_clear(mp_obj_t self_in) {
captouch_petal_log_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_list_t *frames = MP_OBJ_TO_PTR(self->frames);
frames->len = 0;
frames->items =
m_renew(mp_obj_t, frames->items, frames->alloc, LIST_MIN_ALLOC);
frames->alloc = LIST_MIN_ALLOC;
mp_seq_clear(frames->items, 0, frames->alloc, sizeof(*frames->items));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(captouch_petal_log_clear_obj,
captouch_petal_log_clear);
STATIC mp_obj_t captouch_petal_log_append(mp_obj_t self_in,
mp_obj_t frame_obj) {
if (!mp_obj_is_type(frame_obj, &mp_type_captouch_petal_log_frame)) {
mp_raise_TypeError(MP_ERROR_TEXT("frame must be PetalLogFrame"));
}
captouch_petal_log_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_list_t *frames = MP_OBJ_TO_PTR(self->frames);
if (frames->len >= frames->alloc) {
int new_alloc = frames->alloc * 2;
if (self->max_len > new_alloc) new_alloc = self->max_len;
frames->items =
m_renew(mp_obj_t, frames->items, frames->alloc, new_alloc);
frames->alloc = new_alloc;
mp_seq_clear(frames->items, frames->len + 1, frames->alloc,
sizeof(*frames->items));
}
frames->items[frames->len++] = frame_obj;
if (frames->len > self->max_len) {
self->max_len =
frames->len > (PREALLOC_LIMIT) ? (PREALLOC_LIMIT) : frames->len;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(captouch_petal_log_append_obj,
captouch_petal_log_append);
STATIC void captouch_petal_log_attr(mp_obj_t self_in, qstr attr,
mp_obj_t *dest) {
captouch_petal_log_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (dest[0] != MP_OBJ_NULL) {
if (attr == MP_QSTR_frames) {
if (!mp_obj_is_type(dest[1], &mp_type_list))
mp_raise_TypeError(MP_ERROR_TEXT("frames must be a list"));
self->frames = dest[1];
dest[0] = MP_OBJ_NULL;
}
} else {
if (attr == MP_QSTR_frames) {
dest[0] = self->frames;
} else {
dest[1] = MP_OBJ_SENTINEL;
}
}
}
STATIC mp_obj_t captouch_petal_log_make_new(const mp_obj_type_t *type_in,
size_t n_args, size_t n_kw,
const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
captouch_petal_log_obj_t *self = m_new_obj(captouch_petal_log_obj_t);
self->base.type = type_in;
if (n_args) {
if (!mp_obj_is_type(args[0], &mp_type_list))
mp_raise_TypeError(MP_ERROR_TEXT("frames must be a list"));
self->frames = args[0];
mp_obj_list_t *list = MP_OBJ_TO_PTR(self->frames);
self->max_len = list->len;
} else {
self->frames = mp_obj_new_list(0, NULL);
self->max_len = LIST_MIN_ALLOC;
}
return MP_OBJ_FROM_PTR(self);
}
STATIC const mp_rom_map_elem_t captouch_petal_log_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_average),
MP_ROM_PTR(&captouch_petal_log_average_obj) },
{ MP_ROM_QSTR(MP_QSTR_slope_per_ms),
MP_ROM_PTR(&captouch_petal_log_slope_per_ms_obj) },
{ MP_ROM_QSTR(MP_QSTR_length), MP_ROM_PTR(&captouch_petal_log_length_obj) },
{ MP_ROM_QSTR(MP_QSTR_length_ms),
MP_ROM_PTR(&captouch_petal_log_length_ms_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&captouch_petal_log_clear_obj) },
{ MP_ROM_QSTR(MP_QSTR_crop), MP_ROM_PTR(&captouch_petal_log_crop_obj) },
{ MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&captouch_petal_log_append_obj) },
{ MP_ROM_QSTR(MP_QSTR_index_offset_ms),
MP_ROM_PTR(&captouch_petal_log_index_offset_ms_obj) },
};
STATIC MP_DEFINE_CONST_DICT(captouch_petal_log_locals_dict,
captouch_petal_log_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(mp_type_captouch_petal_log, MP_QSTR_PetalLog,
MP_TYPE_FLAG_NONE, locals_dict,
&captouch_petal_log_locals_dict, attr,
captouch_petal_log_attr, make_new,
captouch_petal_log_make_new);
STATIC const mp_rom_map_elem_t globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_Config), MP_ROM_PTR(&mp_type_captouch_config) },
{ MP_ROM_QSTR(MP_QSTR_PetalLog), MP_ROM_PTR(&mp_type_captouch_petal_log) },
{ MP_ROM_QSTR(MP_QSTR_PetalLogFrame),
MP_ROM_PTR(&mp_type_captouch_petal_log_frame) },
{ MP_ROM_QSTR(MP_QSTR_PETAL_ROTORS),
MP_ROM_PTR(&mp_petal_rotors_tuple_obj) },
{ MP_ROM_QSTR(MP_QSTR_PETAL_ANGLES),
MP_ROM_PTR(&mp_petal_angles_tuple_obj) },
#ifndef FLOW3R_V2
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_captouch_read_obj) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(globals, globals_table);
......
......@@ -58,6 +58,11 @@ STATIC mp_obj_t mp_leds_get_slew_rate() {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_leds_get_slew_rate_obj,
mp_leds_get_slew_rate);
STATIC mp_obj_t mp_leds_get_steady() {
return mp_obj_new_bool(st3m_leds_get_steady());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_leds_get_steady_obj, mp_leds_get_steady);
STATIC mp_obj_t mp_led_set_rgb(size_t n_args, const mp_obj_t *args) {
uint8_t index = mp_obj_get_int(args[0]);
float red = mp_obj_get_float(args[1]);
......@@ -70,6 +75,19 @@ STATIC mp_obj_t mp_led_set_rgb(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_led_set_rgb_obj, 4, 4,
mp_led_set_rgb);
STATIC mp_obj_t mp_led_set_rgba(size_t n_args, const mp_obj_t *args) {
uint8_t index = mp_obj_get_int(args[0]);
float red = mp_obj_get_float(args[1]);
float green = mp_obj_get_float(args[2]);
float blue = mp_obj_get_float(args[3]);
float alpha = mp_obj_get_float(args[4]);
st3m_leds_set_single_rgba(index, red, green, blue, alpha);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_led_set_rgba_obj, 5, 5,
mp_led_set_rgba);
STATIC mp_obj_t mp_led_set_hsv(size_t n_args, const mp_obj_t *args) {
uint8_t index = mp_obj_get_int(args[0]);
float hue = mp_obj_get_float(args[1]);
......@@ -90,6 +108,17 @@ STATIC mp_obj_t mp_led_set_all_rgb(mp_obj_t r, mp_obj_t g, mp_obj_t b) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_led_set_all_rgb_obj, mp_led_set_all_rgb);
STATIC mp_obj_t mp_led_set_all_rgba(size_t n_args, const mp_obj_t *args) {
float red = mp_obj_get_float(args[0]);
float green = mp_obj_get_float(args[1]);
float blue = mp_obj_get_float(args[2]);
float alpha = mp_obj_get_float(args[3]);
st3m_leds_set_all_rgba(red, green, blue, alpha);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_led_set_all_rgba_obj, 4, 4,
mp_led_set_all_rgba);
STATIC mp_obj_t mp_led_set_all_hsv(mp_obj_t h, mp_obj_t s, mp_obj_t v) {
float hue = mp_obj_get_float(h);
float sat = mp_obj_get_float(s);
......@@ -99,6 +128,19 @@ STATIC mp_obj_t mp_led_set_all_hsv(mp_obj_t h, mp_obj_t s, mp_obj_t v) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_led_set_all_hsv_obj, mp_led_set_all_hsv);
STATIC mp_obj_t mp_led_get_rgb(mp_obj_t led_index) {
uint8_t index = mp_obj_get_int(led_index);
float red;
float green;
float blue;
st3m_leds_get_single_rgb(index, &red, &green, &blue);
mp_obj_t items[] = { mp_obj_new_float(red), mp_obj_new_float(green),
mp_obj_new_float(blue) };
return mp_obj_new_tuple(3, items);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_led_get_rgb_obj, mp_led_get_rgb);
STATIC mp_obj_t mp_leds_update() {
st3m_leds_update();
return mp_const_none;
......@@ -108,9 +150,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_leds_update_obj, mp_leds_update);
STATIC const mp_rom_map_elem_t mp_module_leds_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_leds) },
{ MP_ROM_QSTR(MP_QSTR_set_rgb), MP_ROM_PTR(&mp_led_set_rgb_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_rgba), MP_ROM_PTR(&mp_led_set_rgba_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_hsv), MP_ROM_PTR(&mp_led_set_hsv_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_all_rgb), MP_ROM_PTR(&mp_led_set_all_rgb_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_all_rgba), MP_ROM_PTR(&mp_led_set_all_rgba_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_all_hsv), MP_ROM_PTR(&mp_led_set_all_hsv_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_rgb), MP_ROM_PTR(&mp_led_get_rgb_obj) },
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mp_leds_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_brightness),
MP_ROM_PTR(&mp_leds_get_brightness_obj) },
......@@ -125,6 +170,7 @@ STATIC const mp_rom_map_elem_t mp_module_leds_globals_table[] = {
MP_ROM_PTR(&mp_leds_get_slew_rate_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_slew_rate),
MP_ROM_PTR(&mp_leds_set_slew_rate_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_steady), MP_ROM_PTR(&mp_leds_get_steady_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_leds_globals,
......
#include <st3m_media.h>
#include "py/builtin.h"
#include "py/runtime.h"
typedef struct _mp_ctx_obj_t {
mp_obj_base_t base;
Ctx *ctx;
mp_obj_t user_data;
} mp_ctx_obj_t;
STATIC mp_obj_t mp_load(size_t n_args, const mp_obj_t *args) {
bool paused = false;
if (n_args > 1) paused = args[1] == mp_const_true;
return mp_obj_new_int(st3m_media_load(mp_obj_str_get_str(args[0]), paused));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_load_obj, 1, 2, mp_load);
STATIC mp_obj_t mp_draw(mp_obj_t uctx_mp) {
mp_ctx_obj_t *uctx = MP_OBJ_TO_PTR(uctx_mp);
st3m_media_draw(uctx->ctx);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_draw_obj, mp_draw);
STATIC mp_obj_t mp_think(mp_obj_t ms_in) {
st3m_media_think(mp_obj_get_float(ms_in));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_think_obj, mp_think);
STATIC mp_obj_t mp_stop(void) {
st3m_media_stop();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_stop_obj, mp_stop);
STATIC mp_obj_t mp_pause(void) {
st3m_media_pause();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_pause_obj, mp_pause);
STATIC mp_obj_t mp_play(void) {
st3m_media_play();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_play_obj, mp_play);
STATIC mp_obj_t mp_is_playing(void) {
return mp_obj_new_bool(st3m_media_is_playing());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_is_playing_obj, mp_is_playing);
STATIC mp_obj_t mp_has_video(void) {
return mp_obj_new_bool(st3m_media_has_video());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_has_video_obj, mp_has_video);
STATIC mp_obj_t mp_has_audio(void) {
return mp_obj_new_bool(st3m_media_has_audio());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_has_audio_obj, mp_has_audio);
STATIC mp_obj_t mp_is_visual(void) {
return mp_obj_new_bool(st3m_media_is_visual());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_is_visual_obj, mp_is_visual);
STATIC mp_obj_t mp_get_duration(void) {
return mp_obj_new_float(st3m_media_get_duration());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_duration_obj, mp_get_duration);
STATIC mp_obj_t mp_get_position(void) {
return mp_obj_new_float(st3m_media_get_position());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_position_obj, mp_get_position);
STATIC mp_obj_t mp_get_time(void) {
return mp_obj_new_float(st3m_media_get_time());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_time_obj, mp_get_time);
STATIC mp_obj_t mp_seek(mp_obj_t position) {
st3m_media_seek(mp_obj_get_float(position));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_seek_obj, mp_seek);
STATIC mp_obj_t mp_seek_relative(mp_obj_t time) {
st3m_media_seek_relative(mp_obj_get_float(time));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_seek_relative_obj, mp_seek_relative);
STATIC mp_obj_t mp_set_volume(mp_obj_t volume) {
st3m_media_set_volume(mp_obj_get_float(volume));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_set_volume_obj, mp_set_volume);
STATIC mp_obj_t mp_get_volume(void) {
return mp_obj_new_float(st3m_media_get_volume());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_volume_obj, mp_get_volume);
STATIC mp_obj_t mp_set(mp_obj_t key, mp_obj_t value) {
st3m_media_set(mp_obj_str_get_str(key), mp_obj_get_float(value));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_set_obj, mp_set);
STATIC mp_obj_t mp_get(mp_obj_t key) {
return mp_obj_new_float(st3m_media_get(mp_obj_str_get_str(key)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_get_obj, mp_get);
STATIC mp_obj_t mp_get_string(mp_obj_t key) {
char *str = st3m_media_get_string(mp_obj_str_get_str(key));
if (!str) return mp_const_none;
mp_obj_t obj = mp_obj_new_str(str, strlen(str));
free(str);
return obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_get_string_obj, mp_get_string);
STATIC mp_obj_t mp_get_tags(mp_obj_t path) {
st3m_media_tags_t *tags = st3m_media_get_tags(mp_obj_str_get_str(path));
if (!tags) return mp_const_none;
mp_obj_t ret;
ret = mp_obj_new_dict(0);
char *key_str;
mp_obj_t value;
if (tags->artist && strlen(tags->artist)) {
key_str = "artist";
value = mp_obj_new_str(tags->artist, strlen(tags->artist));
mp_obj_dict_store(ret, mp_obj_new_str(key_str, strlen(key_str)), value);
}
if (tags->title && strlen(tags->title)) {
key_str = "title";
value = mp_obj_new_str(tags->title, strlen(tags->title));
mp_obj_dict_store(ret, mp_obj_new_str(key_str, strlen(key_str)), value);
}
if (tags->album && strlen(tags->album)) {
key_str = "album";
value = mp_obj_new_str(tags->album, strlen(tags->album));
mp_obj_dict_store(ret, mp_obj_new_str(key_str, strlen(key_str)), value);
}
if (tags->year) {
key_str = "year";
value = mp_obj_new_int(tags->year);
mp_obj_dict_store(ret, mp_obj_new_str(key_str, strlen(key_str)), value);
}
if (tags->track_number) {
key_str = "track number";
value = mp_obj_new_int(tags->track_number);
mp_obj_dict_store(ret, mp_obj_new_str(key_str, strlen(key_str)), value);
}
st3m_media_free_tags(tags);
return ret;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_get_tags_obj, mp_get_tags);
STATIC const mp_rom_map_elem_t globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_draw), MP_ROM_PTR(&mp_draw_obj) },
{ MP_ROM_QSTR(MP_QSTR_think), MP_ROM_PTR(&mp_think_obj) },
{ MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mp_stop_obj) },
{ MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mp_load_obj) },
{ MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&mp_pause_obj) },
{ MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&mp_play_obj) },
{ MP_ROM_QSTR(MP_QSTR_is_playing), MP_ROM_PTR(&mp_is_playing_obj) },
{ MP_ROM_QSTR(MP_QSTR_has_video), MP_ROM_PTR(&mp_has_video_obj) },
{ MP_ROM_QSTR(MP_QSTR_has_audio), MP_ROM_PTR(&mp_has_audio_obj) },
{ MP_ROM_QSTR(MP_QSTR_is_visual), MP_ROM_PTR(&mp_is_visual_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_duration), MP_ROM_PTR(&mp_get_duration_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_position), MP_ROM_PTR(&mp_get_position_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_time), MP_ROM_PTR(&mp_get_time_obj) },
{ MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_seek_obj) },
{ MP_ROM_QSTR(MP_QSTR_seek_relative), MP_ROM_PTR(&mp_seek_relative_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_volume), MP_ROM_PTR(&mp_set_volume_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_volume), MP_ROM_PTR(&mp_get_volume_obj) },
{ MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mp_set_obj) },
{ MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&mp_get_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_string), MP_ROM_PTR(&mp_get_string_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_tags), MP_ROM_PTR(&mp_get_tags_obj) },
};
STATIC MP_DEFINE_CONST_DICT(globals, globals_table);
const mp_obj_module_t mp_module_media = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&globals,
};
MP_REGISTER_MODULE(MP_QSTR_media, mp_module_media);
// SPDX-License-Identifier: CC0-1.0
#include <stdio.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "bl00mbox.h"
#include "bl00mbox_plugin_registry.h"
#include "bl00mbox_user.h"
#include "radspa.h"
// ========================
// PLUGIN OPERATIONS
// ========================
STATIC mp_obj_t mp_plugin_index_get_id(mp_obj_t index) {
/// prints name
radspa_descriptor_t *desc =
bl00mbox_plugin_registry_get_descriptor_from_index(
mp_obj_get_int(index));
if (desc == NULL) return mp_const_none;
return mp_obj_new_int(desc->id);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_plugin_index_get_id_obj,
mp_plugin_index_get_id);
STATIC mp_obj_t mp_plugin_index_get_name(mp_obj_t index) {
/// prints name
radspa_descriptor_t *desc =
bl00mbox_plugin_registry_get_descriptor_from_index(
mp_obj_get_int(index));
if (desc == NULL) return mp_const_none;
return mp_obj_new_str(desc->name, strlen(desc->name));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_plugin_index_get_name_obj,
mp_plugin_index_get_name);
STATIC mp_obj_t mp_plugin_index_get_description(mp_obj_t index) {
/// prints name
radspa_descriptor_t *desc =
bl00mbox_plugin_registry_get_descriptor_from_index(
mp_obj_get_int(index));
if (desc == NULL) return mp_const_none;
return mp_obj_new_str(desc->description, strlen(desc->description));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_plugin_index_get_description_obj,
mp_plugin_index_get_description);
STATIC mp_obj_t mp_plugin_registry_num_plugins(void) {
return mp_obj_new_int(bl00mbox_plugin_registry_get_plugin_num());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_plugin_registry_num_plugins_obj,
mp_plugin_registry_num_plugins);
// ========================
// CHANNEL OPERATIONS
// ========================
STATIC mp_obj_t mp_channel_clear(mp_obj_t index) {
return mp_obj_new_bool(bl00mbox_channel_clear(mp_obj_get_int(index)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_clear_obj, mp_channel_clear);
static mp_obj_t mp_channel_get_free(mp_obj_t index) {
return mp_obj_new_int(bl00mbox_channel_get_free(mp_obj_get_int(index)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_get_free_obj, mp_channel_get_free);
static mp_obj_t mp_channel_set_free(mp_obj_t index, mp_obj_t free) {
return mp_obj_new_int(
bl00mbox_channel_set_free(mp_obj_get_int(index), mp_obj_is_true(free)));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_set_free_obj, mp_channel_set_free);
static mp_obj_t mp_channel_get_free_index() {
return mp_obj_new_int(bl00mbox_channel_get_free_index());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_channel_get_free_index_obj,
mp_channel_get_free_index);
STATIC mp_obj_t mp_channel_get_foreground() {
return mp_obj_new_int(bl00mbox_channel_get_foreground_index());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_channel_get_foreground_obj,
mp_channel_get_foreground);
STATIC mp_obj_t mp_channel_set_foreground(mp_obj_t index) {
bl00mbox_channel_set_foreground_index(mp_obj_get_int(index));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_set_foreground_obj,
mp_channel_set_foreground);
STATIC mp_obj_t mp_channel_get_background_mute_override(mp_obj_t index) {
bool ret =
bl00mbox_channel_get_background_mute_override(mp_obj_get_int(index));
return mp_obj_new_bool(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_get_background_mute_override_obj,
mp_channel_get_background_mute_override);
STATIC mp_obj_t mp_channel_set_background_mute_override(mp_obj_t index,
mp_obj_t enable) {
bool ret = bl00mbox_channel_set_background_mute_override(
mp_obj_get_int(index), mp_obj_is_true(enable));
return mp_obj_new_bool(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_set_background_mute_override_obj,
mp_channel_set_background_mute_override);
STATIC mp_obj_t mp_channel_enable(mp_obj_t chan) {
bl00mbox_channel_enable(mp_obj_get_int(chan));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_enable_obj, mp_channel_enable);
STATIC mp_obj_t mp_channel_disable(mp_obj_t chan) {
bl00mbox_channel_disable(mp_obj_get_int(chan));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_disable_obj, mp_channel_disable);
STATIC mp_obj_t mp_channel_set_volume(mp_obj_t chan, mp_obj_t vol) {
bl00mbox_channel_set_volume(mp_obj_get_int(chan), mp_obj_get_int(vol));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_set_volume_obj,
mp_channel_set_volume);
STATIC mp_obj_t mp_channel_get_volume(mp_obj_t chan) {
return mp_obj_new_int(bl00mbox_channel_get_volume(mp_obj_get_int(chan)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_get_volume_obj,
mp_channel_get_volume);
STATIC mp_obj_t mp_channel_set_name(mp_obj_t chan, mp_obj_t name) {
char *tmp = strdup(mp_obj_str_get_str(name));
bl00mbox_channel_set_name(mp_obj_get_int(chan), tmp);
free(tmp);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_set_name_obj, mp_channel_set_name);
STATIC mp_obj_t mp_channel_get_name(mp_obj_t chan) {
char *name = bl00mbox_channel_get_name(mp_obj_get_int(chan));
if (name == NULL) return mp_const_none;
return mp_obj_new_str(name, strlen(name));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_get_name_obj, mp_channel_get_name);
STATIC mp_obj_t mp_channel_buds_num(mp_obj_t chan) {
return mp_obj_new_int(bl00mbox_channel_buds_num(mp_obj_get_int(chan)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_buds_num_obj, mp_channel_buds_num);
STATIC mp_obj_t mp_channel_get_bud_by_list_pos(mp_obj_t chan, mp_obj_t pos) {
return mp_obj_new_int(bl00mbox_channel_get_bud_by_list_pos(
mp_obj_get_int(chan), mp_obj_get_int(pos)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_get_bud_by_list_pos_obj,
mp_channel_get_bud_by_list_pos);
STATIC mp_obj_t mp_channel_conns_num(mp_obj_t chan) {
return mp_obj_new_int(bl00mbox_channel_conns_num(mp_obj_get_int(chan)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_conns_num_obj,
mp_channel_conns_num);
STATIC mp_obj_t mp_channel_mixer_num(mp_obj_t chan) {
return mp_obj_new_int(bl00mbox_channel_mixer_num(mp_obj_get_int(chan)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_channel_mixer_num_obj,
mp_channel_mixer_num);
STATIC mp_obj_t mp_channel_get_bud_by_mixer_list_pos(mp_obj_t chan,
mp_obj_t pos) {
return mp_obj_new_int(bl00mbox_channel_get_bud_by_mixer_list_pos(
mp_obj_get_int(chan), mp_obj_get_int(pos)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_get_bud_by_mixer_list_pos_obj,
mp_channel_get_bud_by_mixer_list_pos);
STATIC mp_obj_t mp_channel_get_signal_by_mixer_list_pos(mp_obj_t chan,
mp_obj_t pos) {
return mp_obj_new_int(bl00mbox_channel_get_signal_by_mixer_list_pos(
mp_obj_get_int(chan), mp_obj_get_int(pos)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_get_signal_by_mixer_list_pos_obj,
mp_channel_get_signal_by_mixer_list_pos);
// ========================
// BUD OPERATIONS
// ========================
STATIC mp_obj_t mp_channel_new_bud(mp_obj_t chan, mp_obj_t id,
mp_obj_t init_var) {
bl00mbox_bud_t *bud = bl00mbox_channel_new_bud(
mp_obj_get_int(chan), mp_obj_get_int(id), mp_obj_get_int(init_var));
if (bud == NULL) return mp_const_none;
return mp_obj_new_int(bud->index);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_new_bud_obj, mp_channel_new_bud);
STATIC mp_obj_t mp_channel_delete_bud(mp_obj_t chan, mp_obj_t bud) {
bool ret =
bl00mbox_channel_delete_bud(mp_obj_get_int(chan), mp_obj_get_int(bud));
return mp_obj_new_bool(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_delete_bud_obj,
mp_channel_delete_bud);
STATIC mp_obj_t mp_channel_bud_exists(mp_obj_t chan, mp_obj_t bud) {
bool ret =
bl00mbox_channel_bud_exists(mp_obj_get_int(chan), mp_obj_get_int(bud));
return mp_obj_new_bool(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_bud_exists_obj,
mp_channel_bud_exists);
STATIC mp_obj_t mp_channel_bud_get_name(mp_obj_t chan, mp_obj_t bud) {
char *name = bl00mbox_channel_bud_get_name(mp_obj_get_int(chan),
mp_obj_get_int(bud));
return mp_obj_new_str(name, strlen(name));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_bud_get_name_obj,
mp_channel_bud_get_name);
STATIC mp_obj_t mp_channel_bud_get_description(mp_obj_t chan, mp_obj_t bud) {
char *description = bl00mbox_channel_bud_get_description(
mp_obj_get_int(chan), mp_obj_get_int(bud));
return mp_obj_new_str(description, strlen(description));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_bud_get_description_obj,
mp_channel_bud_get_description);
STATIC mp_obj_t mp_channel_bud_get_plugin_id(mp_obj_t chan, mp_obj_t bud) {
uint32_t plugin_id = bl00mbox_channel_bud_get_plugin_id(
mp_obj_get_int(chan), mp_obj_get_int(bud));
return mp_obj_new_int(plugin_id);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_bud_get_plugin_id_obj,
mp_channel_bud_get_plugin_id);
STATIC mp_obj_t mp_channel_bud_get_num_signals(mp_obj_t chan, mp_obj_t bud) {
uint16_t ret = bl00mbox_channel_bud_get_num_signals(mp_obj_get_int(chan),
mp_obj_get_int(bud));
return mp_obj_new_int(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_bud_get_num_signals_obj,
mp_channel_bud_get_num_signals);
// ========================
// SIGNAL OPERATIONS
// ========================
STATIC mp_obj_t mp_channel_bud_get_signal_name(mp_obj_t chan, mp_obj_t bud,
mp_obj_t signal) {
char *name = bl00mbox_channel_bud_get_signal_name(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_str(name, strlen(name));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_bud_get_signal_name_obj,
mp_channel_bud_get_signal_name);
STATIC mp_obj_t mp_channel_bud_get_signal_name_multiplex(mp_obj_t chan,
mp_obj_t bud,
mp_obj_t signal) {
int8_t ret = bl00mbox_channel_bud_get_signal_name_multiplex(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_int(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_bud_get_signal_name_multiplex_obj,
mp_channel_bud_get_signal_name_multiplex);
STATIC mp_obj_t mp_channel_bud_get_signal_description(mp_obj_t chan,
mp_obj_t bud,
mp_obj_t signal) {
char *description = bl00mbox_channel_bud_get_signal_description(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_str(description, strlen(description));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_bud_get_signal_description_obj,
mp_channel_bud_get_signal_description);
STATIC mp_obj_t mp_channel_bud_get_signal_unit(mp_obj_t chan, mp_obj_t bud,
mp_obj_t signal) {
char *unit = bl00mbox_channel_bud_get_signal_unit(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_str(unit, strlen(unit));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_bud_get_signal_unit_obj,
mp_channel_bud_get_signal_unit);
STATIC mp_obj_t mp_channel_bud_get_signal_hints(mp_obj_t chan, mp_obj_t bud,
mp_obj_t signal) {
uint32_t val = bl00mbox_channel_bud_get_signal_hints(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_int(val);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_bud_get_signal_hints_obj,
mp_channel_bud_get_signal_hints);
STATIC mp_obj_t mp_channel_bud_set_signal_value(size_t n_args,
const mp_obj_t *args) {
bool success = bl00mbox_channel_bud_set_signal_value(
mp_obj_get_int(args[0]), // chan
mp_obj_get_int(args[1]), // bud_index
mp_obj_get_int(args[2]), // bud_signal_index
mp_obj_get_int(args[3])); // value
return mp_obj_new_bool(success);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_channel_bud_set_signal_value_obj,
4, 4,
mp_channel_bud_set_signal_value);
STATIC mp_obj_t mp_channel_bud_get_signal_value(mp_obj_t chan, mp_obj_t bud,
mp_obj_t signal) {
int16_t val = bl00mbox_channel_bud_get_signal_value(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_int(val);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_bud_get_signal_value_obj,
mp_channel_bud_get_signal_value);
STATIC mp_obj_t mp_channel_subscriber_num(mp_obj_t chan, mp_obj_t bud,
mp_obj_t signal) {
return mp_obj_new_int(bl00mbox_channel_subscriber_num(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_subscriber_num_obj,
mp_channel_subscriber_num);
STATIC mp_obj_t
mp_channel_get_bud_by_subscriber_list_pos(size_t n_args, const mp_obj_t *args) {
return mp_obj_new_int(bl00mbox_channel_get_bud_by_subscriber_list_pos(
mp_obj_get_int(args[0]), // chan
mp_obj_get_int(args[1]), // bud_index
mp_obj_get_int(args[2]), // bud_signal_index
mp_obj_get_int(args[3])) // pos
);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
mp_channel_get_bud_by_subscriber_list_pos_obj, 4, 4,
mp_channel_get_bud_by_subscriber_list_pos);
STATIC mp_obj_t mp_channel_get_signal_by_subscriber_list_pos(
size_t n_args, const mp_obj_t *args) {
return mp_obj_new_int(bl00mbox_channel_get_signal_by_subscriber_list_pos(
mp_obj_get_int(args[0]), // chan
mp_obj_get_int(args[1]), // bud_index
mp_obj_get_int(args[2]), // bud_signal_index
mp_obj_get_int(args[3])) // pos
);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
mp_channel_get_signal_by_subscriber_list_pos_obj, 4, 4,
mp_channel_get_signal_by_subscriber_list_pos);
STATIC mp_obj_t mp_channel_get_source_bud(mp_obj_t chan, mp_obj_t bud,
mp_obj_t signal) {
uint64_t val = bl00mbox_channel_get_source_bud(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_int(val);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_get_source_bud_obj,
mp_channel_get_source_bud);
STATIC mp_obj_t mp_channel_get_source_signal(mp_obj_t chan, mp_obj_t bud,
mp_obj_t signal) {
uint64_t val = bl00mbox_channel_get_source_signal(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_int(val);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_get_source_signal_obj,
mp_channel_get_source_signal);
// ========================
// TABLE OPERATIONS
// ========================
STATIC mp_obj_t mp_channel_bud_set_table_value(size_t n_args,
const mp_obj_t *args) {
bool success = bl00mbox_channel_bud_set_table_value(
mp_obj_get_int(args[0]), // chan
mp_obj_get_int(args[1]), // bud_index
mp_obj_get_int(args[2]), // table_index
mp_obj_get_int(args[3])); // value
return mp_obj_new_bool(success);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_channel_bud_set_table_value_obj,
4, 4,
mp_channel_bud_set_table_value);
STATIC mp_obj_t mp_channel_bud_get_table_value(mp_obj_t chan, mp_obj_t bud,
mp_obj_t table_index) {
int16_t val = bl00mbox_channel_bud_get_table_value(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(table_index));
return mp_obj_new_int(val);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_bud_get_table_value_obj,
mp_channel_bud_get_table_value);
STATIC mp_obj_t mp_channel_bud_get_table_pointer(mp_obj_t chan, mp_obj_t bud) {
int16_t *val = bl00mbox_channel_bud_get_table_pointer(mp_obj_get_int(chan),
mp_obj_get_int(bud));
return mp_obj_new_int_from_uint((uint32_t)val);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_bud_get_table_pointer_obj,
mp_channel_bud_get_table_pointer);
STATIC mp_obj_t mp_channel_bud_get_table_len(mp_obj_t chan, mp_obj_t bud) {
uint32_t val = bl00mbox_channel_bud_get_table_len(mp_obj_get_int(chan),
mp_obj_get_int(bud));
return mp_obj_new_int_from_uint(val);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_channel_bud_get_table_len_obj,
mp_channel_bud_get_table_len);
// ========================
// CONNECTION OPERATIONS
// ========================
STATIC mp_obj_t mp_channel_disconnect_signal_rx(mp_obj_t chan, mp_obj_t bud,
mp_obj_t signal) {
bool ret = bl00mbox_channel_disconnect_signal_rx(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_bool(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_disconnect_signal_rx_obj,
mp_channel_disconnect_signal_rx);
STATIC mp_obj_t mp_channel_disconnect_signal_tx(mp_obj_t chan, mp_obj_t bud,
mp_obj_t signal) {
bool ret = bl00mbox_channel_disconnect_signal_tx(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_bool(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_disconnect_signal_tx_obj,
mp_channel_disconnect_signal_tx);
STATIC mp_obj_t mp_channel_connect_signal(size_t n_args, const mp_obj_t *args) {
bool success = bl00mbox_channel_connect_signal(
mp_obj_get_int(args[0]), // chan
mp_obj_get_int(args[1]), // bud_tx_index
mp_obj_get_int(args[2]), // bud_tx_signal_index
mp_obj_get_int(args[3]), // bud_tx_index
mp_obj_get_int(args[4])); // bud_tx_signal_index
return mp_obj_new_bool(success);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_channel_connect_signal_obj, 5, 5,
mp_channel_connect_signal);
STATIC mp_obj_t mp_channel_connect_signal_to_output_mixer(
mp_obj_t chan, mp_obj_t bud_index, mp_obj_t bud_signal_index) {
bool success = bl00mbox_channel_connect_signal_to_output_mixer(
mp_obj_get_int(chan), mp_obj_get_int(bud_index),
mp_obj_get_int(bud_signal_index));
return mp_obj_new_bool(success);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_channel_connect_signal_to_output_mixer_obj,
mp_channel_connect_signal_to_output_mixer);
STATIC mp_obj_t mp_channel_disconnect_signal_from_output_mixer(
mp_obj_t chan, mp_obj_t bud, mp_obj_t signal) {
bool ret = bl00mbox_channel_disconnect_signal_from_output_mixer(
mp_obj_get_int(chan), mp_obj_get_int(bud), mp_obj_get_int(signal));
return mp_obj_new_bool(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(
mp_channel_disconnect_signal_from_output_mixer_obj,
mp_channel_disconnect_signal_from_output_mixer);
STATIC const mp_map_elem_t bl00mbox_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__),
MP_OBJ_NEW_QSTR(MP_QSTR_sys_bl00mbox) },
// PLUGIN OPERATIONS
{ MP_ROM_QSTR(MP_QSTR_plugin_registry_num_plugins),
MP_ROM_PTR(&mp_plugin_registry_num_plugins_obj) },
{ MP_ROM_QSTR(MP_QSTR_plugin_index_get_id),
MP_ROM_PTR(&mp_plugin_index_get_id_obj) },
{ MP_ROM_QSTR(MP_QSTR_plugin_index_get_name),
MP_ROM_PTR(&mp_plugin_index_get_name_obj) },
{ MP_ROM_QSTR(MP_QSTR_plugin_index_get_description),
MP_ROM_PTR(&mp_plugin_index_get_description_obj) },
// CHANNEL OPERATIONS
{ MP_ROM_QSTR(MP_QSTR_channel_get_free),
MP_ROM_PTR(&mp_channel_get_free_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_set_free),
MP_ROM_PTR(&mp_channel_set_free_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_free_index),
MP_ROM_PTR(&mp_channel_get_free_index_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_foreground),
MP_ROM_PTR(&mp_channel_get_foreground_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_set_foreground),
MP_ROM_PTR(&mp_channel_set_foreground_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_background_mute_override),
MP_ROM_PTR(&mp_channel_get_background_mute_override_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_set_background_mute_override),
MP_ROM_PTR(&mp_channel_set_background_mute_override_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_enable), MP_ROM_PTR(&mp_channel_enable_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_disable),
MP_ROM_PTR(&mp_channel_disable_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_clear), MP_ROM_PTR(&mp_channel_clear_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_set_volume),
MP_ROM_PTR(&mp_channel_set_volume_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_volume),
MP_ROM_PTR(&mp_channel_get_volume_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_set_name),
MP_ROM_PTR(&mp_channel_set_name_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_name),
MP_ROM_PTR(&mp_channel_get_name_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_buds_num),
MP_ROM_PTR(&mp_channel_buds_num_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_bud_by_list_pos),
MP_ROM_PTR(&mp_channel_get_bud_by_list_pos_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_conns_num),
MP_ROM_PTR(&mp_channel_conns_num_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_mixer_num),
MP_ROM_PTR(&mp_channel_mixer_num_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_bud_by_mixer_list_pos),
MP_ROM_PTR(&mp_channel_get_bud_by_mixer_list_pos_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_signal_by_mixer_list_pos),
MP_ROM_PTR(&mp_channel_get_signal_by_mixer_list_pos_obj) },
// BUD OPERATIONS
{ MP_ROM_QSTR(MP_QSTR_channel_new_bud),
MP_ROM_PTR(&mp_channel_new_bud_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_delete_bud),
MP_ROM_PTR(&mp_channel_delete_bud_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_exists),
MP_ROM_PTR(&mp_channel_bud_exists_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_name),
MP_ROM_PTR(&mp_channel_bud_get_name_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_description),
MP_ROM_PTR(&mp_channel_bud_get_description_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_plugin_id),
MP_ROM_PTR(&mp_channel_bud_get_plugin_id_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_num_signals),
MP_ROM_PTR(&mp_channel_bud_get_num_signals_obj) },
// SIGNAL OPERATIONS
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_signal_name),
MP_ROM_PTR(&mp_channel_bud_get_signal_name_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_signal_name_multiplex),
MP_ROM_PTR(&mp_channel_bud_get_signal_name_multiplex_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_signal_description),
MP_ROM_PTR(&mp_channel_bud_get_signal_description_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_signal_unit),
MP_ROM_PTR(&mp_channel_bud_get_signal_unit_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_set_signal_value),
MP_ROM_PTR(&mp_channel_bud_set_signal_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_signal_value),
MP_ROM_PTR(&mp_channel_bud_get_signal_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_signal_hints),
MP_ROM_PTR(&mp_channel_bud_get_signal_hints_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_subscriber_num),
MP_ROM_PTR(&mp_channel_subscriber_num_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_bud_by_subscriber_list_pos),
MP_ROM_PTR(&mp_channel_get_bud_by_subscriber_list_pos_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_signal_by_subscriber_list_pos),
MP_ROM_PTR(&mp_channel_get_signal_by_subscriber_list_pos_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_source_bud),
MP_ROM_PTR(&mp_channel_get_source_bud_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_get_source_signal),
MP_ROM_PTR(&mp_channel_get_source_signal_obj) },
// TABLE OPERATIONS
{ MP_ROM_QSTR(MP_QSTR_channel_bud_set_table_value),
MP_ROM_PTR(&mp_channel_bud_set_table_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_table_value),
MP_ROM_PTR(&mp_channel_bud_get_table_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_table_pointer),
MP_ROM_PTR(&mp_channel_bud_get_table_pointer_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_bud_get_table_len),
MP_ROM_PTR(&mp_channel_bud_get_table_len_obj) },
// CONNECTION OPERATIONS
{ MP_ROM_QSTR(MP_QSTR_channel_connect_signal),
MP_ROM_PTR(&mp_channel_connect_signal_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_disconnect_signal_rx),
MP_ROM_PTR(&mp_channel_disconnect_signal_rx_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_disconnect_signal_tx),
MP_ROM_PTR(&mp_channel_disconnect_signal_tx_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_connect_signal_to_output_mixer),
MP_ROM_PTR(&mp_channel_connect_signal_to_output_mixer_obj) },
{ MP_ROM_QSTR(MP_QSTR_channel_disconnect_signal_from_output_mixer),
MP_ROM_PTR(&mp_channel_disconnect_signal_from_output_mixer_obj) },
// CONSTANTS
{ MP_ROM_QSTR(MP_QSTR_NUM_CHANNELS), MP_ROM_INT(BL00MBOX_CHANNELS) },
{ MP_ROM_QSTR(MP_QSTR_RADSPA_SIGNAL_HINT_SCT),
MP_ROM_INT(RADSPA_SIGNAL_HINT_SCT) },
{ MP_ROM_QSTR(MP_QSTR_RADSPA_SIGNAL_HINT_GAIN),
MP_ROM_INT(RADSPA_SIGNAL_HINT_GAIN) },
{ MP_ROM_QSTR(MP_QSTR_RADSPA_SIGNAL_HINT_TRIGGER),
MP_ROM_INT(RADSPA_SIGNAL_HINT_TRIGGER) },
{ MP_ROM_QSTR(MP_QSTR_BL00MBOX_CHANNELS), MP_ROM_INT(BL00MBOX_CHANNELS) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_bl00mbox_globals, bl00mbox_globals_table);
const mp_obj_module_t bl00mbox_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_bl00mbox_globals,
};
MP_REGISTER_MODULE(MP_QSTR_sys_bl00mbox, bl00mbox_user_cmodule);
../../bl00mbox/micropython/mp_sys_bl00mbox.c
\ No newline at end of file
......@@ -18,26 +18,44 @@
#include "mp_uctx.h"
STATIC mp_obj_t mp_get_left() {
return mp_obj_new_int(st3m_io_left_button_get());
STATIC mp_obj_t mp_get_app(void) {
return mp_obj_new_int(st3m_io_app_button_get());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_left_obj, mp_get_left);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_app_obj, mp_get_app);
STATIC mp_obj_t mp_get_right() {
return mp_obj_new_int(st3m_io_right_button_get());
STATIC mp_obj_t mp_get_os(void) {
return mp_obj_new_int(st3m_io_os_button_get());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_right_obj, mp_get_right);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_os_obj, mp_get_os);
STATIC mp_obj_t mp_configure(mp_obj_t left_in) {
bool left = mp_obj_is_true(left_in);
st3m_io_app_button_configure(left);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_configure_obj, mp_configure);
STATIC mp_obj_t mp_app_is_left(void) {
return mp_obj_new_bool(st3m_io_app_button_is_left());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_app_is_left_obj, mp_app_is_left);
STATIC const mp_rom_map_elem_t mp_module_sys_buttons_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys_buttons) },
{ MP_ROM_QSTR(MP_QSTR_get_left), MP_ROM_PTR(&mp_get_left_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_right), MP_ROM_PTR(&mp_get_right_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_app), MP_ROM_PTR(&mp_get_app_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_os), MP_ROM_PTR(&mp_get_os_obj) },
{ MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&mp_configure_obj) },
{ MP_ROM_QSTR(MP_QSTR_app_is_left), MP_ROM_PTR(&mp_app_is_left_obj) },
{ MP_ROM_QSTR(MP_QSTR_PRESSED_LEFT), MP_ROM_INT(st3m_tripos_left) },
{ MP_ROM_QSTR(MP_QSTR_PRESSED_RIGHT), MP_ROM_INT(st3m_tripos_right) },
{ MP_ROM_QSTR(MP_QSTR_PRESSED_DOWN), MP_ROM_INT(st3m_tripos_mid) },
{ MP_ROM_QSTR(MP_QSTR_NOT_PRESSED), MP_ROM_INT(st3m_tripos_none) },
// deperecated calls last - and slowest to access during method dispatch
{ MP_ROM_QSTR(MP_QSTR_get_left), MP_ROM_PTR(&mp_get_app_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_right), MP_ROM_PTR(&mp_get_os_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_sys_buttons_globals,
......
#include "st3m_colors.h"
#include "py/builtin.h"
#include "py/runtime.h"
STATIC mp_obj_t mp_hsv_to_rgb(mp_obj_t h, mp_obj_t s, mp_obj_t v) {
float hsv_f[3] = { mp_obj_get_float(h), mp_obj_get_float(s),
mp_obj_get_float(v) };
// hue gets clipped internally somewhat
for (uint8_t i = 1; i < 3; i++) {
if (hsv_f[i] > 1.0) {
hsv_f[i] = 1.0;
} else if (hsv_f[i] < 0.0) {
hsv_f[i] = 0.0;
}
}
st3m_hsv_t hsv = { hsv_f[0], hsv_f[1], hsv_f[2] };
st3m_rgb_t rgb = st3m_hsv_to_rgb(hsv);
mp_obj_t items[3] = { mp_obj_new_float(rgb.r), mp_obj_new_float(rgb.g),
mp_obj_new_float(rgb.b) };
return mp_obj_new_tuple(3, items);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_hsv_to_rgb_obj, mp_hsv_to_rgb);
STATIC mp_obj_t mp_rgb_to_hsv(mp_obj_t r, mp_obj_t g, mp_obj_t b) {
float rgb_f[3] = { mp_obj_get_float(r), mp_obj_get_float(g),
mp_obj_get_float(b) };
for (uint8_t i = 0; i < 3; i++) {
if (rgb_f[i] > 1.0) {
rgb_f[i] = 1.0;
} else if (rgb_f[i] < 0.0) {
rgb_f[i] = 0.0;
}
}
st3m_rgb_t rgb = { rgb_f[0], rgb_f[1], rgb_f[2] };
st3m_hsv_t hsv = st3m_rgb_to_hsv(rgb);
mp_obj_t items[3] = { mp_obj_new_float(hsv.h), mp_obj_new_float(hsv.s),
mp_obj_new_float(hsv.v) };
return mp_obj_new_tuple(3, items);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_rgb_to_hsv_obj, mp_rgb_to_hsv);
STATIC const mp_rom_map_elem_t globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_hsv_to_rgb), MP_ROM_PTR(&mp_hsv_to_rgb_obj) },
{ MP_ROM_QSTR(MP_QSTR_rgb_to_hsv), MP_ROM_PTR(&mp_rgb_to_hsv_obj) },
};
STATIC MP_DEFINE_CONST_DICT(globals, globals_table);
const mp_obj_module_t mp_module_colors_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&globals,
};
MP_REGISTER_MODULE(MP_QSTR_sys_colors, mp_module_colors_user_cmodule);
......@@ -18,7 +18,23 @@
#include "mp_uctx.h"
static st3m_ctx_desc_t *gfx_last_desc = NULL;
STATIC mp_obj_t mp_fps(void) { return mp_obj_new_float(st3m_gfx_fps()); }
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_fps_obj, mp_fps);
STATIC mp_obj_t mp_overlay_clip(size_t n_arge, const mp_obj_t *args) {
st3m_gfx_overlay_clip(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]),
mp_obj_get_int(args[2]), mp_obj_get_int(args[3]));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_overlay_clip_obj, 4, 4,
mp_overlay_clip);
STATIC mp_obj_t mp_fbconfig(size_t n_arge, const mp_obj_t *args) {
st3m_gfx_fbconfig(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]),
mp_obj_get_int(args[2]), mp_obj_get_int(args[3]));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_fbconfig_obj, 4, 4, mp_fbconfig);
STATIC mp_obj_t mp_set_backlight(mp_obj_t percent_in) {
uint8_t percent = mp_obj_get_int(percent_in);
......@@ -27,17 +43,56 @@ STATIC mp_obj_t mp_set_backlight(mp_obj_t percent_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_set_backlight_obj, mp_set_backlight);
STATIC mp_obj_t mp_get_ctx(void) {
if (gfx_last_desc == NULL) {
gfx_last_desc = st3m_gfx_drawctx_free_get(0);
if (gfx_last_desc == NULL) {
STATIC mp_obj_t mp_set_mode(mp_obj_t mode) {
st3m_gfx_set_mode(mp_obj_get_int(mode));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_set_mode_obj, mp_set_mode);
STATIC mp_obj_t mp_set_default_mode(mp_obj_t mode) {
st3m_gfx_set_default_mode(mp_obj_get_int(mode));
return mp_const_none;
}
mp_obj_t mp_ctx = mp_ctx_from_ctx(gfx_last_desc->ctx);
return mp_ctx;
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_set_default_mode_obj, mp_set_default_mode);
STATIC mp_obj_t mp_get_mode(void) {
return mp_obj_new_int(st3m_gfx_get_mode());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_mode_obj, mp_get_mode);
STATIC mp_obj_t mp_set_palette(mp_obj_t pal_in) {
size_t count = mp_obj_get_int(mp_obj_len(pal_in));
uint8_t *pal = m_malloc(count);
for (size_t i = 0; i < count; i++) {
pal[i] = mp_obj_get_int(
mp_obj_subscr(pal_in, mp_obj_new_int(i), MP_OBJ_SENTINEL));
}
st3m_gfx_set_palette(pal, count / 3);
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
m_free(pal, count);
#else
m_free(pal);
#endif
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_set_palette_obj, mp_set_palette);
STATIC mp_obj_t mp_ctx(mp_obj_t mode_in) {
return mp_ctx_from_ctx(st3m_gfx_ctx(mp_obj_get_int(mode_in)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_ctx_obj, mp_get_ctx);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_ctx_obj, mp_ctx);
STATIC mp_obj_t mp_fb(mp_obj_t mode_in) {
int mode = mp_obj_get_int(mode_in);
int stride, width, height;
void *fb = st3m_gfx_fb(mode, &width, &height, &stride);
int size = height * stride;
mp_obj_t items[4] = { mp_obj_new_bytearray_by_ref(size, fb),
mp_obj_new_int(width), mp_obj_new_int(height),
mp_obj_new_int(stride) };
return mp_obj_new_tuple(4, items);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_fb_obj, mp_fb);
STATIC mp_obj_t mp_update(mp_obj_t ctx_in) {
mp_ctx_obj_t *self = MP_OBJ_TO_PTR(ctx_in);
......@@ -45,30 +100,29 @@ STATIC mp_obj_t mp_update(mp_obj_t ctx_in) {
mp_raise_ValueError("not a ctx");
return mp_const_none;
}
if (gfx_last_desc != NULL) {
if (gfx_last_desc->ctx != self->ctx) {
mp_raise_ValueError(
"not the correct ctx (do not hold on to ctx objects!)");
return mp_const_none;
}
st3m_gfx_drawctx_pipe_put(gfx_last_desc);
gfx_last_desc = NULL;
}
st3m_gfx_end_frame(self->ctx);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_update_obj, mp_update);
STATIC mp_obj_t mp_pipe_full(void) {
if (st3m_gfx_drawctx_pipe_full()) {
if (st3m_gfx_pipe_full()) {
return mp_const_true;
}
return mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_pipe_full_obj, mp_pipe_full);
STATIC mp_obj_t mp_pipe_available(void) {
if (st3m_gfx_pipe_available()) {
return mp_const_true;
}
return mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_pipe_available_obj, mp_pipe_available);
STATIC mp_obj_t mp_pipe_flush(void) {
st3m_gfx_flush();
st3m_gfx_flush(1000);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_pipe_flush_obj, mp_pipe_flush);
......@@ -76,10 +130,43 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_pipe_flush_obj, mp_pipe_flush);
STATIC const mp_rom_map_elem_t mp_module_sys_display_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys_display) },
{ MP_ROM_QSTR(MP_QSTR_pipe_full), MP_ROM_PTR(&mp_pipe_full_obj) },
{ MP_ROM_QSTR(MP_QSTR_pipe_available), MP_ROM_PTR(&mp_pipe_available_obj) },
{ MP_ROM_QSTR(MP_QSTR_pipe_flush), MP_ROM_PTR(&mp_pipe_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_backlight), MP_ROM_PTR(&mp_set_backlight_obj) },
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mp_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_ctx), MP_ROM_PTR(&mp_get_ctx_obj) },
{ MP_ROM_QSTR(MP_QSTR_fb), MP_ROM_PTR(&mp_fb_obj) },
{ MP_ROM_QSTR(MP_QSTR_ctx), MP_ROM_PTR(&mp_ctx_obj) },
{ MP_ROM_QSTR(MP_QSTR_fps), MP_ROM_PTR(&mp_fps_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_mode), MP_ROM_PTR(&mp_set_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_mode), MP_ROM_PTR(&mp_get_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_default_mode),
MP_ROM_PTR(&mp_set_default_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_palette), MP_ROM_PTR(&mp_set_palette_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_backlight), MP_ROM_PTR(&mp_set_backlight_obj) },
{ MP_ROM_QSTR(MP_QSTR_overlay_clip), MP_ROM_PTR(&mp_overlay_clip_obj) },
{ MP_ROM_QSTR(MP_QSTR_fbconfig), MP_ROM_PTR(&mp_fbconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_default), MP_ROM_INT((int)st3m_gfx_default) },
{ MP_ROM_QSTR(MP_QSTR_rgb332), MP_ROM_INT((int)st3m_gfx_rgb332) },
{ MP_ROM_QSTR(MP_QSTR_sepia), MP_ROM_INT((int)st3m_gfx_sepia) },
{ MP_ROM_QSTR(MP_QSTR_cool), MP_ROM_INT((int)st3m_gfx_cool) },
{ MP_ROM_QSTR(MP_QSTR_low_latency), MP_ROM_INT((int)st3m_gfx_low_latency) },
{ MP_ROM_QSTR(MP_QSTR_direct_ctx), MP_ROM_INT((int)st3m_gfx_direct_ctx) },
{ MP_ROM_QSTR(MP_QSTR_lock), MP_ROM_INT((int)st3m_gfx_lock) },
{ MP_ROM_QSTR(MP_QSTR_EXPERIMENTAL_think_per_draw),
MP_ROM_INT((int)st3m_gfx_EXPERIMENTAL_think_per_draw) },
{ MP_ROM_QSTR(MP_QSTR_smart_redraw),
MP_ROM_INT((int)st3m_gfx_smart_redraw) },
{ MP_ROM_QSTR(MP_QSTR_x2), MP_ROM_INT((int)st3m_gfx_2x) },
{ MP_ROM_QSTR(MP_QSTR_x3), MP_ROM_INT((int)st3m_gfx_3x) },
{ MP_ROM_QSTR(MP_QSTR_x4), MP_ROM_INT((int)st3m_gfx_4x) },
{ MP_ROM_QSTR(MP_QSTR_bpp1), MP_ROM_INT((int)st3m_gfx_1bpp) },
{ MP_ROM_QSTR(MP_QSTR_bpp2), MP_ROM_INT((int)st3m_gfx_2bpp) },
{ MP_ROM_QSTR(MP_QSTR_bpp4), MP_ROM_INT((int)st3m_gfx_4bpp) },
{ MP_ROM_QSTR(MP_QSTR_bpp8), MP_ROM_INT((int)st3m_gfx_8bpp) },
{ MP_ROM_QSTR(MP_QSTR_bpp16), MP_ROM_INT((int)st3m_gfx_16bpp) },
{ MP_ROM_QSTR(MP_QSTR_bpp24), MP_ROM_INT((int)st3m_gfx_24bpp) },
{ MP_ROM_QSTR(MP_QSTR_osd), MP_ROM_INT((int)st3m_gfx_osd) },
{ MP_ROM_QSTR(MP_QSTR_palette), MP_ROM_INT((int)st3m_gfx_palette) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_sys_display_globals,
......