Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post orgasm modes , Denial count and milk-o-matic post orgasm modes #91

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ and is automatically generated. Here is a quick summary of config variables:
|`post_orgasm_menu_lock`|Boolean|false|Deny access to menu starting after orgasm detected.|
|`max_clench_duration_ms`|Int|3000|Duration the clench detector can raise arousal if clench detector turned on in edging session.|
|`clench_time_threshold_ms`|Int|900|Threshold variable that is milliseconds counts to detect the start of clench.|
|`denials_count_to_orgasm`|Int|10|How many denials before permiting an orgasm, if this mode is chosen.|
|`milk_o_matic_rest_duration_seconds`|Int|60|How long to rest before restarting an other round of Denial_count edging.|
|`random_orgasm_triggers`|Boolean|false|Randomize Edge timer and Denial count to minimum of 1/2 of their values.|
|`post_orgasm_mode`|PostOrgasmMode|Timer|Timer, Denial_count and Milk-O-Matic. Random is a choice between Timer and Milk-o-matic. See documentation for more details.|
|`max_orgasms`|Int|4|Milk-o-matic maximum orgasms before turning off.|


\* AzureFang refers to a common wireless technology that is blue and involves chewing face-rocks. However, the
Expand All @@ -79,6 +84,14 @@ and is automatically generated. Here is a quick summary of config variables:
|3|Enhancement|Vibrator speed ramps up as arousal increases, holding a peak for ramp_time.|
|0|Global Sync|When set on secondary vibrators, they will follow the primary vibrator speed.|

### Post Orgasm Modes:
|ID|Name|Description|
|---|---|---|
|0|Denial_count|How many Denials before permiting an orgasm. Value set with - "Denials to permit orgasm" in the Orgasm Menu|
|1|Timer|How long to edge before permiting an orgasm. Value set with - "Edge Duration Minutes" in the Orgasm Menu|
|2|Milk_o_matic|Cycles in Denial_count mode after each orgasm. Repeats until max_orgasms reached|
|3|Random_mode|Random choice Timer or milk-o-matic before orgasm. For best result choose "Edge Duration Minutes" = 60 min and "Denials to permit orgasm" = 20. the idea is not knowing if you will have an 1 hours tease or multiple orgasm within that same 1 hour. Max_orgasms stops the session after it's reached.|

### post_orgasm_duration_seconds:
|Seconds|Description|
|---|---|
Expand Down
5 changes: 5 additions & 0 deletions include/assets/config_help.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ extern "C" {
#define POST_ORGASM_MENU_LOCK_HELP _HELPSTR("Deny access to menu starting after orgasm detected.")
#define MAX_CLENCH_DURATION_MS_HELP _HELPSTR("Duration the clench detector can raise arousal if clench detector turned on in edging session.")
#define CLENCH_TIME_THRESHOLD_MS_HELP _HELPSTR("Threshold variable that is milliseconds counts to detect the start of clench.")
#define DENIALS_COUNT_TO_ORGASM_HELP _HELPSTR("How many denials before permiting an orgasm, if this mode is chosen.")
#define MILK_O_MATIC_REST_DURATION_SECONDS_HELP _HELPSTR("How long to rest before restarting an other round of Denial_count edging.")
#define RANDOM_ORGASM_TRIGGERS_HELP _HELPSTR("Randomize Edge timer and Denial count to minimum of 1/2 of their values.")
#define POST_ORGASM_MODE_HELP _HELPSTR("Timer, Denial_count and Milk-O-Matic. Random is a choice between Timer and Milk-o-matic. See documentation for more details.")
#define MAX_ORGASMS_HELP _HELPSTR("Milk-o-matic maximum orgasms before turning off.")

#ifdef __cplusplus
}
Expand Down
22 changes: 22 additions & 0 deletions include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ enum vibration_mode { RampStop = 1, Depletion = 2, Enhancement = 3, Pattern = 4,

typedef enum vibration_mode vibration_mode_t;

// Post orgasm Modes
// See vibration_mode_controller.h for more.

enum post_orgasm_mode { Denial_count = 0, Timer = 1, Milk_o_matic = 2, Random_mode = 3 };

typedef enum post_orgasm_mode post_orgasm_mode_t;

/**
* Main Configuration Struct!
*
Expand Down Expand Up @@ -153,6 +160,21 @@ struct config {
bool edge_menu_lock;
// Deny access to menu starting after orgasm detected
bool post_orgasm_menu_lock;
// Edging needed to permit orgasm (Max value if ramdom selected).
int denials_count_to_orgasm;
// milk_o_matic rest period in seconds before restart edge+orgasm
int milk_o_matic_rest_duration_seconds;
// random timer and denial_count to orgasm from set values. minimum is 1/2
bool random_orgasm_triggers;
// how many orgasms before stopping in milk-o-matic
int max_orgasms;


// Timer : default original mode
// Edge_count will permit orgasm after # denial reached
// Milk-O-Matic will restart edge+orgasm indefenetly and randomly choose Timer or edge_count at each loop
// Random choose Timer or Edge_count at start of session
int post_orgasm_mode;

//= Internal System Configuration (Update only if you know what you're doing)

Expand Down
7 changes: 6 additions & 1 deletion src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ CONFIG_DEFS {
CFG_NUMBER(update_frequency_hz, 50);
CFG_NUMBER(sensor_sensitivity, 128);
CFG_BOOL(use_average_values, false);

CFG_NUMBER(denials_count_to_orgasm, 10);
CFG_NUMBER(milk_o_matic_rest_duration_seconds, 60);
CFG_ENUM(post_orgasm_mode, post_orgasm_mode_t, Timer);
CFG_BOOL(random_orgasm_triggers, false);
CFG_NUMBER(max_orgasms, 4);

// Vibration Settings
CFG_ENUM(vibration_mode, vibration_mode_t, RampStop);

Expand Down
77 changes: 76 additions & 1 deletion src/menus/orgasm_settings_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,90 @@ static const ui_input_numeric_t CLENCH_PRESSURE_SENSITIVITY_INPUT = {
.input.help = CLENCH_PRESSURE_SENSITIVITY_HELP
};

void on_to_orgasm_select(const ui_input_select_option_t* option, int final, UI_INPUT_ARG_TYPE arg) {
post_orgasm_mode_t mode = (post_orgasm_mode_t)option->ival;
if (final) Config.post_orgasm_mode = mode;
on_config_save(mode, final, arg);
}

static const ui_input_select_option_t post_orgasm_modes[] = {
{
.label = "Timer",
.ival = Timer,
.value = NULL,
},
{
.label = "Denial count",
.ival = Denial_count,
.value = NULL,
},
{
.label = "Random choice",
.ival = Random_mode,
.value = NULL,
},
{
.label = "Milk-O-Matic",
.ival = Milk_o_matic,
.value = NULL,
},
};

static const ui_input_select_t POST_ORGASM_MODE_INPUT = {
SelectInputValues(
"Orgasm Modes",
&Config.post_orgasm_mode,
&post_orgasm_modes,
sizeof(post_orgasm_modes) / sizeof(post_orgasm_modes[0]),
on_to_orgasm_select
),
.input.help = POST_ORGASM_MODE_HELP,
};

static const ui_input_numeric_t DENIALS_COUNT_TO_ORGASM_INPUT = {
UnsignedInputValues("Denials to permit orgasm", &Config.denials_count_to_orgasm, "", on_config_save),
.max = 255,
.step = 1,
.input.help = DENIALS_COUNT_TO_ORGASM_HELP
};

static const ui_input_numeric_t MILK_O_MATIC_REST_DURATION_INPUT = {
UnsignedInputValues(
"Milk-o-matic resting duration", &Config.milk_o_matic_rest_duration_seconds, UNIT_SECONDS, on_config_save
),
.max = 1800,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be no max seconds. That should be based on a JSON setting.

.step = 1,
.input.help = MILK_O_MATIC_REST_DURATION_SECONDS_HELP
};

static const ui_input_toggle_t RANDOM_ORGASM_TRIGGERS_INPUT = {
ToggleInputValues("Random Timer and Edge_count", &Config.random_orgasm_triggers, on_config_save),
.input.help = RANDOM_ORGASM_TRIGGERS_HELP
};

static const ui_input_numeric_t MAX_ORGASMS_INPUT = {
UnsignedInputValues(
"Milk-o-matic max orgasms", &Config.max_orgasms, "", on_config_save
),
.max = 255,
.step = 1,
.input.help = MAX_ORGASMS_HELP
};

static void on_open(const ui_menu_t* m, UI_MENU_ARG_TYPE arg) {
ui_menu_add_input(m, (ui_input_t*)&USE_POST_ORGASM_INPUT);
ui_menu_add_input(m, (ui_input_t*)&EDGING_DURATION_INPUT);
ui_menu_add_input(m, (ui_input_t*)&DENIALS_COUNT_TO_ORGASM_INPUT);
ui_menu_add_input(m, (ui_input_t*)&POST_ORGASM_MODE_INPUT);
ui_menu_add_input(m, (ui_input_t*)&CLENCH_TIME_TO_ORGASM_MS_INPUT);
ui_menu_add_input(m, (ui_input_t*)&USE_POST_ORGASM_INPUT);
ui_menu_add_input(m, (ui_input_t*)&POST_ORGASM_DURATION_SECONDS_INPUT);
ui_menu_add_input(m, (ui_input_t*)&EDGE_MENU_LOCK_INPUT);
ui_menu_add_input(m, (ui_input_t*)&POST_ORGASM_MENU_LOCK_INPUT);
ui_menu_add_input(m, (ui_input_t*)&CLENCH_DETECTOR_IN_EDGING_INPUT);
ui_menu_add_input(m, (ui_input_t*)&CLENCH_PRESSURE_SENSITIVITY_INPUT);
ui_menu_add_input(m, (ui_input_t*)&MILK_O_MATIC_REST_DURATION_INPUT);
ui_menu_add_input(m, (ui_input_t*)&MAX_ORGASMS_INPUT);
ui_menu_add_input(m, (ui_input_t*)&RANDOM_ORGASM_TRIGGERS_INPUT);
}

DYNAMIC_MENU(ORGASM_SETTINGS_MENU, "Orgasm Settings", on_open);
101 changes: 90 additions & 11 deletions src/orgasm_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,24 @@ static struct {
oc_bool_t menu_is_locked;
oc_bool_t detected_orgasm;
int post_orgasm_duration_seconds;
uint8_t edge_count_to_orgasm;
post_orgasm_mode_t post_orgasm_mode;
uint8_t auto_edging_duration_minutes;
bool random_orgasm_triggers;
uint8_t orgasm_count;
} post_orgasm_state;

volatile static struct {
uint8_t denial_count;
event_handler_node_t* _h_denial;
} denial_state = { 0 };

static void _evt_orgasm_denial(
const char* evt, EVENT_HANDLER_ARG_TYPE eap, int eai, EVENT_HANDLER_ARG_TYPE hap
) {
denial_state.denial_count += 1;
}

volatile static struct {
uint8_t orgasm_count;
event_handler_node_t* _h_orgasm;
Expand Down Expand Up @@ -113,6 +129,10 @@ void orgasm_control_init(void) {
post_orgasm_state.clench_pressure_threshold = 4096;

running_average_init(&arousal_state.average, Config.pressure_smoothing);
if (denial_state._h_denial == NULL) {
denial_state._h_denial =
event_manager_register_handler(EVT_ORGASM_DENIAL, &_evt_orgasm_denial, NULL);
}
orgasm_state.orgasm_count = 0;
if (orgasm_state._h_orgasm == NULL) {
orgasm_state._h_orgasm =
Expand Down Expand Up @@ -256,13 +276,38 @@ static void orgasm_control_updateEdgingTime() { // Edging+Orgasm timer
if (output_state.output_mode == OC_MANUAL_CONTROL) {
post_orgasm_state.menu_is_locked = ocFALSE;
post_orgasm_state.post_orgasm_duration_seconds = Config.post_orgasm_duration_seconds;
post_orgasm_state.edge_count_to_orgasm = Config.denials_count_to_orgasm;
post_orgasm_state.detected_orgasm = ocFALSE;
post_orgasm_state.post_orgasm_mode = Config.post_orgasm_mode;
post_orgasm_state.random_orgasm_triggers = Config.random_orgasm_triggers;
return;
}

// keep edging start time to current time as long as system is not in Edge-Orgasm mode 2
if (output_state.output_mode != OC_ORGASM_MODE) {
post_orgasm_state.auto_edging_start_millis = (esp_timer_get_time() / 1000UL);
post_orgasm_state.post_orgasm_start_millis = 0;
post_orgasm_state.orgasm_count = 0;

if ( post_orgasm_state.post_orgasm_mode == Random_mode ) {
post_orgasm_state.post_orgasm_mode = (random() % 2 + 1);
}
post_orgasm_state.edge_count_to_orgasm = denial_state.denial_count + Config.denials_count_to_orgasm;
post_orgasm_state.auto_edging_duration_minutes = Config.auto_edging_duration_minutes;
} else {
// Orgasm mode started
// Randomize timer and denial_count to orgasm.
if (post_orgasm_state.random_orgasm_triggers) {
// Only run once afer start of session
post_orgasm_state.random_orgasm_triggers = false ;
int min_count = round( Config.denials_count_to_orgasm / 2 );
int min_edge_time = round( Config.auto_edging_duration_minutes / 2 );

post_orgasm_state.edge_count_to_orgasm = denial_state.denial_count +
min_count + rand() % (Config.denials_count_to_orgasm - min_count);
post_orgasm_state.auto_edging_duration_minutes =
min_edge_time + rand() % (Config.auto_edging_duration_minutes - min_edge_time );
}
}

// Lock Menu if turned on. and in Edging_orgasm mode
Expand Down Expand Up @@ -314,7 +359,35 @@ static void orgasm_control_updateEdgingTime() { // Edging+Orgasm timer
output_state.motor_speed = Config.motor_max_speed;
} else { // Post_orgasm timer reached
if (output_state.motor_speed > 0) { // Ramp down motor speed to 0
output_state.motor_speed = output_state.motor_speed - 1;
update_check(output_state.motor_speed, output_state.motor_speed - 1 )
_set_speed(output_state.motor_speed);
} else if ( (post_orgasm_state.post_orgasm_mode == Milk_o_matic) &&
(post_orgasm_state.orgasm_count < Config.max_orgasms)) {
// The motor has been turnned off but this is Milk-O-Matic orgasm mode. Prepare for next round.
output_state.motor_speed = 0;
eom_hal_set_encoder_rgb(255, 0, 127);

// now give a break before restarting edging
if (esp_timer_get_time() / 1000UL > post_orgasm_state.post_orgasm_start_millis +
post_orgasm_state.post_orgasm_duration_millis +
(Config.milk_o_matic_rest_duration_seconds * 1000))
{
// Rest period is finished. Reset variables for next round
post_orgasm_state.auto_edging_start_millis = (esp_timer_get_time() / 1000UL);
post_orgasm_state.post_orgasm_start_millis = 0;
post_orgasm_state.detected_orgasm = ocFALSE;
post_orgasm_state.menu_is_locked = ocFALSE;

// Set the new denial count limit to reach before next orgasm
// Randomize denial_count if turned on
if (Config.random_orgasm_triggers) {
// re-enable calculation of random for next round
post_orgasm_state.random_orgasm_triggers = true;
} else {
post_orgasm_state.edge_count_to_orgasm = denial_state.denial_count + Config.denials_count_to_orgasm;
}
orgasm_control_resume_control();
}
} else {
post_orgasm_state.menu_is_locked = ocFALSE;
post_orgasm_state.detected_orgasm = ocFALSE;
Expand All @@ -324,11 +397,6 @@ static void orgasm_control_updateEdgingTime() { // Edging+Orgasm timer
}
}
}
// Control output while motor control is paused
if (output_state.control_motor == OC_MANUAL_CONTROL) {
uint8_t speed = orgasm_control_get_motor_speed();
_set_speed(speed);
}
}

/**
Expand Down Expand Up @@ -619,12 +687,23 @@ void orgasm_control_permit_orgasm(int seconds) {
}

oc_bool_t orgasm_control_is_permit_orgasm_reached() {
// Detect if edging time has passed
if ((esp_timer_get_time() / 1000UL) > (post_orgasm_state.auto_edging_start_millis +
(Config.auto_edging_duration_minutes * 60 * 1000))) {
return ocTRUE;
if (post_orgasm_state.post_orgasm_mode == Denial_count ||
post_orgasm_state.post_orgasm_mode == Milk_o_matic) {
if (denial_state.denial_count >= post_orgasm_state.edge_count_to_orgasm) {
// if (denial_state.denial_count >= 1) {

return ocTRUE;
} else {
return ocFALSE;
}
} else {
return ocFALSE;
// Detect if edging time has passed
if ((esp_timer_get_time() / 1000UL) > (post_orgasm_state.auto_edging_start_millis +
(Config.auto_edging_duration_minutes * 60 * 1000))) {
return ocTRUE;
} else {
return ocFALSE;
}
}
}

Expand Down