From b47c4e70c358d90f549daffc9e86ed9e592ab24d Mon Sep 17 00:00:00 2001 From: Ubaldo Porcheddu Date: Thu, 3 Sep 2020 16:37:07 +0100 Subject: [PATCH 1/4] preliminary audio support --- ports/gprs_a9/Makefile | 1 + ports/gprs_a9/modaudio.c | 231 +++++++++++++++++++++++++++++++++++ ports/gprs_a9/mpconfigport.h | 2 + 3 files changed, 234 insertions(+) create mode 100644 ports/gprs_a9/modaudio.c diff --git a/ports/gprs_a9/Makefile b/ports/gprs_a9/Makefile index 72110df05be70..ed1b204794d55 100644 --- a/ports/gprs_a9/Makefile +++ b/ports/gprs_a9/Makefile @@ -139,6 +139,7 @@ SRC_C = \ modgps.c \ modusocket.c \ modi2c.c \ + modaudio.c \ machine_adc.c \ machine_uart.c \ machine_rtc.c diff --git a/ports/gprs_a9/modaudio.c b/ports/gprs_a9/modaudio.c new file mode 100644 index 0000000000000..0dc7b6a9ca2be --- /dev/null +++ b/ports/gprs_a9/modaudio.c @@ -0,0 +1,231 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * Development of the code in this file was sponsored by Microbric Pty Ltd + * + * The MIT License (MIT) + * + * Copyright (c) 2020 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "timeout.h" +#include "api_os.h" +#include "api_audio.h" +#include "api_fs.h" +#include "py/runtime.h" + +uint8_t audioTimeout = 5; +uint8_t audioVolume = 5; +bool audioPlayEnd = true; + + +void audioRecordCallback(AUDIO_Error_t result) +{ + if (result != AUDIO_ERROR_NO) { + Trace(1,"audio record error: %d", result); + } +} + + +STATIC mp_obj_t modaudio_record(size_t n_args, const mp_obj_t *args) { + // ======================================== + // Audio Record. + // Args: + // filename (str): output file name with full path + // timeout (int): timeout in seconds (default 5) + // channel (int): audio channel (default 2, AUDIO_MODE_LOUDSPEAKER) + // type (int): audio type (default 3, AUDIO_TYPE_AMR) + // mode (int): audio mode (default 7, AUDIO_RECORD_MODE_AMR122) + // ======================================== + + int timeout = audioTimeout; + int channel = AUDIO_MODE_LOUDSPEAKER; + int type = AUDIO_TYPE_AMR; + int mode = AUDIO_RECORD_MODE_AMR122; + const char* filename; + + if (n_args > 0) { + filename = mp_obj_str_get_str(args[0]); + } else { + mp_raise_ValueError("filename is mandatory"); + return mp_const_none; + } + if (n_args >= 2) { + timeout = mp_obj_get_int(args[1]); + } + if (n_args >= 3) { + channel = mp_obj_get_int(args[2]); + } + if (n_args >= 3) { + type = mp_obj_get_int(args[3]); + } + if (n_args >= 4) { + mode = mp_obj_get_int(args[4]); + } + Trace(1,"record start, filename: %s, timeout: %d, channel: %d, type: %d, mode: %d", filename, timeout, channel, type, mode); + int audioRecordFd = API_FS_Open(filename,FS_O_WRONLY|FS_O_CREAT|FS_O_TRUNC,0); + if(audioRecordFd < 0) { + Trace(1,"audio open file error"); + mp_raise_ValueError("file error"); + return mp_const_none; + } + AUDIO_SetMode(channel); + AUDIO_Error_t result = AUDIO_RecordStart(type, mode, audioRecordFd, audioRecordCallback, NULL); + if (result != AUDIO_ERROR_NO) { + Trace(1,"record start fail: %d",result); + API_FS_Close(audioRecordFd); + audioRecordFd = -1; + mp_raise_ValueError("cannot start recording"); + return mp_const_none; + } + Trace(1,"record start"); + while(--timeout) + { + Trace(1,"recording"); + OS_Sleep(1000); + } + Trace(1,"record stop"); + AUDIO_RecordStop(); + API_FS_Close(audioRecordFd); + audioRecordFd = -1; + Trace(1,"record end"); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_record_obj, 1, 2, modaudio_record); + + +STATIC mp_obj_t modaudio_record_stop(void) { + //Stop recording audio + AUDIO_RecordStop(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_record_stop_obj, modaudio_record_stop); + + +void audioPlayCallback(AUDIO_Error_t result) +{ + Trace(1,"play callback result: %d",result); + if (AUDIO_ERROR_END_OF_FILE == result) { + Trace(1,"play music file end"); + } + audioPlayEnd = true; + AUDIO_Stop(); +} + + +STATIC mp_obj_t modaudio_play(size_t n_args, const mp_obj_t *args) { + // ======================================== + // Audio Play. + // Args: + // filename (str): input file name with full path + // volume (int): (default 5) + // channel (int): audio channel (default 2, AUDIO_MODE_LOUDSPEAKER) + // type (int): audio type (default 3, AUDIO_TYPE_AMR) + // ======================================== + int volume = audioVolume; + int channel = AUDIO_MODE_LOUDSPEAKER; + int type = AUDIO_TYPE_AMR; + const char* filename; + if (n_args > 0) { + filename = mp_obj_str_get_str(args[0]); + } else { + mp_raise_ValueError("filename is mandatory"); + return mp_const_none; + } + if (n_args >= 2) { + volume = mp_obj_get_int(args[1]); + } + if (n_args >= 3) { + channel = mp_obj_get_int(args[2]); + } + if (n_args >= 3) { + type = mp_obj_get_int(args[3]); + } + Trace(1,"play start, filename: %s, volume: %d, channel: %d, type: %d", filename, volume, channel, type); + + AUDIO_Error_t ret = AUDIO_Play(filename, type, audioPlayCallback); + if( ret != AUDIO_ERROR_NO) + { + Trace(1,"play music fail: %d",ret); + mp_raise_ValueError("cannot play file"); + return mp_const_none; + } + else + { + audioPlayEnd = false; + Trace(1,"play music success"); + } + OS_Sleep(200); + AUDIO_SetMode(channel); + AUDIO_SpeakerOpen(); + AUDIO_SpeakerSetVolume(volume); + + uint8_t i = AUDIO_EQ_NORMAL; + while(!audioPlayEnd) + { + OS_Sleep(1000); + } + + Trace(1,"play end"); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_play_obj, 1, 2, modaudio_play); + +/* +STATIC mp_obj_t modaudio_pause(void) { + //Pause audio play + AUDIO_Pause(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_pause_obj, modaudio_pause); + + +STATIC mp_obj_t modaudio_resume(void) { + //Resume playing from pause + AUDIO_Resume(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_resume_obj, modaudio_resume); +*/ + +STATIC mp_obj_t modaudio_play_stop(void) { + //Stop playing audio + AUDIO_Stop(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_play_stop_obj, modaudio_play_stop); + + +STATIC const mp_map_elem_t mp_module_audio_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_audio) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_record), (mp_obj_t)&modaudio_record_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_record_stop), (mp_obj_t)&modaudio_record_stop_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_play), (mp_obj_t)&modaudio_play_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_play_stop), (mp_obj_t)&modaudio_play_stop_obj }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_audio_globals, mp_module_audio_globals_table); + + +const mp_obj_module_t audio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_audio_globals, +}; diff --git a/ports/gprs_a9/mpconfigport.h b/ports/gprs_a9/mpconfigport.h index d3d0cbb24b324..84ab9618fe0c0 100644 --- a/ports/gprs_a9/mpconfigport.h +++ b/ports/gprs_a9/mpconfigport.h @@ -212,6 +212,7 @@ extern const struct _mp_obj_module_t cellular_module; extern const struct _mp_obj_module_t gps_module; extern const struct _mp_obj_module_t usocket_module; extern const struct _mp_obj_module_t i2c_module; +extern const struct _mp_obj_module_t audio_module; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ @@ -222,6 +223,7 @@ extern const struct _mp_obj_module_t i2c_module; { MP_OBJ_NEW_QSTR(MP_QSTR_gps), (mp_obj_t)&gps_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&usocket_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_i2c), (mp_obj_t)&i2c_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_audio), (mp_obj_t)&audio_module }, \ // type definitions for the specific machine From 9c61c5a7c4b3ed4e31c1b9c8742e6348cea0d2b4 Mon Sep 17 00:00:00 2001 From: Ubaldo Porcheddu Date: Fri, 4 Sep 2020 13:10:19 +0100 Subject: [PATCH 2/4] removed sleep loop in record and play functions and renamed both to play_start and record_start --- ports/gprs_a9/modaudio.c | 125 ++++++++++++++------------------------- 1 file changed, 45 insertions(+), 80 deletions(-) diff --git a/ports/gprs_a9/modaudio.c b/ports/gprs_a9/modaudio.c index 0dc7b6a9ca2be..13838a0b05015 100644 --- a/ports/gprs_a9/modaudio.c +++ b/ports/gprs_a9/modaudio.c @@ -32,106 +32,79 @@ #include "api_fs.h" #include "py/runtime.h" -uint8_t audioTimeout = 5; uint8_t audioVolume = 5; -bool audioPlayEnd = true; +int audioRecordFd = -1; -void audioRecordCallback(AUDIO_Error_t result) -{ - if (result != AUDIO_ERROR_NO) { - Trace(1,"audio record error: %d", result); - } -} - - -STATIC mp_obj_t modaudio_record(size_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t modaudio_record_start(size_t n_args, const mp_obj_t *args) { // ======================================== // Audio Record. // Args: // filename (str): output file name with full path - // timeout (int): timeout in seconds (default 5) // channel (int): audio channel (default 2, AUDIO_MODE_LOUDSPEAKER) // type (int): audio type (default 3, AUDIO_TYPE_AMR) // mode (int): audio mode (default 7, AUDIO_RECORD_MODE_AMR122) // ======================================== - int timeout = audioTimeout; + const char* filename; int channel = AUDIO_MODE_LOUDSPEAKER; int type = AUDIO_TYPE_AMR; int mode = AUDIO_RECORD_MODE_AMR122; - const char* filename; if (n_args > 0) { - filename = mp_obj_str_get_str(args[0]); + filename = mp_obj_str_get_str(args[0]); } else { mp_raise_ValueError("filename is mandatory"); return mp_const_none; } if (n_args >= 2) { - timeout = mp_obj_get_int(args[1]); - } - if (n_args >= 3) { - channel = mp_obj_get_int(args[2]); + channel = mp_obj_get_int(args[1]); } if (n_args >= 3) { - type = mp_obj_get_int(args[3]); + type = mp_obj_get_int(args[2]); } if (n_args >= 4) { - mode = mp_obj_get_int(args[4]); + mode = mp_obj_get_int(args[3]); } - Trace(1,"record start, filename: %s, timeout: %d, channel: %d, type: %d, mode: %d", filename, timeout, channel, type, mode); - int audioRecordFd = API_FS_Open(filename,FS_O_WRONLY|FS_O_CREAT|FS_O_TRUNC,0); - if(audioRecordFd < 0) { + Trace(1,"audio record start, filename: %s, channel: %d, type: %d, mode: %d", filename, channel, type, mode); + audioRecordFd = API_FS_Open(filename,FS_O_WRONLY|FS_O_CREAT|FS_O_TRUNC,0); + if (audioRecordFd < 0) { Trace(1,"audio open file error"); - mp_raise_ValueError("file error"); + mp_raise_ValueError("file open error"); return mp_const_none; } AUDIO_SetMode(channel); - AUDIO_Error_t result = AUDIO_RecordStart(type, mode, audioRecordFd, audioRecordCallback, NULL); + AUDIO_Error_t result = AUDIO_RecordStart(type, mode, audioRecordFd, NULL, NULL); if (result != AUDIO_ERROR_NO) { - Trace(1,"record start fail: %d",result); + Trace(1,"audio record start fail: %d",result); API_FS_Close(audioRecordFd); audioRecordFd = -1; - mp_raise_ValueError("cannot start recording"); + mp_raise_ValueError("cannot record audio file"); return mp_const_none; } - Trace(1,"record start"); - while(--timeout) - { - Trace(1,"recording"); - OS_Sleep(1000); - } - Trace(1,"record stop"); - AUDIO_RecordStop(); - API_FS_Close(audioRecordFd); - audioRecordFd = -1; - Trace(1,"record end"); + Trace(1,"recording"); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_record_obj, 1, 2, modaudio_record); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_record_start_obj, 1, 2, modaudio_record_start); STATIC mp_obj_t modaudio_record_stop(void) { //Stop recording audio AUDIO_RecordStop(); + API_FS_Close(audioRecordFd); + audioRecordFd = -1; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_record_stop_obj, modaudio_record_stop); -void audioPlayCallback(AUDIO_Error_t result) -{ - Trace(1,"play callback result: %d",result); - if (AUDIO_ERROR_END_OF_FILE == result) { - Trace(1,"play music file end"); - } - audioPlayEnd = true; +void audioPlayCallback(AUDIO_Error_t result) { + Trace(1,"audio play callback result: %d",result); AUDIO_Stop(); } -STATIC mp_obj_t modaudio_play(size_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t modaudio_play_start(size_t n_args, const mp_obj_t *args) { // ======================================== // Audio Play. // Args: @@ -140,10 +113,12 @@ STATIC mp_obj_t modaudio_play(size_t n_args, const mp_obj_t *args) { // channel (int): audio channel (default 2, AUDIO_MODE_LOUDSPEAKER) // type (int): audio type (default 3, AUDIO_TYPE_AMR) // ======================================== + + const char* filename; int volume = audioVolume; int channel = AUDIO_MODE_LOUDSPEAKER; int type = AUDIO_TYPE_AMR; - const char* filename; + if (n_args > 0) { filename = mp_obj_str_get_str(args[0]); } else { @@ -156,55 +131,43 @@ STATIC mp_obj_t modaudio_play(size_t n_args, const mp_obj_t *args) { if (n_args >= 3) { channel = mp_obj_get_int(args[2]); } - if (n_args >= 3) { + if (n_args >= 4) { type = mp_obj_get_int(args[3]); } Trace(1,"play start, filename: %s, volume: %d, channel: %d, type: %d", filename, volume, channel, type); - - AUDIO_Error_t ret = AUDIO_Play(filename, type, audioPlayCallback); - if( ret != AUDIO_ERROR_NO) - { - Trace(1,"play music fail: %d",ret); - mp_raise_ValueError("cannot play file"); + AUDIO_Error_t result = AUDIO_Play(filename, type, audioPlayCallback); + if (result != AUDIO_ERROR_NO) { + Trace(1,"play fail: %d", result); + mp_raise_ValueError("cannot play audio file"); return mp_const_none; - } - else - { - audioPlayEnd = false; - Trace(1,"play music success"); + } else { + Trace(1,"playing"); } OS_Sleep(200); AUDIO_SetMode(channel); AUDIO_SpeakerOpen(); AUDIO_SpeakerSetVolume(volume); - - uint8_t i = AUDIO_EQ_NORMAL; - while(!audioPlayEnd) - { - OS_Sleep(1000); - } - - Trace(1,"play end"); + Trace(1,"playing"); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_play_obj, 1, 2, modaudio_play); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_play_start_obj, 1, 2, modaudio_play_start); -/* -STATIC mp_obj_t modaudio_pause(void) { + +STATIC mp_obj_t modaudio_play_pause(void) { //Pause audio play AUDIO_Pause(); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_pause_obj, modaudio_pause); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_play_pause_obj, modaudio_play_pause); -STATIC mp_obj_t modaudio_resume(void) { - //Resume playing from pause - AUDIO_Resume(); +STATIC mp_obj_t modaudio_play_resume(void) { + //Resume playing after pause + //AUDIO_Resume(fileFd); //?AUDIO_Play doesn't have nor return a fileFd return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_resume_obj, modaudio_resume); -*/ +STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_play_resume_obj, modaudio_play_resume); + STATIC mp_obj_t modaudio_play_stop(void) { //Stop playing audio @@ -217,10 +180,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(modaudio_play_stop_obj, modaudio_play_stop); STATIC const mp_map_elem_t mp_module_audio_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_audio) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_record), (mp_obj_t)&modaudio_record_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_record_start), (mp_obj_t)&modaudio_record_start_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_record_stop), (mp_obj_t)&modaudio_record_stop_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_play), (mp_obj_t)&modaudio_play_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_play_start), (mp_obj_t)&modaudio_play_start_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_play_stop), (mp_obj_t)&modaudio_play_stop_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_play_pause), (mp_obj_t)&modaudio_play_pause_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_play_resume), (mp_obj_t)&modaudio_play_resume_obj }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_audio_globals, mp_module_audio_globals_table); From 9340ac127ce77a4f2e2cdc8536205489c69b6516 Mon Sep 17 00:00:00 2001 From: Ubaldo Porcheddu Date: Mon, 7 Sep 2020 13:36:09 +0100 Subject: [PATCH 3/4] Call AUDIO_Stop() in case AUDIO_Play() return error --- ports/gprs_a9/modaudio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/gprs_a9/modaudio.c b/ports/gprs_a9/modaudio.c index 13838a0b05015..ae48dacb5ade6 100644 --- a/ports/gprs_a9/modaudio.c +++ b/ports/gprs_a9/modaudio.c @@ -85,7 +85,7 @@ STATIC mp_obj_t modaudio_record_start(size_t n_args, const mp_obj_t *args) { Trace(1,"recording"); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_record_start_obj, 1, 2, modaudio_record_start); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_record_start_obj, 1, 4, modaudio_record_start); STATIC mp_obj_t modaudio_record_stop(void) { @@ -137,6 +137,7 @@ STATIC mp_obj_t modaudio_play_start(size_t n_args, const mp_obj_t *args) { Trace(1,"play start, filename: %s, volume: %d, channel: %d, type: %d", filename, volume, channel, type); AUDIO_Error_t result = AUDIO_Play(filename, type, audioPlayCallback); if (result != AUDIO_ERROR_NO) { + AUDIO_Stop(); Trace(1,"play fail: %d", result); mp_raise_ValueError("cannot play audio file"); return mp_const_none; @@ -150,7 +151,7 @@ STATIC mp_obj_t modaudio_play_start(size_t n_args, const mp_obj_t *args) { Trace(1,"playing"); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_play_start_obj, 1, 2, modaudio_play_start); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modaudio_play_start_obj, 1, 4, modaudio_play_start); STATIC mp_obj_t modaudio_play_pause(void) { From 2912b8b86b64b3e014ff07ae91f90abbccf76f1d Mon Sep 17 00:00:00 2001 From: Ubaldo Porcheddu Date: Wed, 9 Sep 2020 15:43:11 +0100 Subject: [PATCH 4/4] add power key handler --- ports/gprs_a9/main.c | 8 ++++++++ ports/gprs_a9/modmachine.c | 27 +++++++++++++++++++++++++++ ports/gprs_a9/modmachine.h | 2 ++ 3 files changed, 37 insertions(+) diff --git a/ports/gprs_a9/main.c b/ports/gprs_a9/main.c index 012029e09e2e3..bec8b8b79eb55 100644 --- a/ports/gprs_a9/main.c +++ b/ports/gprs_a9/main.c @@ -242,6 +242,14 @@ void EventDispatch(API_Event_t* pEvent) modmachine_notify_power_on(pEvent); break; + case API_EVENT_ID_KEY_DOWN: + modmachine_notify_power_key_down(pEvent); + break; + + case API_EVENT_ID_KEY_UP: + modmachine_notify_power_key_up(pEvent); + break; + // Network // ======= diff --git a/ports/gprs_a9/modmachine.c b/ports/gprs_a9/modmachine.c index 40082c022a66f..2fa1071a255b0 100644 --- a/ports/gprs_a9/modmachine.c +++ b/ports/gprs_a9/modmachine.c @@ -41,12 +41,14 @@ #include "api_hal_adc.h" STATIC mp_obj_t modmachine_watchdog_off(void); +STATIC mp_obj_t power_key = mp_const_none; void modmachine_init0(void) { PM_SetSysMinFreq(PM_SYS_FREQ_312M); modmachine_watchdog_off(); modmachine_pin_init0(); modmachine_uart_init0(); + power_key = mp_const_none; } // ------ @@ -203,6 +205,30 @@ STATIC mp_obj_t modmachine_watchdog_reset(void) { STATIC MP_DEFINE_CONST_FUN_OBJ_0(modmachine_watchdog_reset_obj, modmachine_watchdog_reset); +void modmachine_notify_power_key_down(API_Event_t* event) { + if (power_key && power_key != mp_const_none) { + mp_sched_schedule(power_key, mp_obj_new_int(1)); + } +} + +void modmachine_notify_power_key_up(API_Event_t* event) { + if (power_key && power_key != mp_const_none) { + mp_sched_schedule(power_key, mp_obj_new_int(0)); + } +} + +STATIC mp_obj_t modmachine_on_power_key(mp_obj_t callable) { + // ======================================== + // Sets a callback on power key press. + // Args: + // callback (Callable): a callback to + // execute on power key press. + // ======================================== + power_key = callable; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(modmachine_on_power_key_obj, modmachine_on_power_key); + STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, @@ -213,6 +239,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_set_idle), (mp_obj_t)&modmachine_set_idle_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_set_min_freq), (mp_obj_t)&modmachine_set_min_freq_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_power_on_cause), (mp_obj_t)&modmachine_power_on_cause_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_on_power_key), (mp_obj_t)&modmachine_on_power_key_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_off), (mp_obj_t)&modmachine_off_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_get_input_voltage), (mp_obj_t)&modmachine_get_input_voltage_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_watchdog_on), (mp_obj_t)&modmachine_watchdog_on_obj }, diff --git a/ports/gprs_a9/modmachine.h b/ports/gprs_a9/modmachine.h index abcfc12559758..2cd34d5a4cea0 100644 --- a/ports/gprs_a9/modmachine.h +++ b/ports/gprs_a9/modmachine.h @@ -51,3 +51,5 @@ void modmachine_uart_init0(void); void modmachine_init0(void); void modmachine_notify_power_on(API_Event_t* event); +void modmachine_notify_power_key_down(API_Event_t* event); +void modmachine_notify_power_key_up(API_Event_t* event); \ No newline at end of file