#pragma METAINFO("Fenria Special", 0, 7, "")
// CONFIG MODE: 3x fast press TouchClick to enter and leave config mode
// +DPAD-UP: CFGBTN_SCOPE : button specific Turbo&Alternate&Hold AND quickscope selection
// -Double-Tap a button : to cycle through the available button specific features
// -PS : clear all button features settings assignments and flags
// -TouchClick Hold > 500ms: cycling through quickscope settings
// +DEBUG via Device Monitor: Btn B, Feature F, Toggle T
// -last pressed button information is written to BUTTON_21, Format: BB*1000 , FF , TT/100
// -all button_ fields are displaying via the Output Panel
//
// +DPAD-RIGHT: CFGTURBO : Turbo Timing adjustment
// -PS : Turbo Timing reset
//
// +DPAD-DOWN: CFGSENS_PROT : Sensitivity adjustment and Output Protocol selection
// -Share : Output Protocol selection
// -PS : Sensitivity reset
// Regular Usage:
// + when using multi_func_toggle modes:
// - holding the button + press Options will switch "multi mode<->wrong multi mode"
// my proposed/misunderstood multi_function_toggle version has no mode active by default
// you have to select one with tap+press&hold or hold>1000ms. After that use a short tap to toggle it on/off
// hold the button and tap share again to get back to the correct multi_func_toggle
// + when using turbo modes:
// - Buttonhold + Tap Share toggles turbo<->alt turbo
// DEBUG settings
//
bool TXTSelect[]={ // enable/disable output panel text messages per type
TRUE, // TXTMENU // menu navigation
TRUE , // TXTFEAT // two-line feature status summary output
TRUE, // TXTPROT // output protocol
FALSE, // TXTLED // led feedback
TRUE, // TXTFSEL // button feature selection
TRUE, // TXTFCUR // show current features name on a single press
};
#define BtnValInfo TRUE // show feature and toggle state in Device Monitor // TRUE - FALSE
#define BtnValTo BUTTON_21 // <- at this position --^
#define _ColorBrightness
#include "ColorLED.gph"
// ++ BUTTON SPECIFIC FEATURES
//
// feature/mode identifier, for each button
#define FNONE 0 // no special function
#define FTURBOHN 1 // on hold = normal turbo
#define FTURBOTN 2 // tap = toggle normal turbo
#define FMULTIDN 3 // MULTI direct norm: dbltap+hold = turbo & hold>1sec = hold
#define FHOLD 4 // tap = toggle button hold
#define FTURBOHA 5 // on hold = alt turbo
#define FTURBOTA 6 // tap = toggle alt turbo
#define FMULTIDA 7 // MULTI direct alt: dbltap+hold = turbo&& hold>1sec = hold
#define F_MODES 8 // number of modes available to cycle through with dbl tap
#define FMULTITN 9 // MULTI tap alt : dbltap+hold = turbo & hold>1sec = hold , Btn+Share to toggle
#define FMULTITA 10 // MULTI tap norm: dbltap+hold = turbo & hold>1sec = hold , Btn+Share to toggle
// array used to output the feature name on feature selection cycling
char *FNAMES[] = {
"Feature 00: NONE",
"Feature 01: TURBO NORMAL HOLD",
"Feature 02: TURBO NORMAL TAP",
"Feature 03: MULTI NORMAL TURBO & HOLD",
"Feature 04: SIMPLE HOLD TAP",
"Feature 05: TURBO ALT HOLD",
"Feature 06: TURBO ALT TAP",
"Feature 07: MULTI ALT TURBO & HOLD",
"Feature 08: USED INTERNALY",
"Feature 09: MULTI TAP NORMAL TURBO & HOLD",
"Feature 10: MULTI TAP ALT TURBO & HOLD",
};
// LED blink colors for feature toggles
uint8 LEDF[] = {
CP, // pink on FNONE 0 // no special function
CB, // blue on FTURBOHN 1 // on hold = normal turbo
CA, // amber on FTURBOTN 2 // tap = toggle normal turbo
CC, // cyan on FMULTIDN 3 // MULTI direct norm: dbltap+hold = turbo & hold>1sec = hold
CG, // green on FHOLD 4 // tap = toggle button hold
CR, // red on FTURBOHA 5 // on hold = alt turbo
CW, // white on FTURBOTA 6 // tap = toggle alt turbo
CC, // cyan on FMULTIDA 7 // MULTI direct alt: dbltap+hold = turbo&& hold>1sec = hold
CP, // pink on F_MODES 8 // number of modes available to cycle through with dbl tap
CB, // blue on FMULTITN 9 // MULTI tap alt : dbltap+hold = turbo & hold>1sec = hold , Btn+Share to toggle
CA, // amber on FMULTITA 10 // MULTI tap norm: dbltap+hold = turbo & hold>1sec = hold , Btn+Share to toggle
};
// ++ LED Feedback state tracking flags in RGB order , position in array
#define idx_LEDFTA 0 // FTURBOA (alternate) +blink on active
#define idx_LEDFH 1 // FHOLD +static on active
#define idx_LEDFTN 2 // FTURBON (normal) +blink on active
bool bLED[] = { FALSE,FALSE,FALSE, };
// toggle state ids
#define TOFF 0 // toggled off
#define TON 1 // toggled on
#define TMTURBO 2 // multi turbo
#define TMHOLD 4 // multi hold
#define T_MODES 2 // for state checking using % modulo
uint8 BtnsFeature[21];// buttons feature flags (FNONE, FTURBOHN, ...)
uint8 BtnsToggle[21]; // buttons feature toggle state (TOFF,TON,...)
uint8 BtnTurboVal[2]; // buttons value to set for 0:turbo, 1:alt turbo, set by function fTurboTimer
#define TurboIdxN 0 // normal turbo is at this index in BtnTurboVal
#define TurboIdxA 1 // alternate turbo is at this index in BtnTurboVal
int16 TPress =60; // turbo button press time
int16 TRelease=60; // turbo button release time
// ++ GENERAL FEATURES - non button specific
//
// ######## Quick Scope
bool bQScope =0; // quick scope state flag
uint32 QSTimeLimit=100; // timelimit of press time for starting quickscope combo
// scope , fire
uint8 QSBtns[8] ={18 ,18 , // dummy for off state
BUTTON_8 ,BUTTON_5, // L2 & R2 default
BUTTON_6 ,BUTTON_5, // R3 & R2
BUTTON_17,BUTTON_5, // Square & R2
};
uint8 QSCfg =0; // quickscope button pair to use 0,2,4,6 (0==off)
// ######## Stick Sensitivity and Deadzone
fix32 DeadZone=10.0;
int16 RSensitivity=100; // right stick sensitivity
int16 LSensitivity=100; // left stick sensitivity
// ######## Output Protocol
#define PIO_NONE 0
#define PIO_AUTO 0
#define PIO_PS4 4
#define PIO_PS3 1
#define PIO_XB1 5
#define PIO_XB360 2
#define PIO_WII 3
#define PIO_HID 6
#define PIO_SWITCH 7
// ++ Configuration Mode
bool bConfigure=FALSE;
uint8 CfgMode =0;
#define CFGNONE 0 // no config sub entry (1,2,3) selected
#define CFGBTN_SCOPE 1
#define CFGTURBO 2
#define CFGSENS_PROT 3
char *CNAMES[]={
"CfgMode 0: CFGNONE = Main Cfg Menu",
"CfgMode 1: CFGBTN_SCOPE = Btn Features & Quickscope",
"CfgMode 2: CFGTURBO = Turbo Timing",
"CfgMode 3: CFGSENS_PROT = Sensitivity & Output Protocol",
};
// uint8 number to text translation array
char *NR[]={
"0",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12", "13", "14", "15", "16", "17", " ",
};
// led feedback for configuration menu position
#define LCFGENTER 0
#define LCFGLEAVE 0
uint8 LEDCFG[] = {
CP, // pink , entering+leaving config mode
};
// different text styles for Output Panel messages
#define TXTMENU 0 // menu navigation
#define TXTFEAT 1 // feature & toggle state overview
#define TXTPROT 2 // output protocol
#define TXTLED 3 // led feedback
#define TXTFSEL 4 // feature selection
#define TXTFCUR 5 // show current features name on single tap
//
uint8 TXTLast=100; // last used text type in output panel
uint16 TXTFEATWait=400; // time the combo wait before outputting the two-line feature summary text
static char buffer[400]; // print buffer
static char *tail; // print buffer text end pointer
uint8 TXTFCURWait=250; // time to wait before outputting feature info for single tapped button
uint8 BtnLast=0; // for indicating last pressed button in fDebugBtnsText
init {
// for testing
/*
TPress =200; // turbo button press time
TRelease=200; // turbo button release time
BtnsFeature[BUTTON_10]=FHOLD; // hold feature
BtnsFeature[BUTTON_5]=FTURBOHN; // turbo feature normal
BtnsFeature[BUTTON_8]=FTURBOHA; // turbo feature alternate
*/
/*
bConfigure=TRUE;
CfgMode=CFGBTN_SCOPE;
*/
}
main {
// reset led flags
bLED[0]=FALSE; bLED[1]=FALSE; bLED[2]=FALSE;
fConfigToggle();
if (bConfigure) {
fConfigure(); // handling configuration logic
if (elapsed_time()) { // TESTING: lower cpu usage, remove this when output gets through
fDebug(); // debug
}
} else {
fButtons(); // buttons specific feature toggle and usage: hold, turbo hold, turbo toggle
static uint32 etime=0; etime+=elapsed_time();
if (etime > 5) {
etime=0; fButtonLED(); // usage led feedback
}
}
// ## always active stuff
if (elapsed_time()) { // TESTING: lower cpu usage, this one should be fine as it uses no event_ stuff
fTurboTimer(); // turbo and alternate turbo time tracker, sets values of array BtnTurboVal
}
if (BtnValInfo) fBtnValInfo();
fQuickScope(); // quick scope
fSticks(); // stick deadzone and sensitivity
}
// button feature activity LED feedback
void fButtonLED() {
// bLED[0] is hold feature, green = LED_3
// bLED[1] is turbo(normal) feature, blue = LED_1
// bLED[2] is turbo(alternate) feature, red = LED_2
static bool bIdle=FALSE;
static bool bIdleLast=FALSE;
static uint8 LastState[3]={2, 2, 2};
static uint8 LastVal[3]= {2, 2, 2};
// state change test
if (LastState[0]!=bLED[0] || LastState[1]!=bLED[1] || LastState[2]!=bLED[2]) {
LastState[0]=bLED[0]; LastState[1]=bLED[1]; LastState[2]=bLED[2];
//TextMode(TXTLED,TRUE,"State change");
if (!(bLED[0] + bLED[1] + bLED[2])) { // idle
bIdle=TRUE;
ColorLED(LEDF[FNONE]); // pink led
if (bIdleLast != bIdle) {
bIdleLast=bIdle;
TextMode(TXTLED,TRUE,"State: Idle");
}
} else { // busy
bIdle=FALSE;
LastVal[0]=2; LastVal[1]=2; LastVal[2]=2; // reset
if (bIdleLast != bIdle) {
bIdleLast=bIdle;
TextMode(TXTLED,TRUE,"State: Busy");
}
}
} // eo: state change test
if (!bIdle) { // not idle...set color according to active features
// bLED[0] is hold feature , green = LED_3
if (LastVal[idx_LEDFH]!=bLED[idx_LEDFH]) {
LastVal[idx_LEDFH]=bLED[idx_LEDFH];
led_set(LED_4,0.0,0);
led_set(LED_3,(fix32)bLED[idx_LEDFH]*100f,0);
}
// bLED[1] is turbo(normal) feature, blue = LED_1
if (LastVal[idx_LEDFTN]!=bLED[idx_LEDFTN]*BtnTurboVal[TurboIdxN]) {
LastVal[idx_LEDFTN]=bLED[idx_LEDFTN]*BtnTurboVal[TurboIdxN];
led_set(LED_4,0.0,0);
led_set(LED_1,(fix32)LastVal[idx_LEDFTN],0);
}
// bLED[2] is turbo(alternate) feature, red = LED_2
if (LastVal[idx_LEDFTA]!=bLED[idx_LEDFTA]*BtnTurboVal[TurboIdxA]) {
LastVal[idx_LEDFTA]=bLED[idx_LEDFTA]*BtnTurboVal[TurboIdxA];
led_set(LED_4,0.0,0);
led_set(LED_2,(fix32)LastVal[idx_LEDFTA],0);
}
// feature are selected and active but only one turbo is used, set non-turbo time to pink
/*
if (LastState[idx_LEDFH]==0 && LastVal[idx_LEDFTN]==0 && LastVal[idx_LEDFTA]==0) {
ColorLED(LEDF[FNONE]); // pink led
}
*/
}
}
// toggle configuration mode
void fConfigToggle() {
if (event_active(BUTTON_2) || event_release(BUTTON_2)) { // less cpu usage
if (fTaps(BUTTON_2,3,250)) {
bConfigure=!bConfigure;
CfgMode=CFGNONE; // set active submenu to none
// CfgMode toggle notification
if (bConfigure) {
ColorLED(LEDCFG[LCFGENTER],140,140,3,LEDF[FNONE]);
TextMode(TXTMENU,TRUE,"CfgMode 0 : Entered = Main Menu");
} else {
ColorLED(LEDCFG[LCFGLEAVE],140,140,3,LEDF[FNONE]);
TextMode(TXTMENU,TRUE,"CfgMode Exited");
}
} // eo: tripple click
}
}
// doing the configuration
void fConfigure() {
static uint32 lrelease=0;
static bool TClicked=FALSE; // for trigger quickscope button layout cycle with longer button hold
if (CfgMode==CFGNONE) { // no sub entry selected
if (event_active(BUTTON_10)) {
CfgMode=CFGBTN_SCOPE;
TextMode(TXTMENU,TRUE,CNAMES[CfgMode]);
}
if (event_active(BUTTON_13)) {
CfgMode=CFGTURBO;
TextMode(TXTMENU,TRUE,CNAMES[CfgMode]);
}
if (event_active(BUTTON_11)) {
CfgMode=CFGSENS_PROT;
TextMode(TXTMENU,TRUE,CNAMES[CfgMode]);
}
} // eo: CfgMode==CFGNONE
else { // ## in sub entry
if (event_active(BUTTON_3)) {
CfgMode=CFGNONE; // back to main entry
TextMode(TXTMENU,TRUE,CNAMES[CfgMode]);
ColorLED(LEDCFG[0],140,140,3,LEDF[FNONE]);
}
switch(CfgMode) { // sub entry specific
case CFGBTN_SCOPE: // button feature and quickscope selection
if (event_active(BUTTON_1)) fDefaultFeatures(); // PS button
else {
fButtons(TRUE); // TRUE for feature selection
if (event_release(BUTTON_2)) {
if (!TClicked) {
if (system_time()> lrelease) DebugBtnFeature(TXTFCUR,BUTTON_2);
combo_run(cDebugBtnsText);
}
TClicked=FALSE;
lrelease=system_time()+800;
}
if (check_active(BUTTON_2,500) && !TClicked) {
TClicked=TRUE;
BtnLast=BUTTON_2;
QSCfg=(QSCfg+2)%8;
if (QSCfg==0) bQScope=FALSE; else bQScope=TRUE;
DebugBtnFeature(TXTFSEL,BUTTON_2);
if (TXTSelect[TXTFEAT]) combo_run(cDebugBtnsText);
fBtnValInfo(BUTTON_2);
}
}
break;
case CFGTURBO: // button turbo timing adjustment
if (event_active(BUTTON_1)) fTurboDefault(); // PS button
else fTurboAdjust();
break;
case CFGSENS_PROT: // sensitivity and output protocol adjustment
if (event_active(BUTTON_18)) fOutput(); // Share : change output protocol
if (event_active(BUTTON_1)) fSensitivityDefault(); // PS button
else fSensitivityAdjust();
break;
}
}
}
// button loop for config and usage
void fButtons(bool cfg) {
uint8 btn;
for (btn=BUTTON_4;btn<=BUTTON_17;btn++) { // buttons PS4: R1...Square
// reduces cpu usage
if ( !event_active(btn) && !event_release(btn) && !get_actual(btn) && !BtnsToggle[btn]==TON ) continue;
if (cfg) {
fBtnSelect(btn); // select buttons feature
if (event_active(btn) || event_release(btn) || get_actual(btn)) fBtnValInfo(btn);
fBtnValInfo();
}
else fBtnUsage(btn); // use buttons feature
}
}
// clear all button features assignments and quick scope
void fDefaultFeatures() {
uint8 btn;
for (btn=BUTTON_4;btn<=BUTTON_17;btn++) { // buttons PS4: R1..Square
BtnsFeature[btn]=FNONE;
BtnsToggle[btn]=TOFF;
}
QSCfg=6;
bQScope=FALSE;
}
// select feature for the button
void fBtnSelect(uint8 btn) {
static uint32 TXTFCurBLock=0;
// cycle through modes with dbl tap
if (fTaps(btn,2,250)) {
TXTFCurBLock=system_time()+TXTFCURWait; // block current button text info when new is selected
combo_stop(cDebugBtnText);
BtnsFeature[btn]=(BtnsFeature[btn]+1)%F_MODES;
BtnsToggle[btn]=TOFF; // toggle state reset
DebugBtnFeature(TXTFSEL,btn);
//if (cDebugBtnText)
if (BtnsFeature[btn] < F_MODES ) { // led toggle feedback
if (BtnsFeature[btn] < sizeof(LEDF)) ColorLED(LEDF[BtnsFeature[btn]],200,200,2,LEDF[FNONE]);
}
} else if (event_active(btn)) {
if (TXTSelect[TXTFCUR] && system_time() > TXTFCurBLock) {
combo_run(cDebugBtnText);
}
}
// update debug info for current button
if (event_active(btn)) {
BtnLast=btn;
if (TXTSelect[TXTFEAT]) combo_run(cDebugBtnsText);
}
}
// use buttons selected features
void fBtnUsage(uint8 btn) {
// Button feature ON/OFF toggle with short tap
if (BtnsFeature[btn]!=FNONE && event_release(btn) && time_active(btn) <=250) {
if (BtnsToggle[btn]%T_MODES==TOFF) {
BtnsToggle[btn]+=TON; // sets 1,3,5 (3,5 for multi toggle)
if (BtnsFeature[btn]==FMULTIDN || BtnsFeature[btn]==FMULTIDA) BtnsToggle[btn]=TOFF;
if ((BtnsFeature[btn]==FMULTITN || BtnsFeature[btn]==FMULTITA) && BtnsToggle[btn] < T_MODES) BtnsToggle[btn]=TOFF;
} else if (BtnsToggle[btn]%T_MODES==TON) { // disable
if (BtnsFeature[btn]==FMULTIDN || BtnsFeature[btn]==FMULTIDA) BtnsToggle[btn]=TOFF;
else BtnsToggle[btn]-=TON; // sets 0,2,4 (2,4 for multi org)
}
}
// Buttonhold + press Share toggles turbo<->alt turbo
if (get_actual(btn)) {
set_val(BUTTON_3,0);set_val(BUTTON_18,0); // block share & options
if (event_active(BUTTON_18)) fTurboModeFlip(btn);
}
// multi feature mode : tap+presshold = turbo || hold>1sec = hold
if (BtnsFeature[btn]==FMULTIDN || BtnsFeature[btn]==FMULTIDA || BtnsFeature[btn]==FMULTITN || BtnsFeature[btn]==FMULTITA) {
if (event_release(btn) || event_active(btn) || get_actual(btn)) fMultiFeature(btn);
}
// feature with toggle
if (BtnsToggle[btn]%T_MODES==TON) {
if (BtnsFeature[btn]==FHOLD || BtnsToggle[btn]==TMHOLD+TON) { bLED[idx_LEDFH] =1; set_val(btn,100); }
else if (BtnsFeature[btn]==FTURBOTN || BtnsFeature[btn]==FMULTIDN || BtnsFeature[btn]==FMULTITN) {
bLED[idx_LEDFTN]=1; set_val(btn,BtnTurboVal[TurboIdxN]);
}
else if (BtnsFeature[btn]==FTURBOTA || BtnsFeature[btn]==FMULTIDA || BtnsFeature[btn]==FMULTITA) {
bLED[idx_LEDFTA]=1; set_val(btn,BtnTurboVal[TurboIdxA]);
}
}
// active when the button is held down
if (BtnsFeature[btn]==FTURBOHN) {
BtnsToggle[btn]=0;
if (get_actual(btn)) { BtnsToggle[btn]=1; bLED[idx_LEDFTN]=1; set_val(btn,BtnTurboVal[TurboIdxN]); }
}
if (BtnsFeature[btn]==FTURBOHA) {
BtnsToggle[btn]=0;
if (get_actual(btn)) { BtnsToggle[btn]=1; bLED[idx_LEDFTA]=1; set_val(btn,BtnTurboVal[TurboIdxA]); }
}
if (BtnValInfo) if (event_release(btn)||event_active(btn)||get_actual(btn)) fBtnValInfo(btn);
}
// multi feature mode
void fMultiFeature(uint8 btn) {
static uint8 block=FALSE; // block after toggle until next release
if (event_release(btn)) block=FALSE;
if (fTaps(btn,2,200,250)) { // tap+presshold
block=TRUE;
if (BtnsFeature[btn]==FMULTIDN || BtnsFeature[btn]==FMULTIDA) BtnsToggle[btn]=TMTURBO+TON; // direct activation
else if (BtnsFeature[btn]==FMULTITN || BtnsFeature[btn]==FMULTITA) BtnsToggle[btn]=TMTURBO+TOFF; // req additional tap
}
if (!block && check_active(btn,1000)) { // hold
block=TRUE;
if (BtnsFeature[btn]==FMULTIDN || BtnsFeature[btn]==FMULTIDA ) BtnsToggle[btn]=TMHOLD+TON; // direct activation
else if (BtnsFeature[btn]==FMULTITN || BtnsFeature[btn]==FMULTITA) BtnsToggle[btn]=TMHOLD+TOFF; // req additional tap
}
// switch multi normal<->toggle(missunderstood) , btn+press Options
if (get_actual(btn) && event_active(BUTTON_3)){
if (BtnsFeature[btn]==FMULTIDN) {
BtnsFeature[btn]=FMULTITN; BtnsToggle[btn]=TOFF;
if (BtnsFeature[btn] < sizeof(LEDF)) ColorLED(LEDF[BtnsFeature[btn]],140,140,3,LEDF[FNONE]);
}
else if (BtnsFeature[btn]==FMULTITN) {
BtnsFeature[btn]=FMULTIDN; BtnsToggle[btn]=TOFF;
if (BtnsFeature[btn] < sizeof(LEDF)) ColorLED(LEDF[BtnsFeature[btn]],140,140,3,LEDF[FNONE]);
}
else if (BtnsFeature[btn]==FMULTIDA) {
BtnsFeature[btn]=FMULTITA; BtnsToggle[btn]=TOFF;
if (BtnsFeature[btn] < sizeof(LEDF)) ColorLED(LEDF[BtnsFeature[btn]],140,140,3,LEDF[FNONE]);
}
else if (BtnsFeature[btn]==FMULTITA) {
BtnsFeature[btn]=FMULTIDA; BtnsToggle[btn]=TOFF;
if (BtnsFeature[btn] < sizeof(LEDF)) ColorLED(LEDF[BtnsFeature[btn]],140,140,3,LEDF[FNONE]);
}
}
}
// turbo<->altturbo
void fTurboModeFlip(uint8 btn) {
bool flipped=FALSE;
if (BtnsFeature[btn]==FTURBOHN) { BtnsFeature[btn]=FTURBOHA; flipped=TRUE; } // hold
else if (BtnsFeature[btn]==FTURBOHA) { BtnsFeature[btn]=FTURBOHN; flipped=TRUE; }
else if (BtnsFeature[btn]==FTURBOTN) { BtnsFeature[btn]=FTURBOTA; flipped=TRUE; } // toggle
else if (BtnsFeature[btn]==FTURBOTA) { BtnsFeature[btn]=FTURBOTN; flipped=TRUE; }
else if (BtnsFeature[btn]==FMULTIDN) { BtnsFeature[btn]=FMULTIDA; flipped=TRUE; } // multi direct
else if (BtnsFeature[btn]==FMULTIDA) { BtnsFeature[btn]=FMULTIDN; flipped=TRUE; }
else if (BtnsFeature[btn]==FMULTITN) { BtnsFeature[btn]=FMULTITA; flipped=TRUE; } // multi toggle
else if (BtnsFeature[btn]==FMULTITA) { BtnsFeature[btn]=FMULTITN; flipped=TRUE; }
if (flipped) {
DebugBtnFeature(TXTFSEL,btn);
if (BtnsFeature[btn] < sizeof(LEDF)) ColorLED(LEDF[BtnsFeature[btn]],140,140,3,LEDF[FNONE]);
}
}
// adjust turbo press and release times
void fTurboAdjust() {
// R1: TPress+10
if (event_active(BUTTON_4) && TPress < 2000) { TPress += 10; }
// L1: TPress-10
if (event_active(BUTTON_7) && TPress > 20 ) { TPress -= 10; }
// R2: TRelease+10
if (event_active(BUTTON_5) && TRelease < 2000) { TRelease += 10; }
// L2: TRelease-10
if (event_active(BUTTON_8) && TRelease > 20 ) { TRelease -= 10;}
}
// reset turbo timings
void fTurboDefault() {
TPress = 40;
TRelease = 40;
//fReset();
}
// sets current button value for the turbo modes to use when active
void fTurboTimer() {
uint32 syst = system_time();
static uint32 TurboTimer=system_time();
static uint32 AltTurboTimer=0;
if ( syst > TurboTimer && TurboTimer != 0 ) { // TURBO
if (AltTurboTimer == 0 ) AltTurboTimer=TurboTimer + TPress + TRelease/2 - TPress/2;
if ( syst > TurboTimer && syst <=TurboTimer+TPress ) BtnTurboVal[TurboIdxN]=100;
else if ( syst > TurboTimer+TPress && syst < TurboTimer+TPress+TRelease) BtnTurboVal[TurboIdxN]=0;
else if ( syst >= TurboTimer+TPress+TRelease) TurboTimer = syst;
}
if ( syst > AltTurboTimer && AltTurboTimer != 0 ) { // TURBO ALTERNATE
if ( syst > AltTurboTimer && syst <=AltTurboTimer+TPress ) BtnTurboVal[TurboIdxA]=100;
else if ( syst > AltTurboTimer+TPress && syst < AltTurboTimer+TPress+TRelease) BtnTurboVal[TurboIdxA]=0;
else if ( syst >= AltTurboTimer+TPress+TRelease) AltTurboTimer = 0;
}
}
void fQuickScope() {
if (bQScope && time_active(QSBtns[QSCfg]) < QSTimeLimit && event_release(QSBtns[QSCfg])) {
combo_run(cQuickScope);
}
}
combo cQuickScope {
set_val(QSBtns[QSCfg], 100);
wait(500);
set_val(QSBtns[QSCfg], 100);
set_val(QSBtns[QSCfg+1], 100);
wait(50);
set_val(QSBtns[QSCfg], 0);
set_val(QSBtns[QSCfg+1], 0);
}
void fSensitivityAdjust() {
// R1: TPress+10
if (event_active(BUTTON_4) && RSensitivity < 200) { RSensitivity += 10; }
// L1: TPress-10
if (event_active(BUTTON_7) && LSensitivity < 200) { LSensitivity += 10; }
// R2: TRelease+10
if (event_active(BUTTON_5) && RSensitivity > 20) { RSensitivity -= 10; }
// L2: TRelease-10
if (event_active(BUTTON_8) && LSensitivity > 20) { LSensitivity -= 10; }
}
void fSensitivityDefault() {
RSensitivity = 100;
LSensitivity = 100;
}
// deadzone and sensitivity
void fSticks() {
fDZSens(STICK_1_X,DeadZone,RSensitivity);
fDZSens(STICK_1_Y,DeadZone,RSensitivity);
fDZSens(STICK_2_X,DeadZone,LSensitivity);
fDZSens(STICK_2_Y,DeadZone,LSensitivity);
}
void fDZSens(uint8 axis, fix32 dz,int16 sens) {
if (abs(get_val(axis)) <= dz) {
set_val(axis, 0.0);
} else fSensitivity(axis, 50, sens);
}
void fSensitivity(uint8 id, int16 mid, int16 sen) {
int16 val = (int16)get_val(id);
if(mid != 0) {
int16 val_s = (val >= 0) ? 1 : -1;
val *= val_s;
if(val <= mid) {
val = (val * 50) / mid;
}
else {
val = ((50 * (val - mid)) / (100 - mid)) + 50;
}
val *= val_s;
}
if(sen != 0) {
val = (val * sen) / 100;
}
set_val(id, clamp(val, -100, 100));
return;
}
// cycle through output protocols
void fOutput() {
static uint8 IOP=4;
IOP=(IOP+1)%4;
if (IOP == 0) {
fOutputProtocol(PIO_XB360);
}
if (IOP == 1) {
fOutputProtocol(PIO_PS3);
}
if (IOP == 2) {
fOutputProtocol(PIO_XB1);
}
if (IOP == 3) {
fOutputProtocol(PIO_PS4);
}
}
// activate output protocol
void fOutputProtocol(uint8 id) {
if(bConfigure) return; // don't change it during config, doing it now on exit of configmode
port_disconnect();
switch(id) {
case PIO_PS3:
port_connect(PORT_USB_C, PROTOCOL_PS3);
TextMode(TXTPROT,TRUE,"PROTOCOL_PS3");
break;
case PIO_XB360:
port_connect(PORT_USB_C, PROTOCOL_XB360);
TextMode(TXTPROT,TRUE,"PROTOCOL_XB360");
break;
case PIO_PS4:
port_connect(PORT_USB_C, PROTOCOL_PS4);
TextMode(TXTPROT,TRUE,"PROTOCOL_PS4");
break;
case PIO_XB1:
port_connect(PORT_USB_C, PROTOCOL_XB1);
TextMode(TXTPROT,TRUE,"PROTOCOL_XB1");
break;
case PIO_SWITCH:
port_connect(PORT_USB_C, PROTOCOL_SWITCH);
TextMode(TXTPROT,TRUE,"PROTOCOL_SWITCH");
break;
default:
port_connect(PORT_USB_C, PROTOCOL_AUTO);
TextMode(TXTPROT,TRUE,"PROTOCOL_AUTO");
}
return;
}
// check button tapped "taps" times, each press in the timelimit, with optional hold time check
uint8 fTaps(uint8 btn, uint8 taps, uint32 tlimit, uint32 thold) {
static uint8 lastbtn=200, itaps=0;
static uint32 lastta=0;
if (event_active(btn)) {
if (btn!=lastbtn || lastta+time_release(btn)>tlimit) { lastbtn=btn; itaps=1; }
else if (btn==lastbtn) itaps++;
if (itaps==taps && !thold) { itaps=0; return TRUE; }
}
if (thold && check_active(btn,thold) && itaps==taps) {
itaps=0;
return TRUE;
}
if (event_release(btn) && btn==lastbtn) lastta=time_active(btn);
return FALSE;
}
// block output
void fNullOutput() {
set_val(BUTTON_1,0); set_val(BUTTON_2,0); set_val(BUTTON_3,0); set_val(BUTTON_4,0);
set_val(BUTTON_5,0); set_val(BUTTON_6,0); set_val(BUTTON_7,0); set_val(BUTTON_8,0);
set_val(BUTTON_9,0); set_val(BUTTON_10,0); set_val(BUTTON_11,0); set_val(BUTTON_12,0);
set_val(BUTTON_13,0); set_val(BUTTON_14,0); set_val(BUTTON_15,0); set_val(BUTTON_16,0);
set_val(BUTTON_17,0); set_val(BUTTON_18,0); set_val(BUTTON_19,0); set_val(BUTTON_20,0);
set_val(BUTTON_21,0);
set_val(STICK_1_X,0); set_val(STICK_1_Y,0); set_val(STICK_2_X,0); set_val(STICK_2_Y,0);
set_val(POINT_1_X,0); set_val(POINT_1_Y,0); set_val(POINT_2_X,0); set_val(POINT_2_Y,0);
set_val(ACCEL_1_X,0); set_val(ACCEL_1_Y,0); set_val(ACCEL_1_Z,0);
set_val(ACCEL_2_X,0); set_val(ACCEL_2_Y,0); set_val(ACCEL_2_Z,0);
set_val(GYRO_1_X,0); set_val(GYRO_1_Y,0); set_val(GYRO_1_Z,0);
}
void fDebug() {
if (elapsed_time()) {
fNullOutput(); // zero all output via set_val
set_val(ACCEL_1_Z, TPress / 10);
set_val(ACCEL_2_X, TRelease / 10);
set_val(ACCEL_2_Z, CfgMode);
if (CfgMode==CFGBTN_SCOPE) fBtnValInfo();
}
}
// last button pressed info
void fBtnValInfo(uint8 btn) {
// output format BtnNr NN*1000 , Feature FF , Toggle TT/100
static fix32 DebugLastBtn=9999.0;
if (btn>0) {
// device monitor value
DebugLastBtn=(fix32)btn+1.0; // nr 16 -> name_17.0
DebugLastBtn*=1000.0; // button name 17: 17000.00
if (btn!=BUTTON_2) {
DebugLastBtn+=(fix32)BtnsFeature[btn]; // feature 170FF.00
DebugLastBtn+=(fix32)BtnsToggle[btn]/100.0; // feature 170FF.00
} else {
DebugLastBtn+=(fix32)bQScope;
DebugLastBtn+=(fix32)QSCfg/100f;
}
}
if (DebugLastBtn!=9999.0) { // output
set_val(BtnValTo, DebugLastBtn);
}
}
combo cDebugBtnsText { // all buttons features & states
wait(TXTFEATWait);
fDebugBtnsText();
wait(0);
}
void fDebugBtnsText() {
uint8 btn;
TextMode(TXTFEAT,FALSE,"<h3><pre><b>");
for (btn=BUTTON_4;btn<BUTTON_10;btn++)
TextMode(-1,FALSE," ",NR[btn+1]," |");
for (btn=BUTTON_10;btn<=BUTTON_17;btn++)
TextMode(-1,FALSE," ",NR[btn+1]," |");
print(" QS</b><br>");
for (btn=BUTTON_4;btn<=BUTTON_17;btn++) {
if (BtnsFeature[btn]<10) TextMode(-1,FALSE," ",NR[BtnsFeature[btn]],".",NR[BtnsToggle[btn]],"|");
else TextMode(-1,FALSE," ",NR[BtnsFeature[btn]],".",NR[BtnsToggle[btn]],"|");
}
TextMode(-1,FALSE," ",NR[QSCfg/2],".",NR[bQScope]);
print("<br><font color='green'>");
// feature selected indicator
for (btn=BUTTON_4;btn<=BUTTON_17;btn++) {
if (BtnLast==btn && BtnsFeature[btn]) print(" + ");
else if (BtnsFeature[btn]) print(" ^ ");
else print(" ");
}
if (bQScope && BtnLast==BUTTON_2) print(" +");
else if (bQScope) print(" ^");
else print("");
print("</font></pre></h3>");
print(NULL);
}
void DebugBtnFeature(uint8 txtmode,uint8 btn) {
char *symbl[] = {" -> ", " == "};
uint8 isymbl=0;
if (txtmode!=TXTFSEL) isymbl=1;
if (btn!=BUTTON_2) {
TextMode(txtmode,TRUE,"Btn_",NR[btn+1],symbl[isymbl],
FNAMES[BtnsFeature[btn]]);
} else {
if (bQScope) TextMode(txtmode,TRUE,"Quickscope activate, Scope Btn_",NR[QSBtns[QSCfg]+1],
" , Fire Btn_",NR[QSBtns[QSCfg+1]+1]);
else TextMode(txtmode,TRUE,"Quickscope disabled");
}
}
combo cDebugBtnText{
wait(TXTFCURWait);
DebugBtnFeature(TXTFCUR,BtnLast);
wait(0);
}
// text styles
void TextMode(int8 tag, bool write,
char *str1, char *str2, char *str3, char *str4,
char *str5, char *str6, char *str7, char *str8) {
if (tag>-1) {
if (TXTLast!=tag) TXTLast=tag;
if (!TXTSelect[tag]) return; // skip disabled debug types
switch(tag) {
case TXTMENU: print("<b><font color='#00802b'>MENU</font></b> ");
break;
case TXTFEAT: print("<b><font color='#00802b'>FEATURES</font></b> ");
break;
case TXTPROT: print("<b><font color='#00802b'>PROTOCOL</font></b> ");
break;
case TXTLED: print("<b><font color='#00802b'>LED</font></b> ");
break;
case TXTFSEL: print("<b><font color='#00802b'>SELECTED</font></b> ");
break;
case TXTFCUR: print("<b><font color='#00802b'>CURRENT</font></b> ");
break;
}
}
if (str1) print(str1);
if (str2) print(str2);
if (str3) print(str3);
if (str4) print(str4);
if (str5) print(str5);
if (str6) print(str6);
if (str7) print(str7);
if (str8) print(str8);
if (write) print(NULL);
}
// J2Kbr print to output panel without automatic linebreak
void print(char *str, bool reset) {
if (!TXTSelect[TXTLast]) return; // skip disabled debug types
if (reset) {
tail = NULL;
memset(&buffer,0,sizeof(buffer));
return;
}
if(str) {
if(!tail) {
tail = &buffer; // new text
}
while(*str) {
*tail++ = *str++; // append string
}
} else if(tail) {
printf(&buffer);
tail = NULL;
memset(&buffer,0,sizeof(buffer));
}
}