DoubleCoilGun

Dependents:   Telliskivi2_2014

Fork of CoilGun by Reiko Randoja

coilgun.cpp

Committer:
Reiko
Date:
2016-09-17
Revision:
12:7cc6aeaa4bf8
Parent:
11:49959d33916f

File content as of revision 12:7cc6aeaa4bf8:

#include "coilgun.h"
 
Coilgun::Coilgun(PinName kickPinName, PinName chipPinName, PinName chargePinName, PinName donePinName): 
    kickPin(kickPinName), chipPin(chipPinName), chargePin(chargePinName), donePin(donePinName) 
{
    isCharged = false;
    state = idle;
    kickPin = 0;
    chipPin = 0;
    chargePin = 0;
    donePin.fall(this, &Coilgun::chargeEnd);
    
    currentKickLength = 0;
    currentKickDelay = 0;
    currentChipLength = 0;
    currentChipDelay = 0;
    
    kickActive = false;
    chipActive = false;
    
    //discharge(); // For safety reasons.
}

void Coilgun::kick(unsigned int kickLength, unsigned int kickDelay, unsigned int chipLength, unsigned int chipDelay) {    
    kick(kickLength, kickDelay, chipLength, chipDelay, true);
}

void Coilgun::kick(unsigned int kickLength, unsigned int kickDelay, unsigned int chipLength, unsigned int chipDelay, bool change_state = true) {
    if (change_state) {//Used to keep state when discharging
        changeState(kicking);
    }
    
    currentKickLength = kickLength;
    currentKickDelay = kickDelay;
    currentChipLength = chipLength;
    currentChipDelay = chipDelay;
    
    chargePin = 0; // Maybe not needed anymore? (still a safety?)
    
    kickActive = true;
    chipActive = true;
    
    if (currentKickDelay > 0) {
        kickDelayTimeout.attach_us(this, &Coilgun::kickDelayEnd, currentKickDelay);
    } else {
        kickDelayEnd();
    }
    
    if (currentChipDelay > 0) {
        chipDelayTimeout.attach_us(this, &Coilgun::chipDelayEnd, currentChipDelay);
    } else {
        chipDelayEnd();
    }
    
}

void Coilgun::kickDelayEnd(void) {
    kickDelayTimeout.detach();

    if (currentKickLength > 0) {
        kickPin = 1;
        kickTimeout.attach_us(this, &Coilgun::kickEnd, currentKickLength);
    } else {
        kickEnd();    
    }    
}

void Coilgun::kickEnd(void) {
    kickTimeout.detach();
    kickPin = 0;
    kickActive = false;

    if (!chipActive && state != discharging){ //Used when discharging 
        chargePin = 1; // autocharge
        state = idle; //(let state stay "discharging")
    }
}

void Coilgun::chipDelayEnd(void) {
    chipDelayTimeout.detach();
    
    if (currentChipLength > 0) {
        chipPin = 1;
        chipTimeout.attach_us(this, &Coilgun::chipEnd, currentChipLength);
    } else {
        chipEnd();    
    }  
}

void Coilgun::chipEnd(void) {
    chipTimeout.detach();
    chipPin = 0;
    chipActive = false;

    if (!kickActive && state != discharging){ //Used when discharging 
        chargePin = 1; // autocharge
        state = idle; //(let state stay "discharging")
    }
    
}

void Coilgun::charge() {
    changeState(charging);
    
    kickPin = 0;
    chipPin = 0;
    kickActive = false;
    chipActive = false;
    
    chargePin = 1; 
    isCharged = true;
}

void Coilgun::chargeEnd(){
    chargePin = 0;
    state = idle;
}

void Coilgun::discharge() {
    changeState(discharging);
    dischargeTimeout.attach(this, &Coilgun::dischargeEnd, 10.0); // End discharging after 10 seconds
    discharger.attach_us(this, &Coilgun::dischargeKick, 50000); // calls short kick every 50ms
    isCharged = false;
}

void Coilgun::dischargeEnd(void) {
    discharger.detach();
    state = idle;
}

void Coilgun::dischargeKick(void) {
    kick(200, 0, 0, 0, false);
}

void Coilgun::changeState(State new_state){
    switch(state){
        case idle:
            //nothing to end.
            break;
        case kicking:
            kickEnd();
            chipEnd();
            break;
        case charging:
            chargeEnd();
            break;
        case discharging:
            dischargeEnd();
            break;
        default:
            //error - no such state
            break;
    }
    //set new state
    state = new_state;
}