Skip to content

Commit

Permalink
Start and stop button, and test delay working
Browse files Browse the repository at this point in the history
  • Loading branch information
idealemu committed Apr 16, 2024
1 parent a7f8df2 commit 2214d47
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 31 deletions.
1 change: 1 addition & 0 deletions buildDocker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
docker build -t infinitime-build ./docker
4 changes: 3 additions & 1 deletion docker/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export SOURCES_DIR="${SOURCES_DIR:=/sources}"
export BUILD_DIR="${BUILD_DIR:=$SOURCES_DIR/build}"
export OUTPUT_DIR="${OUTPUT_DIR:=$SOURCES_DIR/build/output}"


# Specify a folder with read/write access to NPM
export NPM_DIR="$BUILD_DIR/npm"
export npm_config_cache="${NPM_DIR}"
Expand Down Expand Up @@ -68,7 +69,8 @@ CmakeGenerate() {
-DARM_NONE_EABI_TOOLCHAIN_PATH="$TOOLS_DIR/$GCC_ARM_PATH" \
-DNRF5_SDK_PATH="$TOOLS_DIR/$NRF_SDK_VER" \
-DBUILD_DFU=1 \
-DBUILD_RESOURCES=1
-DBUILD_RESOURCES=1 \
-DENABLE_USERAPPS="Apps::REM"
}

CmakeBuild() {
Expand Down
27 changes: 20 additions & 7 deletions src/components/motor/MotorController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void MotorController::StopRinging() {

void MotorController::pulse(TimerHandle_t xTimer) {
MotorController* motorController = static_cast<MotorController*>(pvTimerGetTimerID(xTimer));
motorController->RunForDuration(pdMS_TO_TICKS(5));
motorController->RunForDuration(pdMS_TO_TICKS(50));

motorController->pulseCount++;
if (motorController->pulseCount >= 3) {
Expand All @@ -61,14 +61,26 @@ void MotorController::StopMotor(TimerHandle_t /*xTimer*/) {
nrf_gpio_pin_set(PinMap::Motor);
}

void MotorController::StopStimulationTask() {
if (stimulationTaskState == StimulationTaskState::running) {
xTimerStop(REM_HeuristicTimer, 0);
xTimerStop(repeatSequenceTimer, 0);
xTimerStop(sequenceEvery30Seconds, 0);
stimulationTaskState = StimulationTaskState::stopped;
}
}

void MotorController::StartStimulationTask() {
StopStimulationTask();

// Calculate delay in ticks manually, without using ms nor pdMS_To_Ticks to avoid integer overflow
// auto REM_HeuristicDelay = 75 * configTICK_RATE_HZ * 60;
TickType_t REM_HeuristicDelay = 1 * configTICK_RATE_HZ * 60;

REM_HeuristicTimer = xTimerCreate("r", REM_HeuristicDelay, pdTRUE, this, periodicVibrationSequence);
// TODO SET pdTRUE for real !
REM_HeuristicTimer = xTimerCreate("r", REM_HeuristicDelay, pdFALSE, this, periodicVibrationSequence);
xTimerStart(REM_HeuristicTimer, 0);
// stimulationTaskState = StimulationTaskState::waiting;
stimulationTaskState = StimulationTaskState::waiting;
}

TickType_t MotorController::GetRemainingREMHeuristicTime() {
Expand All @@ -90,9 +102,10 @@ void MotorController::periodicVibrationSequence(TimerHandle_t xTimer) {
// Sequence repeated for 3*4 = 12 minutes of REM
// Sequence: 3 pulses in 3 seconds, 4 times seperated by 30 seconds
MotorController* motorController = static_cast<MotorController*>(pvTimerGetTimerID(xTimer));
//motorController->stimulationTaskState = StimulationTaskState::running;
motorController->stimulationTaskState = StimulationTaskState::running;

TickType_t repeatSequenceDelay = pdMS_TO_TICKS(3 * 60 * 1000);
//TickType_t repeatSequenceDelay = pdMS_TO_TICKS(3 * 60 * 1000);
TickType_t repeatSequenceDelay = pdMS_TO_TICKS(2000);
motorController->repeatSequenceTimer = xTimerCreate("vP", repeatSequenceDelay, pdTRUE, motorController, repeatSequence);
xTimerStart(motorController->repeatSequenceTimer, 0);
}
Expand All @@ -107,8 +120,8 @@ void MotorController::repeatSequence(TimerHandle_t xTimer) {
xTimerStop(xTimer, 0); // Stop vibrationPeriod timer after 4 cycles of 3 minutes
count = 0;

TimerHandle_t sequenceEvery30Seconds = xTimerCreate("rS", pdMS_TO_TICKS(30 * 1000), pdTRUE, motorController, majorPulsePeriod);
xTimerStart(sequenceEvery30Seconds, 0);
motorController->sequenceEvery30Seconds = xTimerCreate("rS", pdMS_TO_TICKS(30 * 1000), pdTRUE, motorController, majorPulsePeriod);
xTimerStart(motorController->sequenceEvery30Seconds, 0);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/components/motor/MotorController.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Pinetime {
TickType_t GetRemainingREMHeuristicTime();

static void periodicVibrationSequence(TimerHandle_t xTimer);
void StopStimulationTask();
StimulationTaskState stimulationTaskState = StimulationTaskState::stopped;

private:
Expand All @@ -42,6 +43,7 @@ namespace Pinetime {
TimerHandle_t pulseTimerEnd;
TimerHandle_t REM_HeuristicTimer;
TimerHandle_t repeatSequenceTimer;
TimerHandle_t sequenceEvery30Seconds;
uint8_t pulseCount = 0;

};
Expand Down
67 changes: 46 additions & 21 deletions src/displayapp/screens/REM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,50 @@

using namespace Pinetime::Applications::Screens;

void REM::btnEventHandler(lv_obj_t* obj, lv_event_t event) {
auto* screen = static_cast<REM*>(obj->user_data);
screen->OnButtonEvent(event);
void REM::btnStartEventHandler(lv_obj_t* obj, lv_event_t event) {
REM* screen = static_cast<REM*>(obj->user_data);
if (event == LV_EVENT_CLICKED) {
screen->motorController.hapticFeedback();
screen->motorController.hapticFeedback(); // Two pulse haptic feedback

screen->motorController.StartStimulationTask();
}
}

void REM::btnStopEventHandler(lv_obj_t* obj, lv_event_t event) {
REM* screen = static_cast<REM*>(obj->user_data);
if (event == LV_EVENT_CLICKED) {
screen->motorController.hapticFeedback(); // One pulse haptic feedback

screen->motorController.StopStimulationTask();
}
}



REM::REM(Controllers::MotorController& motorController):
motorController{motorController}
{
lv_obj_t* btn = lv_btn_create(lv_scr_act(), nullptr);
lv_obj_set_size(btn, 100, 50);
lv_obj_align(btn, nullptr, LV_ALIGN_CENTER, 0, 0);
btnStart = lv_btn_create(lv_scr_act(), nullptr);
lv_obj_set_size(btnStart, 100, 50);
lv_obj_align(btnStart, nullptr, LV_ALIGN_CENTER, 0, -25);
lv_obj_t* btnStartText= lv_label_create(btnStart, nullptr);
lv_label_set_text(btnStartText, "Start");
lv_obj_set_user_data(btnStart, this); // Set REM instance as user data
lv_obj_set_event_cb(btnStart, btnStartEventHandler);

btnStop = lv_btn_create(lv_scr_act(), nullptr);
lv_obj_set_size(btnStop, 100, 50);
lv_obj_align(btnStop, nullptr, LV_ALIGN_CENTER, 0, 100);
lv_obj_t* btnStopText = lv_label_create(btnStop, nullptr);
lv_label_set_text(btnStopText, "Stop");
lv_obj_set_user_data(btnStop, this); // Set REM instance as user data
lv_obj_set_event_cb(btnStop, btnStopEventHandler);


timeLeftLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(timeLeftLabel, nullptr, LV_ALIGN_CENTER, 0, -100);


lv_obj_t* startBtn = lv_label_create(btn, nullptr);
lv_label_set_text(startBtn, "NRRR");
lv_obj_set_user_data(btn, this); // Set REM instance as user data
lv_obj_set_event_cb(btn, btnEventHandler);
motorController.Init();

taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this);
Expand All @@ -31,26 +55,27 @@ REM::REM(Controllers::MotorController& motorController):
REM::~REM() {
motorController.StopRinging(); // Make sure to stop any ongoing vibrations
lv_obj_clean(lv_scr_act());
lv_task_del(taskRefresh);
}

void REM::Refresh() {
TickType_t remainingTimeInTicks = motorController.GetRemainingREMHeuristicTime();
const uint16_t remainingTimeInSeconds = remainingTimeInTicks / (configTICK_RATE_HZ); // Truncation towards 0

uint8_t minutes = remainingTimeInSeconds / 60;
uint8_t seconds = remainingTimeInSeconds % 60;
uint16_t minutes = remainingTimeInSeconds / 60;
uint16_t seconds = remainingTimeInSeconds % 60;

char timeLeftStr[6];
char timeLeftStr[16];
snprintf(timeLeftStr, sizeof(timeLeftStr), "%02d:%02d", minutes, seconds);

lv_label_set_text(timeLeftLabel, timeLeftStr);
}

void REM::OnButtonEvent(lv_event_t event) {
if (event == LV_EVENT_CLICKED) {
motorController.hapticFeedback();
motorController.hapticFeedback(); // Two pulse haptic feedback

motorController.StartStimulationTask();
// If state is running or waiting grey out start button
if (motorController.stimulationTaskState == Controllers::StimulationTaskState::running
|| motorController.stimulationTaskState == Controllers::StimulationTaskState::waiting) {
lv_obj_set_style_local_bg_color(btnStart, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
} else {
lv_obj_set_style_local_bg_color(btnStart, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
}
}

7 changes: 5 additions & 2 deletions src/displayapp/screens/REM.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@ namespace Pinetime {
REM(Controllers::MotorController& motorController);
~REM() override;

static void btnEventHandler(lv_obj_t*, lv_event_t);
void OnButtonEvent(lv_event_t);
static void btnStartEventHandler(lv_obj_t*, lv_event_t);
static void btnStopEventHandler(lv_obj_t*, lv_event_t);
void Refresh() override;

private:
Pinetime::Controllers::MotorController& motorController;

lv_obj_t* timeLeftLabel;
lv_task_t* taskRefresh;
lv_obj_t* btnStart;
lv_obj_t* btnStop;

};
}

Expand Down

0 comments on commit 2214d47

Please sign in to comment.