From 899831bdade0bfa95bc9c0b2900e7760bb006b6b Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Thu, 30 Jul 2020 09:15:24 +1000 Subject: [PATCH] MISRA cleanup --- misra/check_misra_github.sh | 8 +++++- speeduino/TS_CommandButtonHandler.h | 2 +- speeduino/TS_CommandButtonHandler.ino | 6 +---- speeduino/auxiliaries.ino | 23 +++++++--------- speeduino/board_teensy35.ino | 2 +- speeduino/comms.ino | 2 ++ speeduino/decoders.ino | 14 +++++----- speeduino/idle.h | 2 +- speeduino/idle.ino | 6 ++--- speeduino/init.ino | 2 +- speeduino/scheduledIO.ino | 38 +++++++++++++-------------- speeduino/speeduino.ino | 33 ++--------------------- 12 files changed, 54 insertions(+), 84 deletions(-) diff --git a/misra/check_misra_github.sh b/misra/check_misra_github.sh index ea3ac9bb..7e74a8e6 100755 --- a/misra/check_misra_github.sh +++ b/misra/check_misra_github.sh @@ -2,9 +2,15 @@ cppcheck_path=cppcheck_github/ cppcheck_bin="${cppcheck_path}cppcheck" -#cppcheck_bin="cppcheck" cppcheck_misra="${cppcheck_path}addons/misra.py" +#Uncomment below to use the Brew installation of cppcheck on Mac +#cppcheck_path_brew=/usr/local/Cellar/cppcheck/2.1/share/cppcheck/ +#cppcheck_misra="${cppcheck_path_brew}addons/misra.py" +#cppcheck_bin=/usr/local/Cellar/cppcheck/2.1/bin/cppcheck + + + if [ -f ./results.txt ]; then rm results.txt fi diff --git a/speeduino/TS_CommandButtonHandler.h b/speeduino/TS_CommandButtonHandler.h index 4a379b51..be3ef679 100644 --- a/speeduino/TS_CommandButtonHandler.h +++ b/speeduino/TS_CommandButtonHandler.h @@ -65,4 +65,4 @@ #define TS_CMD_VSS_RATIO5 39173 #define TS_CMD_VSS_RATIO6 39174 -uint16_t TS_CommandButtonsHandler(int); \ No newline at end of file +void TS_CommandButtonsHandler(int); \ No newline at end of file diff --git a/speeduino/TS_CommandButtonHandler.ino b/speeduino/TS_CommandButtonHandler.ino index f99d27a6..9cece067 100644 --- a/speeduino/TS_CommandButtonHandler.ino +++ b/speeduino/TS_CommandButtonHandler.ino @@ -18,11 +18,9 @@ * @brief * * @param buttonCommand The command number of the button that was clicked. See TS_CommendButtonHandler.h for a list of button IDs - * @return uint16_t If the button command remains incomplete (IE When it must wait for a certain action to complete) the return value is eqaul to the button ID. Otherwise this function returns 0 */ -uint16_t TS_CommandButtonsHandler(int buttonCommand) +void TS_CommandButtonsHandler(int buttonCommand) { - uint16_t returnValue = 0; switch (buttonCommand) { case TS_CMD_TEST_DSBL: // cmd is stop @@ -351,6 +349,4 @@ uint16_t TS_CommandButtonsHandler(int buttonCommand) default: break; } - - return returnValue; } \ No newline at end of file diff --git a/speeduino/auxiliaries.ino b/speeduino/auxiliaries.ino index 81c7fb88..de28326f 100644 --- a/speeduino/auxiliaries.ino +++ b/speeduino/auxiliaries.ino @@ -224,7 +224,7 @@ void vvtControl() { //currentStatus.vvt1Duty = 0; //Calculate the current cam angle - if( configPage4.TrigPattern == 9 ) { getCamAngle_Miata9905(); } + if( configPage4.TrigPattern == 9 ) { currentStatus.vvt1Angle = getCamAngle_Miata9905(); } if( (configPage6.vvtMode == VVT_MODE_OPEN_LOOP) || (configPage6.vvtMode == VVT_MODE_ONOFF) ) { @@ -259,17 +259,12 @@ void vvtControl() //This is dumb, but need to convert the current angle into a long pointer vvt_pid_target_angle = currentStatus.vvt1TargetAngle; - if(currentStatus.vvt1TargetAngle >= 0) - { - //If not already at target angle, calculate new value from PID - bool PID_compute = vvtPID.Compute(false); - //vvtPID.Compute2(currentStatus.vvt1TargetAngle, currentStatus.vvt1Angle, false); - //vvt_pwm_target_value = percentage(40, vvt_pwm_max_count); - //if (currentStatus.vvt1Angle > currentStatus.vvt1TargetAngle) { vvt_pwm_target_value = 0; } - if(PID_compute == true) { currentStatus.vvt1Duty = (vvt1_pwm_value * 100) / vvt_pwm_max_count; } - - } - else { currentStatus.vvt1Duty = 0; } + //If not already at target angle, calculate new value from PID + bool PID_compute = vvtPID.Compute(false); + //vvtPID.Compute2(currentStatus.vvt1TargetAngle, currentStatus.vvt1Angle, false); + //vvt_pwm_target_value = percentage(40, vvt_pwm_max_count); + //if (currentStatus.vvt1Angle > currentStatus.vvt1TargetAngle) { vvt_pwm_target_value = 0; } + if(PID_compute == true) { currentStatus.vvt1Duty = (vvt1_pwm_value * 100) / vvt_pwm_max_count; } } if( (currentStatus.vvt1Duty > 0) || (currentStatus.vvt2Duty > 0) ) { ENABLE_VVT_TIMER(); } @@ -372,12 +367,12 @@ void wmiControl() int wmiPW = 0; // wmi can only work when vvt is disabled - if(configPage6.vvtEnabled == 0 && configPage10.wmiEnabled >= 1) + if( (configPage6.vvtEnabled == 0) && (configPage10.wmiEnabled >= 1) ) { currentStatus.wmiEmpty = WMI_TANK_IS_EMPTY(); if(currentStatus.wmiEmpty == 0) { - if(currentStatus.TPS >= configPage10.wmiTPS && currentStatus.RPMdiv100 >= configPage10.wmiRPM && currentStatus.MAP/2 >= configPage10.wmiMAP && currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET >= configPage10.wmiIAT) + if( (currentStatus.TPS >= configPage10.wmiTPS) && (currentStatus.RPMdiv100 >= configPage10.wmiRPM) && ( (currentStatus.MAP / 2) >= configPage10.wmiMAP) && ( (currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET) >= configPage10.wmiIAT) ) { switch(configPage10.wmiMode) { diff --git a/speeduino/board_teensy35.ino b/speeduino/board_teensy35.ino index 58bdb7ee..8fb11bc1 100644 --- a/speeduino/board_teensy35.ino +++ b/speeduino/board_teensy35.ino @@ -347,7 +347,7 @@ void ftm3_isr(void) //Boost and VVT handler void ftm1_isr(void) { - //FTM1 only has 2 compare channels + //FTM1 only has 2 compare channels (Is this correct?) //Use separate variables for each test to ensure conversion to bool bool interrupt1 = (FTM1_C0SC & FTM_CSC_CHF); bool interrupt2 = (FTM1_C1SC & FTM_CSC_CHF); diff --git a/speeduino/comms.ino b/speeduino/comms.ino index e0b5f157..d5ac23f5 100644 --- a/speeduino/comms.ino +++ b/speeduino/comms.ino @@ -1135,6 +1135,7 @@ void sendPage() break; case wmiMapPage: + { //Need to perform a translation of the values[MAP/TPS][RPM] into the MS expected format byte response[80]; //Bit hacky, but send 1 map at a time (Each map is 8x8, so 64 + 8 + 8) @@ -1144,6 +1145,7 @@ void sendPage() for (int y = 72; y < 80; y++) { response[y] = byte(wmiTable.axisY[7 - (y - 72)] / TABLE_LOAD_MULTIPLIER); } Serial.write((byte *)&response, 80); break; + } default: #ifndef SMALL_FLASH_MODE diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index b856df24..2cc1a839 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -331,14 +331,14 @@ void triggerSetup_missingTooth() triggerToothAngle = 360 / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth if(configPage4.TrigSpeed == CAM_SPEED) { triggerToothAngle = 720 / configPage4.triggerTeeth; } //Account for cam speed missing tooth triggerActualTeeth = configPage4.triggerTeeth - configPage4.triggerMissingTeeth; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt - triggerFilterTime = (int)(1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise if (configPage4.trigPatternSec == SEC_TRIGGER_4_1) { triggerSecFilterTime = 1000000 * 60 / MAX_RPM / 4 / 2; } else { - triggerSecFilterTime = (int)(1000000 / (MAX_RPM / 60)); + triggerSecFilterTime = (1000000 / (MAX_RPM / 60)); } secondDerivEnabled = false; decoderIsSequential = false; @@ -649,8 +649,8 @@ void triggerSetup_DualWheel() triggerToothAngle = 360 / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth if(configPage4.TrigSpeed == 1) { triggerToothAngle = 720 / configPage4.triggerTeeth; } //Account for cam speed toothCurrentCount = 255; //Default value - triggerFilterTime = (int)(1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise - triggerSecFilterTime = (int)(1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed) + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise + triggerSecFilterTime = (1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed) secondDerivEnabled = false; decoderIsSequential = true; triggerToothAngleIsCorrect = true; //This is always true for this pattern @@ -2429,8 +2429,8 @@ void triggerSetup_non360() { triggerToothAngle = (360 * configPage4.TrigAngMul) / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth multiplied by the additional multiplier toothCurrentCount = 255; //Default value - triggerFilterTime = (uint32_t)(1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise - triggerSecFilterTime = (int)(1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed) + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise + triggerSecFilterTime = (1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed) secondDerivEnabled = false; decoderIsSequential = true; MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) @@ -3424,7 +3424,7 @@ void triggerSetup_ThirtySixMinus21() { triggerToothAngle = 10; //The number of degrees that passes from tooth to tooth triggerActualTeeth = 33; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt. Not Used - triggerFilterTime = (int)(1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise secondDerivEnabled = false; decoderIsSequential = false; checkSyncToothCount = (configPage4.triggerTeeth) >> 1; //50% of the total teeth. diff --git a/speeduino/idle.h b/speeduino/idle.h index 348c44e8..3b531aad 100644 --- a/speeduino/idle.h +++ b/speeduino/idle.h @@ -51,7 +51,7 @@ volatile bool idle_pwm_state; unsigned int idle_pwm_max_count; //Used for variable PWM frequency volatile unsigned int idle_pwm_cur_value; long idle_pid_target_value; -long idle_pwm_target_value; +unsigned long idle_pwm_target_value; long idle_cl_target_rpm; byte idleCounter; //Used for tracking the number of calls to the idle control function diff --git a/speeduino/idle.ino b/speeduino/idle.ino index 93b35a9c..1df1390c 100644 --- a/speeduino/idle.ino +++ b/speeduino/idle.ino @@ -257,7 +257,7 @@ void idleControl() currentStatus.idleDuty = table2D_getValue(&iacCrankDutyTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees currentStatus.idleLoad = currentStatus.idleDuty; idle_pwm_target_value = percentage(currentStatus.idleDuty, idle_pwm_max_count); - idle_pid_target_value = idle_pwm_target_value<<2; //Resolution increased + idle_pid_target_value = idle_pwm_target_value << 2; //Resolution increased idlePID.Initialize(); //Update output to smooth transition } else @@ -359,7 +359,7 @@ void idleControl() } doStep(); - idle_pid_target_value = idleStepper.targetIdleStep<<2; //Resolution increased + idle_pid_target_value = idleStepper.targetIdleStep << 2; //Resolution increased idlePID.Initialize(); //Update output to smooth transition } else @@ -375,7 +375,7 @@ void idleControl() currentStatus.CLIdleTarget = (byte)table2D_getValue(&iacClosedLoopTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //All temps are offset by 40 degrees idle_cl_target_rpm = (uint16_t)currentStatus.CLIdleTarget * 10; //All temps are offset by 40 degrees PID_computed = idlePID.Compute(true); - idleStepper.targetIdleStep = idle_pid_target_value>>2; //Increase resolution + idleStepper.targetIdleStep = idle_pid_target_value >> 2; //Increase resolution if(currentStatus.idleUpActive == true) { idleStepper.targetIdleStep += configPage2.idleUpAdder; } //Add Idle Up amount if active //limit to the configured max steps. This must include any idle up adder, to prevent over-opening. diff --git a/speeduino/init.ino b/speeduino/init.ino index f480c640..da3b9ab6 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -2558,7 +2558,7 @@ void setPinMapping(byte boardID) if(configPage10.wmiIndicatorEnabled > 0) { pinMode(pinWMIIndicator, OUTPUT); - if (configPage10.wmiIndicatorPolarity > 0) digitalWrite(pinWMIIndicator, HIGH); + if (configPage10.wmiIndicatorPolarity > 0) { digitalWrite(pinWMIIndicator, HIGH); } } if(configPage10.wmiEmptyEnabled > 0) { diff --git a/speeduino/scheduledIO.ino b/speeduino/scheduledIO.ino index 5d601812..99c756f2 100644 --- a/speeduino/scheduledIO.ino +++ b/speeduino/scheduledIO.ino @@ -3,25 +3,8 @@ #include "globals.h" #include "timers.h" -#ifndef USE_MC33810 - inline void openInjector1() { *inj1_pin_port |= (inj1_pin_mask); BIT_SET(currentStatus.status1, BIT_STATUS1_INJ1); } - inline void closeInjector1() { *inj1_pin_port &= ~(inj1_pin_mask); BIT_CLEAR(currentStatus.status1, BIT_STATUS1_INJ1); } - inline void openInjector2() { *inj2_pin_port |= (inj2_pin_mask); BIT_SET(currentStatus.status1, BIT_STATUS1_INJ2); } - inline void closeInjector2() { *inj2_pin_port &= ~(inj2_pin_mask); BIT_CLEAR(currentStatus.status1, BIT_STATUS1_INJ2); } - inline void openInjector3() { *inj3_pin_port |= (inj3_pin_mask); BIT_SET(currentStatus.status1, BIT_STATUS1_INJ3); } - inline void closeInjector3() { *inj3_pin_port &= ~(inj3_pin_mask); BIT_CLEAR(currentStatus.status1, BIT_STATUS1_INJ3); } - inline void openInjector4() { *inj4_pin_port |= (inj4_pin_mask); BIT_SET(currentStatus.status1, BIT_STATUS1_INJ4); } - inline void closeInjector4() { *inj4_pin_port &= ~(inj4_pin_mask); BIT_CLEAR(currentStatus.status1, BIT_STATUS1_INJ4); } - inline void openInjector5() { *inj5_pin_port |= (inj5_pin_mask); } - inline void closeInjector5() { *inj5_pin_port &= ~(inj5_pin_mask); } - inline void openInjector6() { *inj6_pin_port |= (inj6_pin_mask); } - inline void closeInjector6() { *inj6_pin_port &= ~(inj6_pin_mask); } - inline void openInjector7() { *inj7_pin_port |= (inj7_pin_mask); } - inline void closeInjector7() { *inj7_pin_port &= ~(inj7_pin_mask); } - inline void openInjector8() { *inj8_pin_port |= (inj8_pin_mask); } - inline void closeInjector8() { *inj8_pin_port &= ~(inj8_pin_mask); } -#else -#include "acc_mc33810.h" +#ifdef USE_MC33810 + #include "acc_mc33810.h" inline void openInjector1() { openInjector1_MC33810(); } inline void closeInjector1() { closeInjector1_MC33810(); } inline void openInjector2() { openInjector2_MC33810(); } @@ -38,6 +21,23 @@ inline void closeInjector7() { closeInjector7_MC33810(); } inline void openInjector8() { openInjector8_MC33810(); } inline void closeInjector8() { closeInjector8_MC33810(); } +#else + inline void openInjector1() { *inj1_pin_port |= (inj1_pin_mask); BIT_SET(currentStatus.status1, BIT_STATUS1_INJ1); } + inline void closeInjector1() { *inj1_pin_port &= ~(inj1_pin_mask); BIT_CLEAR(currentStatus.status1, BIT_STATUS1_INJ1); } + inline void openInjector2() { *inj2_pin_port |= (inj2_pin_mask); BIT_SET(currentStatus.status1, BIT_STATUS1_INJ2); } + inline void closeInjector2() { *inj2_pin_port &= ~(inj2_pin_mask); BIT_CLEAR(currentStatus.status1, BIT_STATUS1_INJ2); } + inline void openInjector3() { *inj3_pin_port |= (inj3_pin_mask); BIT_SET(currentStatus.status1, BIT_STATUS1_INJ3); } + inline void closeInjector3() { *inj3_pin_port &= ~(inj3_pin_mask); BIT_CLEAR(currentStatus.status1, BIT_STATUS1_INJ3); } + inline void openInjector4() { *inj4_pin_port |= (inj4_pin_mask); BIT_SET(currentStatus.status1, BIT_STATUS1_INJ4); } + inline void closeInjector4() { *inj4_pin_port &= ~(inj4_pin_mask); BIT_CLEAR(currentStatus.status1, BIT_STATUS1_INJ4); } + inline void openInjector5() { *inj5_pin_port |= (inj5_pin_mask); } + inline void closeInjector5() { *inj5_pin_port &= ~(inj5_pin_mask); } + inline void openInjector6() { *inj6_pin_port |= (inj6_pin_mask); } + inline void closeInjector6() { *inj6_pin_port &= ~(inj6_pin_mask); } + inline void openInjector7() { *inj7_pin_port |= (inj7_pin_mask); } + inline void closeInjector7() { *inj7_pin_port &= ~(inj7_pin_mask); } + inline void openInjector8() { *inj8_pin_port |= (inj8_pin_mask); } + inline void closeInjector8() { *inj8_pin_port &= ~(inj8_pin_mask); } #endif // These are for Semi-Sequential and 5 Cylinder injection diff --git a/speeduino/speeduino.ino b/speeduino/speeduino.ino index 6530f62e..fe36b005 100644 --- a/speeduino/speeduino.ino +++ b/speeduino/speeduino.ino @@ -253,8 +253,8 @@ void loop() //Water methanol injection wmiControl(); //FOR TEST PURPOSES ONLY!!! - if(vvt2_pwm_value < vvt_pwm_max_count) vvt2_pwm_value++; - else vvt2_pwm_value = 1; + if(vvt2_pwm_value < vvt_pwm_max_count) { vvt2_pwm_value++; } + else { vvt2_pwm_value = 1; } } if (BIT_CHECK(LOOP_TIMER, BIT_TIMER_4HZ)) { @@ -575,11 +575,6 @@ void loop() currentStatus.injAngle = table2D_getValue(&injectorAngleTable, currentStatus.RPM / 100); unsigned int PWdivTimerPerDegree = div(currentStatus.PW1, timePerDegree).quot; //How many crank degrees the calculated PW will take at the current speed - //This is a little primitive, but is based on the idea that all fuel needs to be delivered before the inlet valve opens. See www.extraefi.co.uk/sequential_fuel.html for more detail - //if(configPage2.inj1Ang > PWdivTimerPerDegree) { injector1StartAngle = configPage2.inj1Ang - ( PWdivTimerPerDegree ); } - //else { injector1StartAngle = configPage2.inj1Ang + CRANK_ANGLE_MAX_INJ - PWdivTimerPerDegree; } //Just incase - //while(injector1StartAngle > CRANK_ANGLE_MAX_INJ) { injector1StartAngle -= CRANK_ANGLE_MAX_INJ; } - injector1StartAngle = calculateInjectorStartAngle(PWdivTimerPerDegree, channel1InjDegrees); //Repeat the above for each cylinder @@ -798,18 +793,6 @@ void loop() rollingCutLastRev = currentStatus.startRevolutions; //curRollingCut = 0; } - /* - else - { - if(rollingCutLastRev == 0) { rollingCutLastRev = currentStatus.startRevolutions; } // - if (rollingCutLastRev != currentStatus.startRevolutions) - { - rollingCutLastRev = currentStatus.startRevolutions; - rollingCutCounter++; - } - ignitionOn = false; //Finally the ignition is fully cut completely - } - */ } //Hard/Rolling cut check } //RPM Check else { currentStatus.engineProtectStatus = 0; } //Force all engine protection flags to be off as we're below the minimum RPM @@ -1374,18 +1357,6 @@ byte getAdvance() return tempAdvance; } -/* -uint16_t calculateInjector2StartAngle(unsigned int PWdivTimerPerDegree) -{ - uint16_t tempInjector2StartAngle = (currentStatus.injAngle + channel2InjDegrees); //This makes the start angle equal to the end angle - if(tempInjector2StartAngle < PWdivTimerPerDegree) { tempInjector2StartAngle += CRANK_ANGLE_MAX_INJ; } - tempInjector2StartAngle -= PWdivTimerPerDegree; //Subtract the number of degrees the PW will take to get the start angle - if(tempInjector2StartAngle > (uint16_t)CRANK_ANGLE_MAX_INJ) { tempInjector2StartAngle -= CRANK_ANGLE_MAX_INJ; } - - return tempInjector2StartAngle; -} -*/ - uint16_t calculateInjectorStartAngle(uint16_t PWdivTimerPerDegree, int16_t injChannelDegrees) { uint16_t tempInjectorStartAngle = (currentStatus.injAngle + injChannelDegrees);