示例#1
0
void AudioSynthDigiFilter::update(void)
{
    audio_block_t *block, *modBlock;
    uint16_t baseFreq,envIn;
    int16_t modIn;
    uint8_t pot1value;
    block = receiveReadOnly(0);
    modBlock = receiveReadOnly(1);
    if (block)
    {
        if (modBlock)
        {
            //final frequency = baseFreq + envIn * envAmt + modIn * modAmt;
            //following implementation isn't correct yet: negative envIns aren't possible
            envIn = (block->data[64] * (envAmt)) >> 15;//32768 is the middle here, so we can have inverting and non in
            modIn = (modBlock->data[64] * modAmt) >> 15;
            baseFreq = freq;
            int32_t totalfreq = baseFreq + envIn + modIn;
            if(totalfreq > 65535) totalfreq = 65535;
            if(totalfreq < 0) totalfreq = 0;
            pot1value = totalfreq >> 8;
            outvalue = pot1value;
            digitalPotWrite(pot1value);
            release(modBlock);
        }
        release(block);
    }
}
void setup() {
  // set the slaveSelectPin as an output:
  pinMode (slaveSelectPin, OUTPUT);
  // initialize SPI:
  MIDI.begin();            	// Launch MIDI with default options--number is input channel number
  SPI.begin(); 

  //Initialize digiPot so it starts at 0
  for (int i=0; i<6; i++) {
    digitalPotWrite(i, 0);
  }


}
int matchResistance(int low, int high, int pin)
{
	int mid = (low + high) / 2;
	digitalPotWrite(0, mid);
	int voltage = analogRead(pin);
	if(low > high)
	{
		return mid;
	}
	if(voltage < 512)
	return matchResistance(low, mid - 1, pin);
	else if(voltage > 512)
	return matchResistance(mid + 1, high, pin);
	else
	return mid;
}
void loop() {
  if (MIDI.read()) {    // Is there a MIDI message incoming ?
    if (MIDI.getChannel() == 1) {    //filter so we only get messages coming on MIDI channel 1

        switch(MIDI.getType()) {		// Get the type of the message we caught

      case ControlChange:
        int tCCnum = MIDI.getData1(); //Get CC number
        int tCCval = MIDI.getData2(); //Get CC value

        if( tCCnum == AllNotesOff && tCCval == 0 ) { //Controller 123 sends AllOff
          for (int i=0; i<6; i++) {
            digitalPotWrite(i, 0);
          }

        } 

        if( tCCnum == 1 ) {
          digitalPotWrite(0, (tCCval*2));
        } 
        if( tCCnum == 2 ) {
          digitalPotWrite(1, (tCCval*2));
        } 
        if( tCCnum == 8 ) {
          digitalPotWrite(2, (tCCval*2));
        }
        if( tCCnum == 9 ) {
          digitalPotWrite(3, (tCCval*2));
        }
        if( tCCnum == 17 ) {
          digitalPotWrite(4, (tCCval*2));
        }
        if( tCCnum == 18 ) {
          digitalPotWrite(5, (tCCval*2));
        }
        break;


        //    default:
        break;
      }
    }
  }
}
void readChip()
{
	if(writeToSD)
	{
		String toWrite = "";
		if(!haveGPSData)
		{
			toWrite = "NO GPS DATA\t\t\t\t";
			LCD.appendString2File("Data", toWrite);
		}
		else if(haveGPSData)
			haveGPSData = false;
	}
	for(int i = 0; i < CHIP_PINS; ++i)
	{
		setMUX(i);
		int resistance = matchResistance(0, 255);
		long divider = (long) ((double) resistance / 255.0 * 100000.0);
		int bitVoltage = analogRead(0);
		//Read the voltage and calculate the resistance and percent delta
		digitalPotWrite(0, dividerBitResistance[i]);
		int bitVoltage = analogRead(i);
		double voltageOut = (double) bitVoltage / 1023.0 * REFERENCE_VOLTAGE;
		long currentResistance = (voltageOut * dividerResistance[i]) / (INPUT_VOLTAGE - voltageOut);
		
		double percentDelta = (double) (currentResistance - initialResistance[i]) / initialResistance[i];
		
		if(writeToSD)
		{
			String toWrite = (int) (percentDelta * 100);
			toWrite += ".";
			int decimalValue = ((int) absVal(percentDelta * 10000)) % 100;
			toWrite += decimalValue;
		
			LCD.appendString2File("Data", toWrite + "\t");
		}
		//Draw the rectangles if currently viewing chip
		if(deviceStatus == CHIP_VIEW)
		{
			//Get the coordinates of the rectangles based on the delta
			int rectLeft = (int) (RECT_WIDTH * i);
			int rectRight = (int) (rectLeft + RECT_WIDTH);
			int rectTop = BAR_MID;
			int rectBot = BAR_MID;
			long rectDelta = BAR_MID * percentDelta / PERCENT_SCALE;
			//Swap the top and bottom depending on if it goes up or down.
			if(percentDelta < 0)
				rectTop += absVal(rectDelta);
			else
				rectBot -= absVal(rectDelta);
			if(percentDelta != previousDelta[i])
			{
				if(i < 4 && viewOptions);
				else if(i > 11 && viewOptions)	//Don't draw over the button (limit height)
					LCD.rectangle(rectLeft, BUTTON_HEIGHT, rectRight, HEIGHT, BLACK);
				else
					LCD.rectangle(rectLeft, 0, rectRight, HEIGHT, BLACK);
				previousDelta[i] = percentDelta;
			}
			
			if(i < 4 && viewOptions);		//Don't draw at all
			else if(i > 11 && viewOptions)	//Don't draw over the button (limit height)
			{
				if(rectTop < BUTTON_HEIGHT)
					rectTop = BUTTON_HEIGHT;
				LCD.rectangle(rectLeft, rectTop, rectRight, rectBot, WHITE);
			}
			else 
				LCD.rectangle(rectLeft, rectTop, rectRight, rectBot, WHITE);
		}
	}
}
示例#6
0
/*----------------------------------------
*
* Start the massive Gcode processing loop
*-----------------------------------------
*/
void process_commands()
{
  int result;
  int motorChannel, motorPower;
  unsigned long codenum;
  char *starpos = NULL;
  
  if(code_seen('G'))
  {
    switch((int)code_value())
    {
    case 0: // G0 -> G1
    case 1: // G1
      break;
	  
    case 2:
	  break;
	  
    case 3:
	  break;
	  
    case 4: // G4 dwell
      //LCD_MESSAGEPGM(MSG_DWELL);
      codenum = 0;
      if(code_seen('P')) codenum = code_value(); // milliseconds to wait
      if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait

      //codenum += millis();  // keep track of when we started waiting
      previous_millis_cmd = 0;//millis();
      while(++previous_millis_cmd  < codenum ){
        manage_inactivity();
		_delay_ms(1);
      }
      break;
	  
	case 5: // G5 - Absolute command motor C<Channel> P<motor power -1000 to 1000>
	     if(!Stopped) {
		     if(code_seen('C')) {
				motorChannel = code_value(); // motor channel 1,2
				if(code_seen('P')) {
					motorPower = code_value(); // motor power -1000,1000
					fault = 0; // clear fault flag
					motorControl->commandMotorPower(motorChannel, motorPower);
				} // code P
			 } // code C
	     } // stopped
	     break;
		 
    case 28:
      previous_millis_cmd = 0;
      break;
	  
    case 90: // G90
      break;
	  
    case 91: // G91
      break;
	  
    case 92: // G92
      break;
	  
	case 99: // G99 start watchdog timer. G99 T<time_in_millis> values are 15,30,60,120,250,500,1000,4000,8000 default 4000
		if( code_seen('T') ) {
			int time_val = code_value();
			watchdog_timer = new WatchdogTimer();
			watchdog_timer->watchdog_init(time_val);
		}
		break;
		
	case 100: // G100 reset watchog timer before time interval is expired, otherwise a reset occurs
		if( watchdog_timer != NULL )
			watchdog_timer->watchdog_reset();
		break;
		
    } // switch
  } // if code
  /*-------------------------------------
  * M Code processing
  *--------------------------------------
  */
  else if(code_seen('M'))
  {
    switch( (int)code_value() )
    {
	case 0: // M0 Set real time output off
		realtime_output = 0;
		break;
		
	case 1: // M1 Set real time output on
		realtime_output = 1;
		break;
		
	case 2: // M2 [C<channel> E<encoder pin>] set smart controller (default) with optional encoder pin per channel
		motor_status = 0;
		motorControl = &roboteqDevice;
		if(code_seen('C')) {
			channel = code_value();
			if(code_seen('E')) {
				pin_number = code_value();
				motorControl->createEncoder(channel, pin_number);
			}
		}
		break;
		
	//Set PWM motor driver, map pin to channel, this will check to prevent free running motors during inactivity
	//For a PWM motor control subsequent G5 commands are affected here. 	
	case 3: // M3 P<pin> C<channel> D<direction pin> E<default dir> W<encoder pin> [T<timer mode 0-3>] [R<resolution 8,9,10 bits>] [X<prescale 0-7>]
	  motor_status = 1;
	  pin_number = -1;
	  encode_pin = 0;
	  motorControl = (AbstractMotorControl*)&hBridgeDriver;
	  ((HBridgeDriver*)motorControl)->setMotors((PWM**)&ppwms);
	  ((HBridgeDriver*)motorControl)->setDirectionPins((Digital**)&pdigitals);
	  if(code_seen('P'))
          pin_number = code_value();
	  else
		 break;
      if(code_seen('C')) {
        channel = code_value();
		if( code_seen('D'))
			dir_pin = code_value();
		else 
			break;
		if( code_seen('E'))
			dir_default = code_value();
		else
			break;
		if( code_seen('W')) 
			encode_pin = code_value(); 
		((HBridgeDriver*)motorControl)->createPWM(channel, pin_number, dir_pin, dir_default, timer_pre, timer_res);
		if(encode_pin)
			motorControl->createEncoder(channel, encode_pin);
      } // code C
	  break;
	
	case 4:
		// BLDC motor
		// BLDC: lo1,lo2,lo3,hi1,hi2,hi3,hall1,hall2,hall3,enable
		// hall sensors hall1:bit0,hall2:bit1,hall2:bit2 of commu array offset
		// BLDC3PhaseSensor* tmotor1 = new BLDC3PhaseSensor(29,31,33,8,9,10,64,65,66);
		// tmotor2 = new BLDC3PhaseSensor(35,37,39,11,12,13,67,68,69,30);
		// tmotor1->motor_init();
		// tmotor2->Motor_init();
		break;
		
	case 11: // M11 C<channel> D<duration> Set maximum motor cycle duration for given channel.
		if( code_seen('C') ) {
			channel = code_value();
			if( code_seen('D') )
				motorControl->setDuration(channel, code_value());
		}
	break;
	
	case 12: // M12 C<channel> P<offset> set amount to add to G5 for min motor power
		if( code_seen('C') ) {
			channel = code_value();
			if( code_seen('P'))
				motorControl->setMinMotorPower(channel, code_value());
		}
		break;
			 	
    case 17:
      break;
	  
	case 18: //M18
	  break;
	  
	case 31: //M31 take time since the start of the SD print or an M109 command
      stoptime=0;//millis();
      char time[30];
      t =(stoptime-starttime)/1000;
      int sec,min;
      min=t/60;
      sec=t%60;
      sprintf_P(time, PSTR("%i min, %i sec"), min, sec);
      SERIAL_PGMLN(timeCntrlHdr);
	  SERIAL_PGM("1 ");
      SERIAL_PORT.println(time);
	  SERIAL_PORT.flush();
      //lcd_setstatus(time);
      //autotempShutdown();
      break;
	  
	case 33: // M33 P<ultrasonic pin> D<min. distance in cm> [E<direction 1- forward facing, 0 - reverse facing sensor>] 
	// link Motor controller to ultrasonic sensor, the sensor must exist via M301
	  motor_status = 1;
	  pin_number = 0;
	  if(code_seen('P')) {
        pin_number = code_value();
		if( code_seen('D'))
			dist = code_value();
		else 
			break;
		dir_face = 1; // default forward
		if( code_seen('E'))
			dir_face = code_value(); // optional
		motorControl->linkDistanceSensor((Ultrasonic**)psonics, pin_number, dist, dir_face);
	  } // code_seen = 'P'
	  break;
	  
	  case 35: //M35 - Clear all digital pins
		for(int i = 0; i < 10; i++) {
			 if(pdigitals[i]) {
				unassignPin(pdigitals[i]->pin);
				delete pdigitals[i];
				pdigitals[i] = 0;
			 }
		}
	  break;
		  
	  case 36: //M36 - Clear all analog pins
		  	 for(int i = 0; i < 10; i++) {
			  	  if(panalogs[i]) {
					unassignPin(panalogs[i]->pin);
				  	delete panalogs[i];
					panalogs[i] = 0;
			  	  }
		  	 }
	  break;
	  
	  case 37: //M36 - Clear all PWM pins
	  for(int i = 0; i < 10; i++) {
		  if(ppwms[i]) {
			  unassignPin(ppwms[i]->pin);
			  delete ppwms[i];
			  ppwms[i] = 0;
		  }
	  }
	  break;
	  
	  case 38: //M38 - Remove PWM pin P<pin>
	  	  pin_number = -1;
	  	  if (code_seen('P')) {
		  	  pin_number = code_value();
		  	  if(unassignPin(pin_number) ) {
			  	  for(int i = 0; i < 10; i++) {
				  	  if(ppwms[i] && ppwms[i]->pin == pin_number) {
					  	  delete ppwms[i];
						  ppwms[i] = 0;
				  	  } // pwms == pin_number
			  	  } // i iterate pwm array
		  	  } // unassign pin
	  	  } // code P
	  break;
	  
	  case 39: //M39 - Remove Persistent Analog pin P<pin>
	  	  pin_number = -1;
	  	  if (code_seen('P')) {
		  	  pin_number = code_value();
		  	  if(unassignPin(pin_number) ) {
			  	  for(int i = 0; i < 10; i++) {
				  	  if(panalogs[i] && panalogs[i]->pin == pin_number) {
					  	delete panalogs[i];
						panalogs[i] = 0;
					    break;
				  	  }
			  	  }
		  	  }
	  	  }
	  break;
			
	  case 40: //M40 - Remove persistent digital pin P<pin>
	       pin_number = -1;
	       if (code_seen('P')) {
		       pin_number = code_value();
		       if(unassignPin(pin_number) ) {
			       for(int i = 0; i < 10; i++) {
				       if(pdigitals[i] && pdigitals[i] == pin_number) {
					       delete pdigitals[i];
						   pdigitals[i] = 0;
					       break;
				       }
			       }
			   }
		   }
	  break;
		
	  case 41: //M41 - Create persistent digital pin, Write digital pin HIGH P<pin> (this gives you a 5v source on pin)
	     pin_number = -1;
	     if (code_seen('P')) {
		     pin_number = code_value();
		     if( assignPin(pin_number) ) {
			     dpin = new Digital(pin_number);
				 dpin->setPin(pin_number);
			     dpin->pinMode(OUTPUT);
			     dpin->digitalWrite(HIGH);
			     for(int i = 0; i < 10; i++) {
				     if(!pdigitals[i]) {
					     pdigitals[i] = dpin;
					     break;
				     }
			     }
			 } else {
			     for(int i = 0; i < 10; i++) {
				     if(pdigitals[i] && pdigitals[i]->pin == pin_number) {
						 pdigitals[i]->setPin(pin_number);
						 pdigitals[i]->pinMode(OUTPUT);
					     pdigitals[i]->digitalWrite(HIGH);
					     break;
				     }
			     }
		     }
	     }
	break;
	     
    case 42: //M42 - Create persistent digital pin, Write digital pin LOW P<pin> (This gives you a grounded pin)
	  pin_number = -1;
	  if (code_seen('P')) {
        pin_number = code_value();
		if( assignPin(pin_number) ) {
			dpin = new Digital(pin_number);
			dpin->pinMode(OUTPUT);
			dpin->digitalWrite(LOW);
			for(int i = 0; i < 10; i++) {
				if(!pdigitals[i]) {
					pdigitals[i] = dpin;
					break;
				}
			}
		} else {
			for(int i = 0; i < 10; i++) {
				if(pdigitals[i] && pdigitals[i]->pin == pin_number) {
					pdigitals[i]->setPin(pin_number);
					pdigitals[i]->pinMode(OUTPUT);
					pdigitals[i]->digitalWrite(LOW);
					break;
				}
			}
		}
	  }
     break;
	 
	case 43: // M43 Read from digital pin P<pin>
        pin_number = -1;
        if (code_seen('P'))
          pin_number = code_value();
   		if( assignPin(pin_number) ) {
			dpin = new Digital(pin_number);
			dpin->pinMode(INPUT);
			int res = dpin->digitalRead();
			delete &dpin;
			unassignPin(pin_number); // reset it since this is a one-shot
			SERIAL_PGMLN(digitalPinHdr);
			SERIAL_PGM("1 ");
			SERIAL_PORT.println(pin_number);
			SERIAL_PGM("2 ");
			SERIAL_PORT.println(res);
			SERIAL_PORT.println();
			SERIAL_PORT.flush();
		}
		break;
	
	case 44: // M44 -Read digital pin with pullup P<pin>
        pin_number = -1;
        if (code_seen('P'))
          pin_number = code_value();
    	if( assignPin(pin_number) ) {
			dpin = new Digital(pin_number);
			dpin->pinMode(INPUT_PULLUP);
			int res = dpin->digitalRead();
			delete &dpin;
			unassignPin(pin_number); // reset it since this is a one-shot
			SERIAL_PGMLN(digitalPinHdr);
			SERIAL_PGM("1 ");
			SERIAL_PORT.println(pin_number);
			SERIAL_PGM("2 ");
			SERIAL_PORT.println(res);
			SERIAL_PORT.flush();
		}
		break;
		
	 // PWM value between 0 and 255, default timer mode is 2; clear on match, default resolution is 8 bits, default prescale is 1
	 // Prescale: 1,2,4,6,7,8,9 = none, 8, 64, 256, 1024, external falling, external rising
	 // Use M445 to disable pin permanently or use timer more 0 to stop pulse without removing pin assignment
     case 45: // M45 - set up PWM P<pin> S<power val 0-255> [T<timer mode 0-3>] [R<resolution 8,9,10 bits>] [X<prescale 0-7>]
	  pin_number = -1;
	  if(code_seen('P') )
          pin_number = code_value();
	  else
		 break;
      if (code_seen('S')) {
        int pin_status = code_value();
		int timer_mode = 2;
		int timer_res = 8;
		int timer_pre = 1;
		
		if( pin_status < 0 || pin_status > 255)
			pin_status = 0;
		// this is a semi-permanent pin assignment so dont add if its already assigned
		if( assignPin(pin_number) ) {
			// timer mode 0-3: 0 stop, 1 toggle on compare match, 2 clear on match, 3 set on match (see HardwareTimer)
			if( code_seen('T') ) {
				timer_mode = code_value();
				if( timer_mode < 0 || timer_mode > 3 )
					timer_mode = 0;
			}
			// timer bit resolution 8,9, or 10 bits
			if( code_seen('R')) {
				timer_res = code_value();
				if( timer_res < 8 || timer_res > 10 )
					timer_res = 8;
			}
			// X - prescale 0-7 for power of 2
			if( code_seen('X') ) {
				timer_pre = code_value();
				if( timer_pre < 0 || timer_pre > 7 )
					timer_pre = 0;
			}
			for(int i = 0; i < 10; i++) {
				if(ppwms[i] == NULL) {
					ppin = new PWM(pin_number);
					ppin->init(pin_number);
					ppin->setPWMPrescale(timer_pre);
					ppin->setPWMResolution(timer_res);
					ppin->pwmWrite(pin_status,timer_mode); // default is 2, clear on match. to turn off, use 0
					ppwms[i] = ppin;
					break;
				}
			}
		 } else { // reassign pin with new mode and value
			 for(int i = 0; i < 10; i++) {
				 if(ppwms[i] && ppwms[i]->pin == pin_number) {
					 // timer mode 0-3: 0 stop, 1 toggle on compare match, 2 clear on match, 3 set on match (see HardwareTimer)
					 if( code_seen('T') ) {
						 timer_mode = code_value();
						 if( timer_mode < 0 || timer_mode > 3 )
							timer_mode = 2; // mess up the code get clear on match default
					 }
					 //ppwms[i]->init();
					 ppwms[i]->pwmWrite(pin_status, timer_mode);
					 break;
				 }
			 }
		 }
      }
	  break;
	  
	  case 46: // M46 -Read analog pin P<pin>
        pin_number = -1;
        if (code_seen('P'))
          pin_number = code_value();
		if( assignPin(pin_number) ) {
			apin = new Analog(pin_number);
			int res = apin->analogRead();
			res = apin->analogRead(); // de-jitter
			delete &apin;
			unassignPin(pin_number);
			SERIAL_PGMLN(analogPinHdr);
			SERIAL_PGM("1 ");
			SERIAL_PORT.println(pin_number);
			SERIAL_PGM("2 ");
			SERIAL_PORT.println(res);
			SERIAL_PORT.flush();
		}
     break;
	 
     case 80: // M80 - Turn on Power Supply
	  #if defined(PS_ON_PIN) && PS_ON_PIN > -1
        SET_OUTPUT(PS_ON_PIN); //GND
        WRITE(PS_ON_PIN, PS_ON_AWAKE);
        // If you have a switch on suicide pin, this is useful
        #if defined(SUICIDE_PIN) && SUICIDE_PIN > -1
            SET_OUTPUT(SUICIDE_PIN);
            WRITE(SUICIDE_PIN, HIGH);
        #endif
      #endif
	  break;

     case 81: // M81 - Turn off Power
      if( motorControl->isConnected())
		motorControl->commandEmergencyStop();
      #if defined(SUICIDE_PIN) && SUICIDE_PIN > -1
        suicide();
      #elif defined(PS_ON_PIN) && PS_ON_PIN > -1
        SET_OUTPUT(PS_ON_PIN);
        WRITE(PS_ON_PIN, PS_ON_ASLEEP);
      #endif
	    _delay_ms(1000); // Wait 1 sec before switch off
	  break;

    case 82:
      break;
	  
    case 83:
      break;
	  
    case 84: // M84
      break;
	  
    case 85: // M85
      break;
	  
    case 92: // M92
      break;
	  
	case 104: // M104
      break;
	  
    case 105 : // M105
      SERIAL_PORT.println();
      break; 
	   
    case 106: //M106
        break;
		
    case 107: //M107
        break;
	
    case 109: // M109 
      break;
	  
    case 115: // M115
      SERIAL_PGMLN(MSG_M115_REPORT);
      break;
	  
    case 117: 
      break;
	  
    case 114: // M114
      break;
	  
    case 120: // M120
      break;
	  
    case 121: // M121
      break;
	  
    case 119: // M119
      break; 
	  
	case 140: // M140 
      break;
	  
    case 150: // M150 - set an RGB value
        byte red;
        byte grn;
        byte blu;
        if(code_seen('R')) red = code_value();
        if(code_seen('U')) grn = code_value();
        if(code_seen('B')) blu = code_value();
        //SendColors(red,grn,blu);
      break;
	  
	case 190: // M190
      break;
	  
    case 200:
      break;
	  
    case 201: // M201
      //reset_acceleration_rates();
      break;
	  
    case 202: // M202
      break;
	  
    case 203:
      break;
	  
    case 204: // M204 acceleration T
      if(code_seen('T')) ;//max_acceleration = code_value();
      break;
	  
    case 205: //M205 advanced settings:  maximum travel speed T=travel
      if(code_seen('T')) ;//maxtravelspeed = code_value();
	  break;
	
    case 206: 
      break;
	  
    case 207:
	  break;
	  
    case 208:
      break;
	  
    case 209: 
	  break;
	  
    case 218:
	  break;
	  
    case 220: 
      if(code_seen('S'))
      {
        
      }
    break;
	
    case 221: 
      if(code_seen('S'))
      {
        
      }
    break;

	case 226: // M226 P<pin number> S<pin state>- Wait until the specified pin reaches the state required, default is opposite current state
      if(code_seen('P')) {
        int pin_number = code_value(); // pin number
        int pin_state = -1; // required pin state - default is inverted
        if(code_seen('S')) 
			pin_state = code_value(); // required pin state
		if( assignPin(pin_number) ) {
			Digital pn = new Digital(pin_number);
            pn.pinMode(INPUT);
            int target;
            switch(pin_state){
				case 1:
					target = HIGH;
					break;
				case 0:
					target = LOW;
					break;
				default:
					target = !pn.digitalRead(); // opposite of current state
					break;
            } // switch
            while(pn.digitalRead() != target) {
              manage_inactivity();
            } // while
			delete &pn;
			unassignPin(pin_number);
          } // if pin_number
      } // code seen p
    break;

	case 227: // M227 P<pin number> S<pin state>- INPUT_PULLUP Wait until the specified pin reaches the state required, default is opposite current state
	if(code_seen('P')) {
		int pin_number = code_value(); // pin number
		int pin_state = -1; // required pin state - default is inverted
		if(code_seen('S'))
		pin_state = code_value(); // required pin state
		if( assignPin(pin_number) ) {
			Digital pn = new Digital(pin_number);
			pn.pinMode(INPUT_PULLUP);
			int target;
			switch(pin_state){
				case 1:
				target = HIGH;
				break;
				case 0:
				target = LOW;
				break;
				default:
				target = !pn.digitalRead(); // opposite of current state
				break;
			} // switch
			while(pn.digitalRead() != target) {
				manage_inactivity();
			} // while
			delete &pn;
			unassignPin(pin_number);
		} // if pin_number
	} // code seen p
	break;
		
	case 240: // M240  Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/
	/*
      #if defined(PHOTOGRAPH_PIN) && PHOTOGRAPH_PIN > -1
        const uint8_t NUM_PULSES=16;
        const float PULSE_LENGTH=0.01524;
        for(int i=0; i < NUM_PULSES; i++) {
          WRITE(PHOTOGRAPH_PIN, HIGH);
          _delay_ms(PULSE_LENGTH);
          WRITE(PHOTOGRAPH_PIN, LOW);
          _delay_ms(PULSE_LENGTH);
        }
        delay(7.33);
        for(int i=0; i < NUM_PULSES; i++) {
          WRITE(PHOTOGRAPH_PIN, HIGH);
          _delay_ms(PULSE_LENGTH);
          WRITE(PHOTOGRAPH_PIN, LOW);
          _delay_ms(PULSE_LENGTH);
        }
      #endif
	  */
    break;
	
	case 250: 
      break;
	
    case 280: 
      break;

    case 300: // M300 - emit ultrasonic pulse on given pin and return duration P<pin number>
      uspin = code_seen('P') ? code_value() : 0;
      if (uspin > 0) {
		Ultrasonic* upin = new Ultrasonic(uspin);
		pin_number = upin->getPin();
		SERIAL_PGMLN(sonicCntrlHdr);
		SERIAL_PGM("1 "); // pin
		SERIAL_PORT.println(pin_number);
		SERIAL_PGM("2 "); // sequence
		SERIAL_PORT.println(upin->getRange()); // range
		delete upin;
      }
    break;
		
    case 301: // M301 - toggle ultrasonic during inactivity P<pin>
		// wont assign pin 0 as its sensitive
		uspin = code_seen('P') ? code_value() : 0;
		// this is a permanent pin assignment so dont add if its already assigned
		if( assignPin(uspin) ) {
			for(int i = 0; i < 10; i++) {
				if(!psonics[i]) {
					psonics[i] = new Ultrasonic(uspin);
					break;
				}
			}
		}
		break;
	
	case 302: // M302 - disable ultrasonic during inactivity P<pin>
		uspin = code_seen('P') ? code_value() : 0;
		unassignPin(uspin);
		for(int i = 0; i < 10; i++) {
				if(psonics[i] && psonics[i] == uspin) {
					delete psonics[i];
					psonics[i] = 0;
					break;
				}
		}
      break;
	
	case 303: // M303 - toggle analog read during inactivity P<pin> with exclusion range 0-1024 via L<min> H<max> if present
		// wont assign pin 0 as its sensitive
		// if optional L and H values exclude readings in that range
		uspin = code_seen('P') ? code_value() : 0;
		// this is a permanent pin assignment so dont add if its already assigned
		if( assignPin(uspin) ) {
			for(int i = 0; i < 10; i++) {
				if(!panalogs[i]) {
					analogRanges[0][i] = code_seen('L') ? code_value() : 0;
					analogRanges[1][i] = code_seen('H') ? code_value() : 0;
					panalogs[i] = new Analog(uspin);
					panalogs[i]->pinMode(INPUT);
					break;
				}
			}
		} else { // reassign values for assigned pin
			for(int i = 0; i < 10; i++) {
				if(panalogs[i] && panalogs[i]->pin == uspin) {
					analogRanges[0][i] = code_seen('L') ? code_value() : 0;
					analogRanges[1][i] = code_seen('H') ? code_value() : 0;
					break;
				}
			}
		}
      break;
	  
	case 304:// M304 - toggle analog read INPUT_PULLUP during inactivity P<pin> with exclusion range 0-1024 via L<min> H<max> if present
		// if optional L and H values exclude readings in that range
		uspin = code_seen('P') ? code_value() : 0;
		// this is a permanent pin assignment so dont add if its already assigned
		if( assignPin(uspin) ) {
			for(int i = 0; i < 10; i++) {
				if(!panalogs[i]) {
					analogRanges[0][i] = code_seen('L') ? code_value() : 0;
					analogRanges[1][i] = code_seen('H') ? code_value() : 0;
					panalogs[i] = new Analog(uspin);
					panalogs[i]->pinMode(INPUT_PULLUP);
					break;
				}
			}
		} else { // reassign values for assigned pin
			for(int i = 0; i < 10; i++) {
				if(panalogs[i] && panalogs[i]->pin == uspin) {
					analogRanges[0][i] = code_seen('L') ? code_value() : 0;
					analogRanges[1][i] = code_seen('H') ? code_value() : 0;
					break;
				}
			}
		}
      break;
	
	case 305: // M305 - toggle digital read during inactivity M305 P<pin> T<target> 0 or 1 for target value, default 0
		// wont assign pin 0 as its sensitive
		// Looks for target value for pin during inactive, if so publish with <digitalpin> header and 1 - pin, 2 - value
		uspin = code_seen('P') ? code_value() : 0;
		digitarg = code_seen('T') ? code_value() : 0;
		// this is a permanent pin assignment so dont add if its already assigned
		if( assignPin(uspin) ) {
			for(int i = 0; i < 10; i++) {
				if(!pdigitals[i]) {
					pdigitals[i] = new Digital(uspin);
					pdigitals[i]->pinMode(INPUT);
					digitalTarget[i] = digitarg;
					break;
				}
			}
		} else {
			for(int i = 0; i < 10; i++) {
				if(pdigitals[i] && pdigitals[i]->pin == uspin) {
					digitalTarget[i] = digitarg;
					break;
				}
			}
		}
      break;
	
	case 306:// M306 - INPUT_PULLUP toggle digital read during inactivity M306 P<pin> T<target> 0 or 1 for target value, default 0
		// Looks for target value for pin during inactive, if so publish with <digitalpin> header and 1 - pin 2 - value
		uspin = code_seen('P') ? code_value() : 0;
		digitarg = code_seen('T') ? code_value() : 0;
		// this is a permanent pin assignment so dont add if its already assigned
		if( assignPin(uspin) ) {
			for(int i = 0; i < 10; i++) {
				if(!pdigitals[i]) {
					pdigitals[i] = new Digital(uspin);
					pdigitals[i]->pinMode(INPUT_PULLUP);
					digitalTarget[i] = digitarg;
					break;
				}
			}
		} else {
			for(int i = 0; i < 10; i++) {
				if(pdigitals[i] && pdigitals[i]->pin == uspin) {
					digitalTarget[i] = digitarg;
					break;
				}
			}
		}
		break;
	
    case 349: // M349
	/*
        if(code_seen('P')) bedKp = code_value();
        if(code_seen('I')) bedKi = scalePID_i(code_value());
        if(code_seen('D')) bedKd = scalePID_d(code_value());

        updatePID();
        SERIAL_PROTOCOL(MSG_OK);
        SERIAL_PROTOCOL(" p:");
        SERIAL_PROTOCOL(bedKp);
        SERIAL_PROTOCOL(" i:");
        SERIAL_PROTOCOL(unscalePID_i(bedKi));
        SERIAL_PROTOCOL(" d:");
        SERIAL_PROTOCOL(unscalePID_d(bedKd));
        SERIAL_PROTOCOLLN("");
		*/
      break;
	  
   case 350:
    break;
	
   case 351: 
      break;
	  
    case 400:
      
    break;
	
    case 401:
        
    break;
	
    case 402:
        
    break;
	
	case 444: // M444 - set battery warning threshold V<volts*10>!!!!!!!!!!!!!!!!!! REMEMBER ITS TIMES 10 !!!!!!!!!!!!!!!!!!
	    if(code_seen('V')) {
			BatteryThreshold = code_value(); // times 10!!!
		}
		break;
		
	case 445: // M445 - Turn off pulsed write pin - disable PWM P<pin>
      pin_number = -1;
      if (code_seen('P'))
          pin_number = code_value();
	  unassignPin(pin_number);
	  for(int i = 0; i < 10; i++) {
			if(ppwms[i] && ppwms[i] == pin_number) {
				ppwms[i]->pwmWrite(0,0); // default is 2, clear on match. to turn off, use 0 
				delete ppwms[i];
				ppwms[i] = 0;
				break;
			}
	  }
	  break;
	  
    case 500: // M500 Store settings in EEPROM
        Config_StoreSettings();
    break;
	
    case 501: // M501 Read settings from EEPROM
        Config_RetrieveSettings();
    break;
	
    case 502: // M502 Revert to default settings
        Config_ResetDefault();
    break;
	
    case 503: // M503 print settings currently in memory
        Config_PrintSettings();
    break;
	
    case 540:
        //if(code_seen('S')) abort_on_endstop_hit = code_value() > 0;
    break;
	
    case 600: 
    break;
	
    case 605: 
    break;
	
	case 666:
    break;
	  
	case 700: // return stats
	  // Check startup - does nothing if bootloader sets MCUSR to 0
	  mcu = MCUSR;
	  if(mcu & 1) SERIAL_PGMLN(MSG_POWERUP);
	  if(mcu & 2) SERIAL_PGMLN(MSG_EXTERNAL_RESET);
	  if(mcu & 4) SERIAL_PGMLN(MSG_BROWNOUT_RESET);
	  if(mcu & 8) SERIAL_PGMLN(MSG_WATCHDOG_RESET);
	  if(mcu & 32) SERIAL_PGMLN(MSG_SOFTWARE_RESET);
	  MCUSR=0;
	  SERIAL_PGM(VERSION_STRING);
	  #ifdef STRING_VERSION_CONFIG_H
	  #ifdef STRING_CONFIG_H_AUTHOR
	  SERIAL_PGM(MSG_CONFIGURATION_VER);
	  SERIAL_PGM(STRING_VERSION_CONFIG_H);
	  SERIAL_PGM(MSG_AUTHOR);
	  SERIAL_PGMLN(STRING_CONFIG_H_AUTHOR);
	  SERIAL_PGM("Compiled: ");
	  SERIAL_PGM(__DATE__);
	  #endif
	  #endif
	  SERIAL_PGM(MSG_FREE_MEMORY);
	  SERIAL_PORT.println(freeMemory());
	  SERIAL_PORT.flush();
	  break; 
	  
	case 701: // Report digital pins in use
		SERIAL_PGMLN("Digital Pins:");
		for(int i = 0; i < 10; i++) {
			if( pdigitals[i] ) {
				SERIAL_PORT.print(pdigitals[i]->pin);
				switch(pdigitals[i]->mode) {
					case INPUT:
						SERIAL_PGMLN(" INPUT");
						break;
					case INPUT_PULLUP:
						SERIAL_PGMLN(" INPUT_PULLUP");
						break;
					case OUTPUT:
						SERIAL_PGMLN(" OUTPUT");
						break;
				}
			}
		}
		SERIAL_PORT.println();
		SERIAL_PORT.flush();
		break;
		
	case 702: // Report analog pins in use
		SERIAL_PGMLN("Analog Pins:");
		for(int i = 0; i < 10; i++) {
			if( panalogs[i]  ) {
				SERIAL_PORT.print(panalogs[i]->pin);
				switch(panalogs[i]->mode) {
					case INPUT:
					SERIAL_PGMLN(" INPUT");
					break;
					case INPUT_PULLUP:
					SERIAL_PGMLN(" INPUT_PULLUP");
					break;
					case OUTPUT:
					SERIAL_PGMLN(" OUTPUT");
					break;
				}
			}
		}
		SERIAL_PORT.println();
		SERIAL_PORT.flush();
		break;
		
	case 703: // Report ultrasonic pins in use
		SERIAL_PGMLN("Ultrasonic Pins:");
		for(int i = 0; i < 10; i++) {
			if( psonics[i] ) {
				SERIAL_PGM("Pin:");
				SERIAL_PORT.println(psonics[i]->getPin());
			}
		}
		SERIAL_PORT.flush();
		break;
		
	case 704: // Report PWM pins in use
		SERIAL_PGMLN("PWM Pins:");
		for(int i = 0; i < 10; i++) {
			if( ppwms[i] ) {
				SERIAL_PGM("Pin:");
				SERIAL_PORT.print(ppwms[i]->pin);
				SERIAL_PGM(" Timer channel:");
				SERIAL_PORT.print(ppwms[i]->channel);
				switch(ppwms[i]->mode) {
					case INPUT:
						SERIAL_PGM(" INPUT");
						break;
					case INPUT_PULLUP:
						SERIAL_PGM(" INPUT_PULLUP");
						break;
					case OUTPUT:
						SERIAL_PGM(" OUTPUT");
						break;
				}
				SERIAL_PORT.println();
			}
			SERIAL_PORT.flush();
		}
		break;
		
	case 705:
			// see if it has propulsion attributes declared with M3 as interrupt serviced
			switch(motor_status) {
				case 0:
					SERIAL_PGMLN("Multi Channel Motor Controller:");
					break;
				case 1:
					SERIAL_PGMLN("H-Bridge Brushed DC Motor Driver(s):");
					break;
				case 2:
					SERIAL_PGMLN("Brushless DC Motor Driver(s):");
					break;
			}
			for(int i = 0 ; i < motorControl->getChannels(); i++) { //per channel
					SERIAL_PGM("Motor channel:");
					SERIAL_PORT.print(i+1);
					SERIAL_PGM(" Min Power:");
					SERIAL_PORT.print(motorControl->getMinMotorPower(i+1));
					SERIAL_PGM(" Speed:");
					SERIAL_PORT.print(motorControl->getMotorSpeed(i+1));
					SERIAL_PGM(" Curr. Dir:");
					SERIAL_PORT.print(motorControl->getCurrentDirection(i+1));
					SERIAL_PGM(" Default. Dir:");
					SERIAL_PORT.println(motorControl->getDefaultDirection(i+1));
					SERIAL_PGM(" Encoder Pin:");
					if(motorControl->getWheelEncoder(i+1)) {
						SERIAL_PORT.print(motorControl->getWheelEncoder(i+1)->pin);
						SERIAL_PGM(" Count:");
						SERIAL_PORT.print(motorControl->getEncoderCount(i+1));
						SERIAL_PGM(" Duration:");
						SERIAL_PORT.println(motorControl->getMaxMotorDuration(i+1));
					} else {
						SERIAL_PGMLN("None.");
					}
			}
			SERIAL_PGM("Ultrasonic pins:");
			if( motorControl->totalUltrasonics() ) {
				SERIAL_PORT.println(motorControl->totalUltrasonics());
				for(int j = 0; j < motorControl->totalUltrasonics(); j++) {
					SERIAL_PGM("Pin:");
					SERIAL_PORT.print(psonics[motorControl->getUltrasonicIndex(i+1)]->getPin());
					SERIAL_PGM(" Facing:");
					SERIAL_PORT.print(motorControl->getUltrasonicFacing(i+1));
					SERIAL_PGM(" Shutdown cm:");
					SERIAL_PORT.println(motorControl->getMinMotorDist(i+1));
				}
			} else {
						SERIAL_PGMLN("None.");
			}
			SERIAL_PORT.flush();
			break;
			
	case 706: // Report all pins in use
		for(int i = 0; i < 100; i++) {
			if( pinAssignment(i) == PIN_ASSIGNED ) {
				SERIAL_PORT.print(i);
				SERIAL_PORT.print(',');
			}
		}
		SERIAL_PORT.println();
		SERIAL_PORT.flush();
		break;
		
	case 797:
		break;
		
	case 798: // Report controller status
		//SERIAL_PGMLN(motorCntrlHdr);
		if( motorControl->isConnected() ) {
			for(int i = 0; i < motorControl->getChannels() ; i++ ) {
				SERIAL_PGM("Motor Channel:");
				SERIAL_PORT.println(i+1);
				char* buf = motorControl->getDriverInfo(i+1);
				while(*buf) {
					SERIAL_PORT.print(*buf);
					buf++;
				}
			}
		}
		SERIAL_PORT.println();
		SERIAL_PORT.flush();
		break;	
		
	case 799: // Reset Motor controller
		motorControl->commandEmergencyStop();
		break;		
		
	case 800: 
		break;
		
	case 801: // IMU
		prh = new PitchRollHeading();
		orient = prh->getPitchRollHeading();
		SERIAL_PGMLN(posCntrlHdr);
		SERIAL_PGM("1 ");
		SERIAL_PORT.println(orient.pitch);
		SERIAL_PGM("2 ");
		SERIAL_PORT.println(orient.roll);
		SERIAL_PGM("3 ");
		SERIAL_PORT.println(orient.heading);
		break;	
			
	case 802: // Acquire analog pin data M802 Pnn Sxxx Mxxx P=Pin number, S=number readings, M=microseconds per reading. X - pullup.
		// Publish <dataset> 1 - pin, 2 - reading
		if( code_seen('P')) {
			apin = new Analog((uint8_t)code_value());
			if( code_seen('X') )
				apin->pinMode(INPUT_PULLUP);
			else
				apin->pinMode(INPUT);
		}
		nread = 0;
		if( code_seen('S') ) {
			nread = code_value();
		}
		micros = 0;
		if( code_seen('M')) {
			micros = (uint32_t)code_value();
		}
		values = new int(nread);
		for(int i = 0; i < nread; i++) {
			*(values+i) = apin->analogRead();
			for(int j = 0; j < micros; j++) _delay_us(1);
		}
		SERIAL_PGMLN(datasetHdr);
		SERIAL_PORT.println();
		for(int i = 0; i < nread; i++) {
			SERIAL_PORT.print(i+1); // sequence
			SERIAL_PORT.print(' ');
			// 0 element is pin number
			if( i == 0 )
				SERIAL_PORT.println(apin->pin);
			else
				SERIAL_PORT.println(*(values+i)); // value
		}
		delete values;
		SERIAL_PORT.println();
		SERIAL_PORT.flush();
		break;	
		
	case 803:
		break;	
		
	case 907: 
		break; 
		 
	case 908: // M908 Control digital trimpot directly.
		uint8_t current;
		if(code_seen('P')) channel=code_value();
		if(code_seen('S')) current=code_value();
		digitalPotWrite(channel, current);
		break;
		
    case 999: // M999: Reset
		Stopped = false;
		//lcd_reset_alert_level();
		gcode_LastN = Stopped_gcode_LastN;
		//FlushSerialRequestResend();
		if( watchdog_timer != NULL )
			delete watchdog_timer;
		watchdog_timer = new WatchdogTimer();
		watchdog_timer->watchdog_init(15); // 15 ms
	
  } // switch m code

  } else { // if M code
    SERIAL_PGMLN(MSG_UNKNOWN_COMMAND);
    //SERIAL_PORT.println(cmdbuffer[bufindr]);
  }

}
int main() {

        led1 = led2 = led3 = led4 = false;
        
        
        //Initialize Buttons
        ABut      = BBut        = XBut        = YBut         = 
        LBBut     = RBBut       = LSCBut      = RSCBut       = 
        GuideBut  = StartBut    = BackBut     = SyncBut      = 
        DpadUpBut = DpadDownBut = DpadLeftBut = DpadRightBut = 0;

        
        //Turn IC off
        cs = 1;

        //Initialize Serial Port 
        pc.baud(115200);
        //Initialize SPI Connection
        jst.format(8,0);
        jst.frequency(100000);        
        
        // Declare Buffer for Serial Input and Count Variable
        int buffer[23];
        int i;
        
        
        while(1)
        {

            //If Serial Port is Readable
            if (pc.readable() == 1){
                
                //Store Serial Data in Buffer
                for (i= 0; i < 23; i++){
                    buffer[i] = (int)pc.getc();
                }

                
/*[0] AccelX   */   /* Unused */
/*[1] AccelY   */   /* Unused */
/*[2] AccelZ   */   /* Unused */
/*[3] nunAccX  */   /* Unused */
/*[4] nunAccY  */   /* Unused */
/*[5] nunAccZ  */   if ((int)buffer[5] < 128)RBBut = true;else{ RBBut = false;}
/*[6] JoyX     */   digitalPotWrite         (0, 255-(int)buffer[6]);
/*[7] JoyY     */   digitalPotWrite             (1, (int)buffer[7]);
/*[8] A        */   ABut        =             (int)(bool) buffer[8];
/*[9] B        */   digitalPotWrite (5, (int)((bool)buffer[9])*250);
/*[10] One     */   StartBut    =             (int)(bool)buffer[10];
/*[11] Two     */   DpadDownBut =             (int)(bool)buffer[11];
/*[12] Up      */   BBut        =             (int)(bool)buffer[12];
/*[13] Down    */   LSCBut      =             (int)(bool)buffer[13];
/*[14] Left    */   YBut        =             (int)(bool)buffer[14];  /* Address | Controller  */
/*[15] Right   */   XBut        =             (int)(bool)buffer[15];  /*      0       LSX      */
/*[16] Plus    */   RSCBut      =             (int)(bool)buffer[16];  /*      1       LSY      */
/*[17] Minus   */   BackBut     =             (int)(bool)buffer[17];  /*      2       LT       */
/*[18] Home    */   GuideBut    =             (int)(bool)buffer[18];  /*      3       RSX      */
/*[19] C       */   digitalPotWrite (2,(int)((bool)buffer[19])*250);  /*      4       RSY      */
/*[20] Z       */   LBBut       =             (int)(bool)buffer[20];  /*      5       RT       */
/*[21] xIR     */   digitalPotWrite             (3,(int)buffer[21]); 
/*[22] yIR     */   digitalPotWrite         (4,255-(int)buffer[22]);                             
                                

                }
                  
                  
                  if ( buffer[6] < 128){
                        led1 = true;}
                  if ( buffer[6] >= 128){
                        led1 = false;  }    
                  if ( buffer[7] < 128){
                        led2 = true;}
                  if ( buffer[7] >= 128){
                        led2 = false;  }                           
                  if ( buffer[21] < 128){
                        led3 = true;}
                  if ( buffer[21] >= 128){
                        led3 = false;  }
                  if ( buffer[22] < 128){
                        led4 = true;}
                  if ( buffer[22] >= 128){
                        led4 = false;  }               
        }
}