// // Main.c // // PRESSURE PRINCIPLE // Dodge Viper Fuel Relay Engine Start Pressurization Time Extender // Version PressurePrinciple-9 29-Jun-2019 // // The header files and the initial boilerplate version of this source file // was created using the Microchip, Inc. Code Configurator ("MCC"), which // creates all the .h and .c files for hardware access for the specific chip // in use. // // Microchip PIC 16F188555 pin usage by this project: // // PORTA<0> OUT ActiveHigh TransistorDrivingLocalRelay TO_LOCAL_FUEL_RELAY // PORTA<1> OUT ActiveHigh ResistorToLEDToGnd TO_LED1_DURINGBOOSTTIME // PORTA<2> OUT ActiveHigh ResistorToLEDToGnd TO_LED2_VIPERFUELCMD // PORTA<5> IN TriStateInput OpenCollectorInECMToGNDActiveLow FROM_VIPER_FUEL_RELAY_CMD // #include "mcc_generated_files/mcc.h" void sleep_ms (int inMilliseconds) // // This works for the oscillator settings of 4MHz, NDIV=4, etc. // We can replace this with something more timer-using if desired. // { for (int i = 0; i < inMilliseconds; i++) { for (int j = 0; j < 14; j++) {} } } void main (void) { // Initialize the device (Microchip, Inc.'s code): // SYSTEM_Initialize (); // Set PORTA<0> (bit 0) to be not-tristate aka configured as output // Set PORTA<1> (bit 1) to be not-tristate aka configured as output // Set PORTA<2> (bit 2) to be not-tristate aka configured as output // Set PORTA<5> (bit 5) to be tristate aka configured as input, as well as all other port bits (power save?) // ------ 76543210 TRISA = 0b11111000; // AnalogSelectPortA: Turn off all analog inputs (needed for enabling digital input): // ------- 76543210 ANSELA = 0b00000000; // Turn off all pull-ups, especially bit 5, which we want to level-sample: // weak pull up A // ----- 76543210 WPUA = 0b00000000; // Turn off: // latch echoing the written outputs (vs. read) A // ----- 76543210 LATA = 0b00000000; // Set digital input analog input level handling (0=TTL vs. 1=SchmittTrig): // // ------- 76543210 INLVLA = 0b00000000; uint16_t timeSincePowerOnReset_10ms = 0; uint8_t prepMode = 0; uint8_t viperECMFuelCommand = 0; uint8_t portAWrite = 0; while (1) { // Part of computing whether we are in prep mode: // "At rising edge of power-up, get INTO prep mode." // if (0 == timeSincePowerOnReset_10ms) { prepMode = 1; } // See text: // while (1) {} // Part of computing whether we are in prep mode: // "At event of POR+THESTARTUPTIMETORUNTHERELAY amount of time, go OUT of prep mode." // if (1100/*11sec*/ == timeSincePowerOnReset_10ms) { prepMode = 0; } // Part of computing whether we are in prep mode: // "At event of POR+THESTARTUPTIMETORUNTHERELAY+SmallUserPromptDelay amount of time, // go back INTO prep mode again." // if (1130/*11sec+SmallDelay*/ == timeSincePowerOnReset_10ms) { prepMode = 1; } // Part of computing whether we are in prep mode: // "At event of POR+THESTARTUPTIMETORUNTHERELAY+SmallUserPromptDelay+AFEWMORESECONDS amount // of time, go back OUT of prep mode again." // if (1430/*N+SmallDelay+3sec*/ == timeSincePowerOnReset_10ms) { prepMode = 0; } // Part of computing whether we are in prep mode: // "No matter what else, if it has been more than 30 seconds, never be in prep mode." // // Do this last, so it has the last word (last vote which thus wins), for safety. // Note that this is level-sensitive, not edge-sensitive, on our timer. // // Furthermore, keep our time base counter from advancing too much. This will thus // prevent anything else from happening. For example, consider otherwise that perhaps // due to integer overflow of the timebase, our above sequence could start again, // thus causing, say, an interruption in fuel flow while driving! But we do not want // to simply hang the CPU either, because we want to still mimic the fuel-on command // from the ECM that's coming in. Nor do we want to stop the timebase from advancing // a bit because it's used for blinkers, etc. So here we just repeat the last 4sec // over and over. // // So that means that, after 30 seconds, we are never in prep mode, and never // being in prep mode means always taking the viper fuel command verbatim. // if (timeSincePowerOnReset_10ms > 3000/*30sec*/) { prepMode = 0; timeSincePowerOnReset_10ms = 2600;/*26sec -- just repeat the last 4sec over and over*/ } // Read the open-collector output from the Viper Engine Control Module (ECM). // A closure to ground indicates active. So, our boolean should be set if the // bit value is "0": // ----------------------------------- 76543210 viperECMFuelCommand = (0 == (PORTA & 0b00100000)); // Get ready to prepare outputs to PortA: // Assume all zero bit values unless set below: // ----------- 76543210 portAWrite = 0b00000000; // Prepare output to PortA: Compute our local relay output: // "RelayOn := FuelPumpCommandFromViper || prepMode" // And write that command output out every time to our port to our relay. // if (viperECMFuelCommand || prepMode) { // Prepare to write a "1" to PORTA<0> // ------------ 76543210 portAWrite |= 0b00000001; } else { // Leave a "0" in PORTA<0> } // Prepare output to PortA: Blink LED1 during prepMode=YES epoch: // "LED1 := 0 normally, or 1 if prepMode & SomeTimeBaseBit" // if (prepMode) { if (0 != (timeSincePowerOnReset_10ms & 0x10)) { // Prepare to write a "1" to PORTA<1> // ------------ 76543210 portAWrite |= 0b00000010; } else { // Leave a "0" in PORTA<1> } } // Prepare output to PortA: Show the value of viperECMFuelCommand: // To make it more visible and to give an idea that the processor is running // long after the initial stuff is done, we will blink it very fast when true; // that is, "LED2 := 0 normally, or 1 if viperECMFuelCommand & SomeFastTimeBaseBit". // if (viperECMFuelCommand) { if (0 != (timeSincePowerOnReset_10ms & 0x04)) { // Prepare to write a "1" to PORTA<2> // ------------ 76543210 portAWrite |= 0b00000100; } else { // Leave a "0" in PORTA<2> } } // Write our outputs to PortA: // // PORTA = portAWrite; // Wait and advance timebase: // sleep_ms (10); timeSincePowerOnReset_10ms++; timeSincePowerOnReset_10ms -= 1; } }