<commit_before>#include "MPU9150.h"
#include "AConfig.h"
#if(HAS_MPU9150)
#include "Device.h"
#include "Settings.h"
#include <Wire.h>
//#include "I2Cdev.h"
#include "MPU9150Lib.h"
#include "CalLib.h"
//#include "dmpKey.h"
//#include "dmpmap.h"
//#include "inv_mpu.h"
//#include "inv_mpu_dmp_motion_driver.h"
#include <EEPROM.h>
#include "Timer.h"

MPU9150Lib MPU;                                              // the MPU object
int MPUDeviceId = 1;
boolean DidInit = false;
boolean InCallibrationMode = false;
Timer MPU9150ReInit;
Timer mpu_update_timer;
CALLIB_DATA calData;
Timer calibration_timer;
int counter = 0;
//  MPU_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the sensor data and DMP output

//  MPU_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the sensor data and DMP output

#define MPU_UPDATE_RATE  (20)

//  MAG_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the magnetometer data
//  MAG_UPDATE_RATE should be less than or equal to the MPU_UPDATE_RATE

#define MAG_UPDATE_RATE  (10)

//  MPU_MAG_MIX defines the influence that the magnetometer has on the yaw output.
//  The magnetometer itself is quite noisy so some mixing with the gyro yaw can help
//  significantly. Some example values are defined below:

#define  MPU_MAG_MIX_GYRO_ONLY          0                   // just use gyro yaw
#define  MPU_MAG_MIX_MAG_ONLY           1                   // just use magnetometer and no gyro yaw
#define  MPU_MAG_MIX_GYRO_AND_MAG       10                  // a good mix value
#define  MPU_MAG_MIX_GYRO_AND_SOME_MAG  50                  // mainly gyros with a bit of mag correction

//  MPU_LPF_RATE is the low pas filter rate and can be between 5 and 188Hz

#define MPU_LPF_RATE   5

void MPU9150::device_setup(){
  //Todo: Read calibration values from EPROM
  Wire.begin();
  MPU.selectDevice(MPUDeviceId);
  if (!MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_ONLY, MAG_UPDATE_RATE, MPU_LPF_RATE)){
  	Serial.println(F("log:Trying other MPU9150 address to init;"));
  	Serial.print(F("log:IMU Address was :"));
  	Serial.print(1);
  	MPUDeviceId = !MPUDeviceId;
  	Serial.print(F(" but is now:"));
  	Serial.print(MPUDeviceId);
  	Serial.println(";");
  	MPU.selectDevice(MPUDeviceId);
  	if (MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_ONLY, MAG_UPDATE_RATE, MPU_LPF_RATE)){
  		DidInit = true;
  		Serial.println(F("log:Init worked the second time;"));
  	} else {
  		Serial.println(F("log:Failed to init on both addresses;"));
  	}
  } else {
  	DidInit = true;
  	Serial.println(F("log:init on primary addresses;"));
  }                             // start the MPU
  Settings::capability_bitarray |= (1 << COMPASS_CAPABLE);
  Settings::capability_bitarray |= (1 << ORIENTATION_CAPABLE);
  MPU9150ReInit.reset();
  mpu_update_timer.reset();
}

void MPU9150::device_loop(Command command){
  if (!DidInit){
    if( MPU9150ReInit.elapsed(30000)){
	MPU9150::device_setup();
    }
     return;
  }
  if (command.cmp("ccal")){
   // Compass_Calibrate();
   // The IMU needs both Magnatrometer and Acceleromter to be calibrated. This attempts to do them both at the same time
    calLibRead(MPUDeviceId, &calData);               // pick up existing accel data if there

    calData.accelValid = false;
    calData.accelMinX = 0x7fff;                              // init accel cal data
    calData.accelMaxX = 0x8000;
    calData.accelMinY = 0x7fff;
    calData.accelMaxY = 0x8000;
    calData.accelMinZ = 0x7fff;
    calData.accelMaxZ = 0x8000;

    calData.magValid = false;
    calData.magMinX = 0x7fff;                                // init mag cal data
    calData.magMaxX = 0x8000;
    calData.magMinY = 0x7fff;
    calData.magMaxY = 0x8000;
    calData.magMinZ = 0x7fff;
    calData.magMaxZ = 0x8000;

    MPU.useAccelCal(false);
    //MPU.init(MPU_UPDATE_RATE, 5, 1, MPU_LPF_RATE);

    counter = 359;
    InCallibrationMode = true;
    calibration_timer.reset();
    Serial.println(F("!!!:While the compass counts down from 360 to 0, rotate the ROV slowly in all three axis;"));

  }

  if (InCallibrationMode){
    bool changed = false;

    if(counter>0){
      if (MPU.read()) {                                        // get the latest data
        changed = false;
        if (MPU.m_rawAccel[VEC3_X] < calData.accelMinX) {
          calData.accelMinX = MPU.m_rawAccel[VEC3_X];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_X] > calData.accelMaxX) {
          calData.accelMaxX = MPU.m_rawAccel[VEC3_X];
          changed = true;
        }
        if (MPU.m_rawAccel[VEC3_Y] < calData.accelMinY) {
          calData.accelMinY = MPU.m_rawAccel[VEC3_Y];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_Y] > calData.accelMaxY) {
          calData.accelMaxY = MPU.m_rawAccel[VEC3_Y];
          changed = true;
        }
        if (MPU.m_rawAccel[VEC3_Z] < calData.accelMinZ) {
          calData.accelMinZ = MPU.m_rawAccel[VEC3_Z];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_Z] > calData.accelMaxZ) {
          calData.accelMaxZ = MPU.m_rawAccel[VEC3_Z];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_X] < calData.magMinX) {
          calData.magMinX = MPU.m_rawMag[VEC3_X];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_X] > calData.magMaxX) {
          calData.magMaxX = MPU.m_rawMag[VEC3_X];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_Y] < calData.magMinY) {
          calData.magMinY = MPU.m_rawMag[VEC3_Y];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_Y] > calData.magMaxY) {
          calData.magMaxY = MPU.m_rawMag[VEC3_Y];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_Z] < calData.magMinZ) {
          calData.magMinZ = MPU.m_rawMag[VEC3_Z];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_Z] > calData.magMaxZ) {
          calData.magMaxZ = MPU.m_rawMag[VEC3_Z];
          changed = true;
        }

        if (changed) {
          Serial.print(F("dia:accel.MinX=")); Serial.print(calData.accelMinX); Serial.println(";");
          Serial.print(F("dia:accel.maxX=")); Serial.print(calData.accelMaxX); Serial.println(";");
          Serial.print(F("dia:accel.minY=")); Serial.print(calData.accelMinY); Serial.println(";");
          Serial.print(F("dia:accel.maxY=")); Serial.print(calData.accelMaxY); Serial.println(";");
          Serial.print(F("dia:accel.minZ=")); Serial.print(calData.accelMinZ); Serial.println(";");
          Serial.print(F("dia:accel.maxZ=")); Serial.print(calData.accelMaxZ); Serial.println(";");
          Serial.print(F("dia:mag.minX=")); Serial.print(calData.magMinX); Serial.println(";");
          Serial.print(F("dia:mag.maxX=")); Serial.print(calData.magMaxX); Serial.println(";");
          Serial.print(F("dia:mag.minY=")); Serial.print(calData.magMinY); Serial.println(";");
          Serial.print(F("dia:mag.maxY=")); Serial.print(calData.magMaxY); Serial.println(";");
          Serial.print(F("dia:mag.minZ=")); Serial.print(calData.magMinZ); Serial.println(";");
          Serial.print(F("dia:mag.maxZ=")); Serial.print(calData.magMaxZ); Serial.println(";");
        }
      }
      if (calibration_timer.elapsed (1000)) {
        counter--;
        navdata::HDGD = counter;
        Serial.print(F("hdgd:"));
        Serial.print(navdata::HDGD);
        Serial.print(';');
      }
    }
    if (counter <= 0){
      calData.accelValid = true;
      calData.magValid = true;
      calLibWrite(MPUDeviceId, &calData);
      Serial.println(F("log:Accel cal data saved for device;"));
      InCallibrationMode = false;
    }
    return;  //prevents the normal read and reporting of IMU data
  }
  else if (command.cmp("i2cscan")){
   // scan();
  }

  if (mpu_update_timer.elapsed (50)){ //20 hz
    if(MPU.read()){
      navdata::HDGD = MPU.m_fusedEulerPose[VEC3_Z] * RAD_TO_DEGREE;
      //To convert to-180/180 to 0/360
      if (navdata::HDGD < 0) navdata::HDGD+=360;
      navdata::PITC = 180 + (MPU.m_fusedEulerPose[VEC3_X] * RAD_TO_DEGREE);
      if (navdata::PITC > 180) (navdata::PITC = navdata::PITC - 360);
      navdata::ROLL = MPU.m_fusedEulerPose[VEC3_X] * RAD_TO_DEGREE;
      navdata::YAW = MPU.m_fusedEulerPose[VEC3_Z] * RAD_TO_DEGREE;
    }
  }
}
#endif
<commit_msg>Fixed bad refactor on pitch in MPU9150<commit_after>#include "MPU9150.h"
#include "AConfig.h"
#if(HAS_MPU9150)
#include "Device.h"
#include "Settings.h"
#include <Wire.h>
//#include "I2Cdev.h"
#include "MPU9150Lib.h"
#include "CalLib.h"
//#include "dmpKey.h"
//#include "dmpmap.h"
//#include "inv_mpu.h"
//#include "inv_mpu_dmp_motion_driver.h"
#include <EEPROM.h>
#include "Timer.h"

MPU9150Lib MPU;                                              // the MPU object
int MPUDeviceId = 1;
boolean DidInit = false;
boolean InCallibrationMode = false;
Timer MPU9150ReInit;
Timer mpu_update_timer;
CALLIB_DATA calData;
Timer calibration_timer;
int counter = 0;
//  MPU_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the sensor data and DMP output

//  MPU_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the sensor data and DMP output

#define MPU_UPDATE_RATE  (20)

//  MAG_UPDATE_RATE defines the rate (in Hz) at which the MPU updates the magnetometer data
//  MAG_UPDATE_RATE should be less than or equal to the MPU_UPDATE_RATE

#define MAG_UPDATE_RATE  (10)

//  MPU_MAG_MIX defines the influence that the magnetometer has on the yaw output.
//  The magnetometer itself is quite noisy so some mixing with the gyro yaw can help
//  significantly. Some example values are defined below:

#define  MPU_MAG_MIX_GYRO_ONLY          0                   // just use gyro yaw
#define  MPU_MAG_MIX_MAG_ONLY           1                   // just use magnetometer and no gyro yaw
#define  MPU_MAG_MIX_GYRO_AND_MAG       10                  // a good mix value
#define  MPU_MAG_MIX_GYRO_AND_SOME_MAG  50                  // mainly gyros with a bit of mag correction

//  MPU_LPF_RATE is the low pas filter rate and can be between 5 and 188Hz

#define MPU_LPF_RATE   5

void MPU9150::device_setup(){
  //Todo: Read calibration values from EPROM
  Wire.begin();
  MPU.selectDevice(MPUDeviceId);
  if (!MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_ONLY, MAG_UPDATE_RATE, MPU_LPF_RATE)){
  	Serial.println(F("log:Trying other MPU9150 address to init;"));
  	Serial.print(F("log:IMU Address was :"));
  	Serial.print(1);
  	MPUDeviceId = !MPUDeviceId;
  	Serial.print(F(" but is now:"));
  	Serial.print(MPUDeviceId);
  	Serial.println(";");
  	MPU.selectDevice(MPUDeviceId);
  	if (MPU.init(MPU_UPDATE_RATE, MPU_MAG_MIX_GYRO_ONLY, MAG_UPDATE_RATE, MPU_LPF_RATE)){
  		DidInit = true;
  		Serial.println(F("log:Init worked the second time;"));
  	} else {
  		Serial.println(F("log:Failed to init on both addresses;"));
  	}
  } else {
  	DidInit = true;
  	Serial.println(F("log:init on primary addresses;"));
  }                             // start the MPU
  Settings::capability_bitarray |= (1 << COMPASS_CAPABLE);
  Settings::capability_bitarray |= (1 << ORIENTATION_CAPABLE);
  MPU9150ReInit.reset();
  mpu_update_timer.reset();
}

void MPU9150::device_loop(Command command){
  if (!DidInit){
    if( MPU9150ReInit.elapsed(30000)){
	MPU9150::device_setup();
    }
     return;
  }
  if (command.cmp("ccal")){
   // Compass_Calibrate();
   // The IMU needs both Magnatrometer and Acceleromter to be calibrated. This attempts to do them both at the same time
    calLibRead(MPUDeviceId, &calData);               // pick up existing accel data if there

    calData.accelValid = false;
    calData.accelMinX = 0x7fff;                              // init accel cal data
    calData.accelMaxX = 0x8000;
    calData.accelMinY = 0x7fff;
    calData.accelMaxY = 0x8000;
    calData.accelMinZ = 0x7fff;
    calData.accelMaxZ = 0x8000;

    calData.magValid = false;
    calData.magMinX = 0x7fff;                                // init mag cal data
    calData.magMaxX = 0x8000;
    calData.magMinY = 0x7fff;
    calData.magMaxY = 0x8000;
    calData.magMinZ = 0x7fff;
    calData.magMaxZ = 0x8000;

    MPU.useAccelCal(false);
    //MPU.init(MPU_UPDATE_RATE, 5, 1, MPU_LPF_RATE);

    counter = 359;
    InCallibrationMode = true;
    calibration_timer.reset();
    Serial.println(F("!!!:While the compass counts down from 360 to 0, rotate the ROV slowly in all three axis;"));

  }

  if (InCallibrationMode){
    bool changed = false;

    if(counter>0){
      if (MPU.read()) {                                        // get the latest data
        changed = false;
        if (MPU.m_rawAccel[VEC3_X] < calData.accelMinX) {
          calData.accelMinX = MPU.m_rawAccel[VEC3_X];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_X] > calData.accelMaxX) {
          calData.accelMaxX = MPU.m_rawAccel[VEC3_X];
          changed = true;
        }
        if (MPU.m_rawAccel[VEC3_Y] < calData.accelMinY) {
          calData.accelMinY = MPU.m_rawAccel[VEC3_Y];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_Y] > calData.accelMaxY) {
          calData.accelMaxY = MPU.m_rawAccel[VEC3_Y];
          changed = true;
        }
        if (MPU.m_rawAccel[VEC3_Z] < calData.accelMinZ) {
          calData.accelMinZ = MPU.m_rawAccel[VEC3_Z];
          changed = true;
        }
         if (MPU.m_rawAccel[VEC3_Z] > calData.accelMaxZ) {
          calData.accelMaxZ = MPU.m_rawAccel[VEC3_Z];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_X] < calData.magMinX) {
          calData.magMinX = MPU.m_rawMag[VEC3_X];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_X] > calData.magMaxX) {
          calData.magMaxX = MPU.m_rawMag[VEC3_X];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_Y] < calData.magMinY) {
          calData.magMinY = MPU.m_rawMag[VEC3_Y];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_Y] > calData.magMaxY) {
          calData.magMaxY = MPU.m_rawMag[VEC3_Y];
          changed = true;
        }
        if (MPU.m_rawMag[VEC3_Z] < calData.magMinZ) {
          calData.magMinZ = MPU.m_rawMag[VEC3_Z];
          changed = true;
        }
         if (MPU.m_rawMag[VEC3_Z] > calData.magMaxZ) {
          calData.magMaxZ = MPU.m_rawMag[VEC3_Z];
          changed = true;
        }

        if (changed) {
          Serial.print(F("dia:accel.MinX=")); Serial.print(calData.accelMinX); Serial.println(";");
          Serial.print(F("dia:accel.maxX=")); Serial.print(calData.accelMaxX); Serial.println(";");
          Serial.print(F("dia:accel.minY=")); Serial.print(calData.accelMinY); Serial.println(";");
          Serial.print(F("dia:accel.maxY=")); Serial.print(calData.accelMaxY); Serial.println(";");
          Serial.print(F("dia:accel.minZ=")); Serial.print(calData.accelMinZ); Serial.println(";");
          Serial.print(F("dia:accel.maxZ=")); Serial.print(calData.accelMaxZ); Serial.println(";");
          Serial.print(F("dia:mag.minX=")); Serial.print(calData.magMinX); Serial.println(";");
          Serial.print(F("dia:mag.maxX=")); Serial.print(calData.magMaxX); Serial.println(";");
          Serial.print(F("dia:mag.minY=")); Serial.print(calData.magMinY); Serial.println(";");
          Serial.print(F("dia:mag.maxY=")); Serial.print(calData.magMaxY); Serial.println(";");
          Serial.print(F("dia:mag.minZ=")); Serial.print(calData.magMinZ); Serial.println(";");
          Serial.print(F("dia:mag.maxZ=")); Serial.print(calData.magMaxZ); Serial.println(";");
        }
      }
      if (calibration_timer.elapsed (1000)) {
        counter--;
        navdata::HDGD = counter;
        Serial.print(F("hdgd:"));
        Serial.print(navdata::HDGD);
        Serial.print(';');
      }
    }
    if (counter <= 0){
      calData.accelValid = true;
      calData.magValid = true;
      calLibWrite(MPUDeviceId, &calData);
      Serial.println(F("log:Accel cal data saved for device;"));
      InCallibrationMode = false;
    }
    return;  //prevents the normal read and reporting of IMU data
  }
  else if (command.cmp("i2cscan")){
   // scan();
  }

  if (mpu_update_timer.elapsed (50)){ //20 hz
    if(MPU.read()){
      navdata::HDGD = MPU.m_fusedEulerPose[VEC3_Z] * RAD_TO_DEGREE;
      //To convert to-180/180 to 0/360
      if (navdata::HDGD < 0) navdata::HDGD+=360;
      navdata::PITC = 180 + (MPU.m_fusedEulerPose[VEC3_Y] * RAD_TO_DEGREE);
      if (navdata::PITC > 180) (navdata::PITC = navdata::PITC - 360);
      navdata::ROLL = MPU.m_fusedEulerPose[VEC3_X] * RAD_TO_DEGREE;
      navdata::YAW = MPU.m_fusedEulerPose[VEC3_Z] * RAD_TO_DEGREE;
    }
  }
}
#endif
<|endoftext|>


<commit_before>//=============================================================================
//File Name: OperatorControl.cpp
//Description: Handles driver controls for robot
//Author: FRC Team 3512, Spartatroniks
//=============================================================================

#include <Timer.h>
#include "OurRobot.hpp"
#include "ButtonTracker.hpp"

void OurRobot::OperatorControl() {
    Timer hammerClock;
    bool isHammerDown = false;

    mainCompressor.Start();

    isShooting = false;
    isAutoAiming = false;

    pinLock.Set( false );
    hammer.Set( false );

    ButtonTracker driveStick1Buttons( 1 );
    ButtonTracker driveStick2Buttons( 2 );
    ButtonTracker turretStickButtons( 3 );

    while ( IsEnabled() && IsOperatorControl() ) {
        DS_PrintOut();

        // update "new" value of joystick buttons
        driveStick1Buttons.updateButtons();
        driveStick2Buttons.updateButtons();
        turretStickButtons.updateButtons();

        /* ===== AIM ===== */
        if ( fabs( turretStick.GetX() ) > 0.1 ) { // manual turret movement outside of -0.5 to 0.5 range, up to 0.5 speed
            rotateMotor.Set( -turretStick.GetX() / 2.f );
        }
        else if ( isAutoAiming ) { // let autoAiming take over if activated and user isn't rotating turret
            if( fabs( turretKinect.getPixelOffset() ) < TurretKinect::pxlDeadband ) { // deadband so shooter won't jitter
                rotateMotor.Set(0);
            }
            else {
                /* Set(x) = x / 320
                 * -320 <= x <= 320 therefore Set( -1 <= x / 320 <= 1 )
                 * smooth tracking because as the turret aims closer to the target, the motor value gets smaller
                 */
                rotateMotor.Set( static_cast<float>( turretKinect.getPixelOffset() ) / 320.f );
            }
        }
        else {
            rotateMotor.Set( 0 );
        }
        /* =============== */

        /* ===================== AutoAim ===================== */
        if ( turretStickButtons.releasedButton( 3 ) ) {
            isAutoAiming = !isAutoAiming; // toggles autoAim
        }
        /* =================================================== */

        /* ================= Target Selection ================ */
        // selecting target to left of current target
        if ( turretStickButtons.releasedButton( 4 ) ) {
            turretKinect.setTargetSelect( -1 );

            turretKinect.send();
        }

        // selecting target to right of current target
        if ( turretStickButtons.releasedButton( 5 ) ) {
            turretKinect.setTargetSelect( 1 );

            turretKinect.send();
        }
        /* =================================================== */

        /* ============== Toggle Shooter Motors ============== */
        // turns shooter on/off
        if ( turretStickButtons.releasedButton( 1 ) ) { // if released trigger
            isShooting = !isShooting;
        }

        if ( isShooting ) {
            if ( shooterIsManual ) { // let driver change shooter speed manually
                shooterMotorLeft.Set( -ScaleZ(turretStick) );
                shooterMotorRight.Set( ScaleZ(turretStick) );
            }
            else { // else adjust shooter voltage to match RPM
                if ( 60.f / ( 16.f * shooterEncoder.GetPeriod() ) < 72.0 * ScaleZ(turretStick) * 60.0 ) {
                    shooterMotorLeft.Set( -1 );
                    shooterMotorRight.Set( 1 );
                }
                else {
                    shooterMotorLeft.Set( 0 );
                    shooterMotorRight.Set( 0 );
                }
            }
        }
        else {
            shooterMotorLeft.Set( 0 );
            shooterMotorRight.Set( 0 );
        }

        // toggle manual RPM setting vs setting with encoder input
        if ( turretStickButtons.releasedButton( 2 ) ) {
            shooterIsManual = !shooterIsManual;
        }
		/* =================================================== */

        /* ===== Ball Intake/Conveyor ===== */
        if ( turretStick.GetRawButton( 6 ) ) { // move upper lift up
            upperLift.Set( Relay::kForward );
        }
        else if ( turretStick.GetRawButton( 11 ) ) { // move upper lift down
            upperLift.Set( Relay::kReverse );
        }
        else {
            upperLift.Set( Relay::kOff ); // turn off lift
        }

        if ( turretStick.GetRawButton( 7 ) ) { // move lower lift up
            lowerLift.Set( Relay::kReverse );
        }
        else if ( turretStick.GetRawButton( 10 ) ) { // move lower lift down
            lowerLift.Set( Relay::kForward );
		}
        else {
            lowerLift.Set( Relay::kOff ); // turn off lift
        }

        // ---------- Full Lift Forward ----------
        if ( turretStick.GetRawButton( 8 ) ) { // move all lifts up
            upperLift.Set( Relay::kForward );
            lowerLift.Set( Relay::kReverse );
        }

        // ---------- Full Lift Reverse ----------
        if ( turretStick.GetRawButton( 9 ) ) { // move all lifts down
            upperLift.Set( Relay::kReverse );
            lowerLift.Set( Relay::kForward );
        }
        /* ================================ */

        /* ===== Hammer =====
         * There are two parts to switching the state of this mechanism.
         *
         * 1) The first device is moved into position and out of the other one's way.
         * 2) The second device is moved after a delay to avoid a mechanical lock-up.
         *
         * When the trigger is released, the state variable switches and a timer is started.
         * The first device is moved into position immediately.
         *
         * After the delay for the respective state change has passed,
         *     the second device is moved into position. This is done
         *     to make sure that there are no mechanical lock-ups caused
         *     by the devices being triggered at the same time. It may
         *     damage them.
         *
         * After the second device is told to move, the timers are stopped and
         *     reset since they aren't needed anymore.
         *
         * Note: We don't know for sure if either device moved out of the way by
         *       the time the second device needs to be moved. It's just
         *       assumed that the delay gave the first device enough time
         *       to do so.
         */

        // ===== PART 1
        if ( driveStick2Buttons.releasedButton( 1 ) ) { // if released trigger
            // start process of switching position of hammer
            isHammerDown = !isHammerDown;

            hammerClock.Start(); // used to track delay between actions

            // move the first device immediately
            if( isHammerDown ) {
                hammer.Set( true ); // if hammer should be going down, deploy it immediately
            }
            else {
                pinLock.Set( false ); // if hammer is coming back up, unlock solenoid immediately
            }
        }
        // ============

        // ===== PART 2
        // move second device after delay has passed
        if ( isHammerDown && hammerClock.Get() > 0 ) {
            // if hammer is down and delay passed, deploy locks
            pinLock.Set( true );

            // stop timer because the device has finished switching states
            hammerClock.Stop();
            hammerClock.Reset();
        }

        if ( !isHammerDown && hammerClock.Get() > 0.2 ) {
            // if hammer is coming back up after delay passed, locks are disengaged so bring hammer back up
            hammer.Set( false );

            // stop timer because the device has finished switching states
            hammerClock.Stop();
            hammerClock.Reset();
        }
        // ============
        /* ================== */

        /* ===== Shifter ===== */
        if ( driveStick1Buttons.releasedButton( 1 ) ) { // if released trigger
            shifter.Set( !shifter.Get() ); // shifts between low and high gear
        }
        /* =================== */

        // move robot based on two joystick inputs
        mainDrive.ArcadeDrive( ScaleZ( driveStick1 ) * driveStick1.GetY() , driveStick2.GetX() , false );

        Wait( 0.1 );
    }
}
<commit_msg>Added ScaleZ(Joystick&) to robot turning so robot can turn slow as well as drive slow<commit_after>//=============================================================================
//File Name: OperatorControl.cpp
//Description: Handles driver controls for robot
//Author: FRC Team 3512, Spartatroniks
//=============================================================================

#include <Timer.h>
#include "OurRobot.hpp"
#include "ButtonTracker.hpp"

void OurRobot::OperatorControl() {
    Timer hammerClock;
    bool isHammerDown = false;

    mainCompressor.Start();

    isShooting = false;
    isAutoAiming = false;

    pinLock.Set( false );
    hammer.Set( false );

    ButtonTracker driveStick1Buttons( 1 );
    ButtonTracker driveStick2Buttons( 2 );
    ButtonTracker turretStickButtons( 3 );

    while ( IsEnabled() && IsOperatorControl() ) {
        DS_PrintOut();

        // update "new" value of joystick buttons
        driveStick1Buttons.updateButtons();
        driveStick2Buttons.updateButtons();
        turretStickButtons.updateButtons();

        /* ===== AIM ===== */
        if ( fabs( turretStick.GetX() ) > 0.1 ) { // manual turret movement outside of -0.5 to 0.5 range, up to 0.5 speed
            rotateMotor.Set( -turretStick.GetX() / 2.f );
        }
        else if ( isAutoAiming ) { // let autoAiming take over if activated and user isn't rotating turret
            if( fabs( turretKinect.getPixelOffset() ) < TurretKinect::pxlDeadband ) { // deadband so shooter won't jitter
                rotateMotor.Set(0);
            }
            else {
                /* Set(x) = x / 320
                 * -320 <= x <= 320 therefore Set( -1 <= x / 320 <= 1 )
                 * smooth tracking because as the turret aims closer to the target, the motor value gets smaller
                 */
                rotateMotor.Set( static_cast<float>( turretKinect.getPixelOffset() ) / 320.f );
            }
        }
        else {
            rotateMotor.Set( 0 );
        }
        /* =============== */

        /* ===================== AutoAim ===================== */
        if ( turretStickButtons.releasedButton( 3 ) ) {
            isAutoAiming = !isAutoAiming; // toggles autoAim
        }
        /* =================================================== */

        /* ================= Target Selection ================ */
        // selecting target to left of current target
        if ( turretStickButtons.releasedButton( 4 ) ) {
            turretKinect.setTargetSelect( -1 );

            turretKinect.send();
        }

        // selecting target to right of current target
        if ( turretStickButtons.releasedButton( 5 ) ) {
            turretKinect.setTargetSelect( 1 );

            turretKinect.send();
        }
        /* =================================================== */

        /* ============== Toggle Shooter Motors ============== */
        // turns shooter on/off
        if ( turretStickButtons.releasedButton( 1 ) ) { // if released trigger
            isShooting = !isShooting;
        }

        if ( isShooting ) {
            if ( shooterIsManual ) { // let driver change shooter speed manually
                shooterMotorLeft.Set( -ScaleZ(turretStick) );
                shooterMotorRight.Set( ScaleZ(turretStick) );
            }
            else { // else adjust shooter voltage to match RPM
                if ( 60.f / ( 16.f * shooterEncoder.GetPeriod() ) < 72.0 * ScaleZ(turretStick) * 60.0 ) {
                    shooterMotorLeft.Set( -1 );
                    shooterMotorRight.Set( 1 );
                }
                else {
                    shooterMotorLeft.Set( 0 );
                    shooterMotorRight.Set( 0 );
                }
            }
        }
        else {
            shooterMotorLeft.Set( 0 );
            shooterMotorRight.Set( 0 );
        }

        // toggle manual RPM setting vs setting with encoder input
        if ( turretStickButtons.releasedButton( 2 ) ) {
            shooterIsManual = !shooterIsManual;
        }
		/* =================================================== */

        /* ===== Ball Intake/Conveyor ===== */
        if ( turretStick.GetRawButton( 6 ) ) { // move upper lift up
            upperLift.Set( Relay::kForward );
        }
        else if ( turretStick.GetRawButton( 11 ) ) { // move upper lift down
            upperLift.Set( Relay::kReverse );
        }
        else {
            upperLift.Set( Relay::kOff ); // turn off lift
        }

        if ( turretStick.GetRawButton( 7 ) ) { // move lower lift up
            lowerLift.Set( Relay::kReverse );
        }
        else if ( turretStick.GetRawButton( 10 ) ) { // move lower lift down
            lowerLift.Set( Relay::kForward );
		}
        else {
            lowerLift.Set( Relay::kOff ); // turn off lift
        }

        // ---------- Full Lift Forward ----------
        if ( turretStick.GetRawButton( 8 ) ) { // move all lifts up
            upperLift.Set( Relay::kForward );
            lowerLift.Set( Relay::kReverse );
        }

        // ---------- Full Lift Reverse ----------
        if ( turretStick.GetRawButton( 9 ) ) { // move all lifts down
            upperLift.Set( Relay::kReverse );
            lowerLift.Set( Relay::kForward );
        }
        /* ================================ */

        /* ===== Hammer =====
         * There are two parts to switching the state of this mechanism.
         *
         * 1) The first device is moved into position and out of the other one's way.
         * 2) The second device is moved after a delay to avoid a mechanical lock-up.
         *
         * When the trigger is released, the state variable switches and a timer is started.
         * The first device is moved into position immediately.
         *
         * After the delay for the respective state change has passed,
         *     the second device is moved into position. This is done
         *     to make sure that there are no mechanical lock-ups caused
         *     by the devices being triggered at the same time. It may
         *     damage them.
         *
         * After the second device is told to move, the timers are stopped and
         *     reset since they aren't needed anymore.
         *
         * Note: We don't know for sure if either device moved out of the way by
         *       the time the second device needs to be moved. It's just
         *       assumed that the delay gave the first device enough time
         *       to do so.
         */

        // ===== PART 1
        if ( driveStick2Buttons.releasedButton( 1 ) ) { // if released trigger
            // start process of switching position of hammer
            isHammerDown = !isHammerDown;

            hammerClock.Start(); // used to track delay between actions

            // move the first device immediately
            if( isHammerDown ) {
                hammer.Set( true ); // if hammer should be going down, deploy it immediately
            }
            else {
                pinLock.Set( false ); // if hammer is coming back up, unlock solenoid immediately
            }
        }
        // ============

        // ===== PART 2
        // move second device after delay has passed
        if ( isHammerDown && hammerClock.Get() > 0 ) {
            // if hammer is down and delay passed, deploy locks
            pinLock.Set( true );

            // stop timer because the device has finished switching states
            hammerClock.Stop();
            hammerClock.Reset();
        }

        if ( !isHammerDown && hammerClock.Get() > 0.2 ) {
            // if hammer is coming back up after delay passed, locks are disengaged so bring hammer back up
            hammer.Set( false );

            // stop timer because the device has finished switching states
            hammerClock.Stop();
            hammerClock.Reset();
        }
        // ============
        /* ================== */

        /* ===== Shifter ===== */
        if ( driveStick1Buttons.releasedButton( 1 ) ) { // if released trigger
            shifter.Set( !shifter.Get() ); // shifts between low and high gear
        }
        /* =================== */

        // move robot based on two joystick inputs
        mainDrive.ArcadeDrive( ScaleZ( driveStick1 ) * driveStick1.GetY() , ScaleZ( driveStick2 ) * driveStick2.GetX() , false );

        Wait( 0.1 );
    }
}
<|endoftext|>


<commit_before>#include <iostream>

#include "SDL/SDL.h"
#include "SDL_image.h"
#include "SDL_gfxPrimitives.h"
#include "point.h"
#include "map.h"
#include "game.h"
#include "surface.h"
#include "eventfactory.h"

using namespace std;

Game::Game() {
  playing=true;
  screen=NULL;
  terrain=NULL;
  map_camera=NULL;
}

int Game::execute() {
  if (!init()) {
    cerr << "Errors occured when starting the game. Stopping." << endl;
    return 1;
  }

  SDL_Event event;

  while(playing) {
    SDL_PumpEvents();
    while(SDL_PollEvent(&event)) {
      onEvent(&event);
    }

    updateState();
    render();
    // SDL rest?
  }

  return cleanup();
}

int Game::init() {
  if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
    return false;
  }

  screen = SDL_SetVideoMode(800, 600, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
  if(screen == NULL) {
     return false;
  }

  int flags = IMG_INIT_JPG | IMG_INIT_PNG;
  int initted=IMG_Init(flags);
  if( initted & flags != flags) {
    cout << "could not init SDL_Image" << endl;
    cout << "Reason: " << IMG_GetError() << endl;
    return false;
  }

  terrain = Surface::load("graphics/terrain.png");

  if (terrain == NULL) {
    cout << "Failed to read graphics/terrain.png data" << endl;
    return false;
  }

  shroud_edges = Surface::load("graphics/shroud_edges.bmp");

  if (shroud_edges == NULL) {
    cout << "Failed to read graphics/shroud_edges.bmp data" << endl;
    return false;
  }

  shroud_edges_shadow = Surface::load("graphics/shroud_edges_shadow.bmp");

  if (shroud_edges_shadow == NULL) {
    cout << "Failed to read graphics/shroud_edges_shadow.bmp data" << endl;
    return false;
  }

  SDL_ShowCursor(0);
  mouse.init(screen);

  map_camera = new MapCamera(0, 0, screen, &map);
  map.load("maps/4PL_Mountains.ini");
  unitRepository = new UnitRepository(&map);

  Unit* frigate = unitRepository->create(UNIT_FRIGATE, HOUSE_SARDAUKAR, 64, 64, 10);
  units.push_back(frigate);

  Unit* trike1 = unitRepository->create(UNIT_TRIKE, HOUSE_ATREIDES, 256, 256, 3);
  units.push_back(trike1);

  Unit* trike2 = unitRepository->create(UNIT_SOLDIER, HOUSE_SARDAUKAR, 448, 448, 3);
  units.push_back(trike2);

  return true;
}

void Game::onEvent(SDL_Event* event) {
  if(event->type == SDL_QUIT) {
    playing = false;
  }

  mouse.onEvent(event);
  keyboard.onEvent(event);

  map_camera->onEvent(event);

  if (event->type == SDL_USEREVENT) {
    if (event->user.code == D2TM_SELECT) {
      D2TMSelectStruct *s = static_cast<D2TMSelectStruct*>(event->user.data1);

      Point p = map_camera->toWorldCoordinates(s->screen_position);

      if (mouse.is_pointing()) {
        Unit* selected_unit = NULL;
        for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
          if ((*it)->is_point_within(p)) {
            selected_unit = *it;
            break;
          }
        }

        if (selected_unit != NULL) {
          deselectAllUnits();
          selected_unit->select();
          mouse.state_order_move();
        }
      }

      delete s;
    } else if (event->user.code == D2TM_DESELECT) {
      mouse.state_pointing();
      deselectAllUnits();
    } else if (event->user.code == D2TM_BOX_SELECT) {
      D2TMBoxSelectStruct *s = static_cast<D2TMBoxSelectStruct*>(event->user.data1);

      Rectangle rectangle = map_camera->toWorldCoordinates(s->rectangle);

      if (mouse.is_pointing()) {
        mouse.state_pointing();

        deselectAllUnits();
        for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
          if ((*it)->is_within(rectangle)) {
            (*it)->select();
            mouse.state_order_move();
          }
        }
      }

      delete s;
    } else if (event->user.code == D2TM_MOVE_UNIT) {
      D2TMMoveUnitStruct *s = static_cast<D2TMMoveUnitStruct*>(event->user.data1);
      Point p = map_camera->toWorldCoordinates(s->screen_position);

      for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
        if ((*it)->is_selected()) {
          (*it)->order_move(p);
        }
      }

      delete s;
    }

  }

}

void Game::render() {
  SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));

  map_camera->draw(&map, terrain, screen);

  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    if ((*it)->is_on_ground_layer()) map_camera->draw(*it, screen);
  }

  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    if ((*it)->is_on_air_layer()) map_camera->draw(*it, screen);
  }

  map_camera->drawShroud(&map, shroud_edges, shroud_edges_shadow, screen);

  mouse.draw(screen);

  SDL_Flip(screen);
}

void Game::updateState() {
  keyboard.updateState();
  mouse.updateState();
  map_camera->updateState();

  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    (*it)->updateState();
  }
}

int Game::cleanup() {
  delete map_camera;
  delete unitRepository;
  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    delete *it;
  }
  units.clear();
  SDL_FreeSurface(screen);
  SDL_FreeSurface(terrain);
  SDL_FreeSurface(shroud_edges);
  SDL_FreeSurface(shroud_edges_shadow);
  SDL_Quit();
  return 0;
}

void Game::deselectAllUnits() {
  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    (*it)->unselect();
  }
}

<commit_msg>add 5 soldiers, with coordinates as if the sub-cells already exist, just to give some sense of how it looks like<commit_after>#include <iostream>

#include "SDL/SDL.h"
#include "SDL_image.h"
#include "SDL_gfxPrimitives.h"
#include "point.h"
#include "map.h"
#include "game.h"
#include "surface.h"
#include "eventfactory.h"

using namespace std;

Game::Game() {
  playing=true;
  screen=NULL;
  terrain=NULL;
  map_camera=NULL;
}

int Game::execute() {
  if (!init()) {
    cerr << "Errors occured when starting the game. Stopping." << endl;
    return 1;
  }

  SDL_Event event;

  while(playing) {
    SDL_PumpEvents();
    while(SDL_PollEvent(&event)) {
      onEvent(&event);
    }

    updateState();
    render();
    // SDL rest?
  }

  return cleanup();
}

int Game::init() {
  if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
    return false;
  }

  screen = SDL_SetVideoMode(800, 600, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
  if(screen == NULL) {
     return false;
  }

  int flags = IMG_INIT_JPG | IMG_INIT_PNG;
  int initted=IMG_Init(flags);
  if( initted & flags != flags) {
    cout << "could not init SDL_Image" << endl;
    cout << "Reason: " << IMG_GetError() << endl;
    return false;
  }

  terrain = Surface::load("graphics/terrain.png");

  if (terrain == NULL) {
    cout << "Failed to read graphics/terrain.png data" << endl;
    return false;
  }

  shroud_edges = Surface::load("graphics/shroud_edges.bmp");

  if (shroud_edges == NULL) {
    cout << "Failed to read graphics/shroud_edges.bmp data" << endl;
    return false;
  }

  shroud_edges_shadow = Surface::load("graphics/shroud_edges_shadow.bmp");

  if (shroud_edges_shadow == NULL) {
    cout << "Failed to read graphics/shroud_edges_shadow.bmp data" << endl;
    return false;
  }

  SDL_ShowCursor(0);
  mouse.init(screen);

  map_camera = new MapCamera(0, 0, screen, &map);
  map.load("maps/4PL_Mountains.ini");
  unitRepository = new UnitRepository(&map);

  units.push_back(unitRepository->create(UNIT_FRIGATE, HOUSE_SARDAUKAR, 64, 64, 10));
  units.push_back(unitRepository->create(UNIT_TRIKE, HOUSE_ATREIDES, 256, 256, 3));

  // soldiers
  units.push_back(unitRepository->create(UNIT_SOLDIER, HOUSE_SARDAUKAR, 448, 448, 3)); // this is sub-cell 3
  units.push_back(unitRepository->create(UNIT_SOLDIER, HOUSE_SARDAUKAR, 440, 440, 3)); // this is sub-cell 1 (up left), -8, -8
  units.push_back(unitRepository->create(UNIT_SOLDIER, HOUSE_SARDAUKAR, 456, 440, 3)); // this is sub-cell 2 (up right), +8, -8
  units.push_back(unitRepository->create(UNIT_SOLDIER, HOUSE_SARDAUKAR, 440, 456, 3)); // this is sub-cell 4 (down left), -8, + 8
  units.push_back(unitRepository->create(UNIT_SOLDIER, HOUSE_SARDAUKAR, 456, 456, 3)); // this is sub-cell 5 (down right), +8, + 8

  return true;
}

void Game::onEvent(SDL_Event* event) {
  if(event->type == SDL_QUIT) {
    playing = false;
  }

  mouse.onEvent(event);
  keyboard.onEvent(event);

  map_camera->onEvent(event);

  if (event->type == SDL_USEREVENT) {
    if (event->user.code == D2TM_SELECT) {
      D2TMSelectStruct *s = static_cast<D2TMSelectStruct*>(event->user.data1);

      Point p = map_camera->toWorldCoordinates(s->screen_position);

      if (mouse.is_pointing()) {
        Unit* selected_unit = NULL;
        for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
          if ((*it)->is_point_within(p)) {
            selected_unit = *it;
            break;
          }
        }

        if (selected_unit != NULL) {
          deselectAllUnits();
          selected_unit->select();
          mouse.state_order_move();
        }
      }

      delete s;
    } else if (event->user.code == D2TM_DESELECT) {
      mouse.state_pointing();
      deselectAllUnits();
    } else if (event->user.code == D2TM_BOX_SELECT) {
      D2TMBoxSelectStruct *s = static_cast<D2TMBoxSelectStruct*>(event->user.data1);

      Rectangle rectangle = map_camera->toWorldCoordinates(s->rectangle);

      if (mouse.is_pointing()) {
        mouse.state_pointing();

        deselectAllUnits();
        for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
          if ((*it)->is_within(rectangle)) {
            (*it)->select();
            mouse.state_order_move();
          }
        }
      }

      delete s;
    } else if (event->user.code == D2TM_MOVE_UNIT) {
      D2TMMoveUnitStruct *s = static_cast<D2TMMoveUnitStruct*>(event->user.data1);
      Point p = map_camera->toWorldCoordinates(s->screen_position);

      for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
        if ((*it)->is_selected()) {
          (*it)->order_move(p);
        }
      }

      delete s;
    }

  }

}

void Game::render() {
  SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));

  map_camera->draw(&map, terrain, screen);

  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    if ((*it)->is_on_ground_layer()) map_camera->draw(*it, screen);
  }

  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    if ((*it)->is_on_air_layer()) map_camera->draw(*it, screen);
  }

  map_camera->drawShroud(&map, shroud_edges, shroud_edges_shadow, screen);

  mouse.draw(screen);

  SDL_Flip(screen);
}

void Game::updateState() {
  keyboard.updateState();
  mouse.updateState();
  map_camera->updateState();

  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    (*it)->updateState();
  }
}

int Game::cleanup() {
  delete map_camera;
  delete unitRepository;
  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    delete *it;
  }
  units.clear();
  SDL_FreeSurface(screen);
  SDL_FreeSurface(terrain);
  SDL_FreeSurface(shroud_edges);
  SDL_FreeSurface(shroud_edges_shadow);
  SDL_Quit();
  return 0;
}

void Game::deselectAllUnits() {
  for (vector<Unit*>::iterator it = units.begin(); it != units.end(); ++it) {
    (*it)->unselect();
  }
}

<|endoftext|>


<commit_before>//=====================================================================//
/*!	@file
	@brief	SD カードの読み書き、サンプル
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include <cstring>
#include "G13/system.hpp"
#include "common/port_utils.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/itimer.hpp"
#include "common/format.hpp"
#include "common/delay.hpp"
#include "common/csi_io.hpp"
#include "common/sdc_io.hpp"
#include "common/command.hpp"

namespace {
	void wait_()
	{
		asm("nop");
	}

	// 送信、受信バッファの定義
	typedef utils::fifo<64> buffer;
	// UART の定義（SAU2、SAU3）
	device::uart_io<device::SAU02, device::SAU03, buffer, buffer> uart_;

	// インターバル・タイマー
	device::itimer<uint16_t> itm_;

	// CSI(SPI) の定義、CSI00 の通信では、「SAU00」を利用、０ユニット、チャネル０
	typedef device::csi_io<device::SAU00> csi;
	csi csi_;

	// FatFS インターフェースの定義
	typedef device::PORT<device::port_no::P0,  device::bitpos::B0> card_select;	///< カード選択信号
	typedef device::PORT<device::port_no::P0,  device::bitpos::B1> card_power;	///< カード電源制御
	typedef device::PORT<device::port_no::P14, device::bitpos::B6> card_detect;	///< カード検出

	utils::sdc_io<csi, card_select, card_power, card_detect> sdc_(csi_);

	utils::command<64> command_;
}

const void* ivec_[] __attribute__ ((section (".ivec"))) = {
	/*  0 */  nullptr,
	/*  1 */  nullptr,
	/*  2 */  nullptr,
	/*  3 */  nullptr,
	/*  4 */  nullptr,
	/*  5 */  nullptr,
	/*  6 */  nullptr,
	/*  7 */  nullptr,
	/*  8 */  nullptr,
	/*  9 */  nullptr,
	/* 10 */  nullptr,
	/* 11 */  nullptr,
	/* 12 */  nullptr,
	/* 13 */  nullptr,
	/* 14 */  nullptr,
	/* 15 */  nullptr,
	/* 16 */  reinterpret_cast<void*>(uart_.send_task),
	/* 17 */  reinterpret_cast<void*>(uart_.recv_task),
	/* 18 */  reinterpret_cast<void*>(uart_.error_task),
	/* 19 */  nullptr,
	/* 20 */  nullptr,
	/* 21 */  nullptr,
	/* 22 */  nullptr,
	/* 23 */  nullptr,
	/* 24 */  nullptr,
	/* 25 */  nullptr,
	/* 26 */  reinterpret_cast<void*>(itm_.task),
};

extern "C" {
	void sci_putch(char ch)
	{
		uart_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		uart_.puts(str);
	}

	char sci_getch(void)
	{
		return uart_.getch();
	}

	uint16_t sci_length()
	{
		return uart_.recv_length();
	}

	DSTATUS disk_initialize(BYTE drv) {
		return sdc_.at_mmc().disk_initialize(drv);
	}

	DSTATUS disk_status(BYTE drv) {
		return sdc_.at_mmc().disk_status(drv);
	}

	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_read(drv, buff, sector, count);
	}

	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_write(drv, buff, sector, count);
	}

	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdc_.at_mmc().disk_ioctl(drv, ctrl, buff);
	}

	DWORD get_fattime(void) {
		return 0;
	}
};

namespace {

	uint8_t v_ = 91;
	uint8_t m_ = 123;
	uint8_t rand_()
	{
		v_ += v_ << 2;
		++v_;
		uint8_t n = 0;
		if(m_ & 0x02) n = 1;
		if(m_ & 0x40) n ^= 1;
		m_ += m_;
		if(n == 0) ++m_;
		return v_ ^ m_;
	}

	bool create_test_file_(const char* fname, uint32_t size)
	{
		utils::format("SD Write test...\n");

		uint8_t buff[512];
		for(uint16_t i = 0; i < sizeof(buff); ++i) {
			buff[i] = rand_();
		}

		auto st = itm_.get_counter();
		FIL fp;
		if(f_open(&fp, fname, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) {
			utils::format("Can't create file: '%s'\n") % fname;
			return false;
		}
		auto rs = size;
		while(rs > 0) {
			UINT sz = sizeof(buff);
			if(sz > rs) sz = rs;
			UINT bw;
			f_write(&fp, buff, sz, &bw);
			rs -= bw;
		}
		f_close(&fp);

		auto ed = itm_.get_counter();
		uint32_t len;
		if(ed > st) len = ed - st;
		else len = 65536 + ed - st;
		utils::format("Write frame: %d\n") % len;
		auto pbyte = size * 60 / len;
		utils::format("Write: %d Bytes/Sec\n") % pbyte;
		utils::format("Write: %d KBytes/Sec\n") % (pbyte / 1024);

		return true;
	}

	void test_all_()
	{
		const char* test_file = { "TEST.BIN" };
		uint32_t size = 1024L * 1024L;
		if(!create_test_file_(test_file, size)) {
			return;
		}
		utils::format("SD Speed test start...\n");

		auto st = itm_.get_counter();

		utils::format("SD Read test...\n");
		FIL fp;
		if(f_open(&fp, test_file, FA_READ) != FR_OK) {
			utils::format("Can't read file: '%s'\n") % test_file;
		}
		auto rs = size;
		while(rs > 0) {
			uint8_t buff[512];
			UINT rb;
			UINT sz = sizeof(buff);
			if(sz > rs) sz = rs;
			f_read(&fp, buff, sz, &rb);
			rs -= rb;
		}
		f_close(&fp);

		auto ed = itm_.get_counter();
		uint32_t len;
		if(ed > st) len = ed - st;
		else len = 65536 + ed - st;
		utils::format("Read frame: %d\n") % len;
		auto pbyte = size * 60 / len;
		utils::format("Read: %d Bytes/Sec\n") % pbyte;
		utils::format("Read: %d KBytes/Sec\n") % (pbyte / 1024);
	}
}

int main(int argc, char* argv[])
{
	using namespace device;

	utils::port::pullup_all();  ///< 安全の為、全ての入力をプルアップ

	PM4.B3 = 0;  // output

	// インターバル・タイマー開始
	{
		uint8_t intr_level = 1;
		itm_.start(60, intr_level);
	}

	// UART 開始
	{
		uint8_t intr_level = 1;
		uart_.start(115200, intr_level);
	}

	sdc_.initialize();

	uart_.puts("Start RL78/G13 SD-CARD Access sample\n");

	command_.set_prompt("# ");

	uint8_t n = 0;
	while(1) {
		itm_.sync();

		sdc_.service();

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			auto cmdn = command_.get_words();
			if(cmdn >= 1) {
				bool f = false;
				if(command_.cmp_word(0, "dir")) {
					sdc_.dir("");
					f = true;
				} else if(command_.cmp_word(0, "speed")) {
					test_all_();
					f = true;
				}
				if(!f) {
					char tmp[16];
					command_.get_word(0, sizeof(tmp), tmp);
					utils::format("Command error: '%s'\n") % tmp;
				}
			}
		}

		++n;
		if(n >= 30) n = 0;
		P4.B3 = n < 10 ? false : true;
	}
}
<commit_msg>fix message<commit_after>//=====================================================================//
/*!	@file
	@brief	SD カードの読み書き、サンプル
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include <cstring>
#include "G13/system.hpp"
#include "common/port_utils.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/itimer.hpp"
#include "common/format.hpp"
#include "common/delay.hpp"
#include "common/csi_io.hpp"
#include "common/sdc_io.hpp"
#include "common/command.hpp"

namespace {
	void wait_()
	{
		asm("nop");
	}

	// 送信、受信バッファの定義
	typedef utils::fifo<64> buffer;
	// UART の定義（SAU2、SAU3）
	device::uart_io<device::SAU02, device::SAU03, buffer, buffer> uart_;

	// インターバル・タイマー
	device::itimer<uint16_t> itm_;

	// CSI(SPI) の定義、CSI00 の通信では、「SAU00」を利用、０ユニット、チャネル０
	typedef device::csi_io<device::SAU00> csi;
	csi csi_;

	// FatFS インターフェースの定義
	typedef device::PORT<device::port_no::P0,  device::bitpos::B0> card_select;	///< カード選択信号
	typedef device::PORT<device::port_no::P0,  device::bitpos::B1> card_power;	///< カード電源制御
	typedef device::PORT<device::port_no::P14, device::bitpos::B6> card_detect;	///< カード検出

	utils::sdc_io<csi, card_select, card_power, card_detect> sdc_(csi_);

	utils::command<64> command_;
}

const void* ivec_[] __attribute__ ((section (".ivec"))) = {
	/*  0 */  nullptr,
	/*  1 */  nullptr,
	/*  2 */  nullptr,
	/*  3 */  nullptr,
	/*  4 */  nullptr,
	/*  5 */  nullptr,
	/*  6 */  nullptr,
	/*  7 */  nullptr,
	/*  8 */  nullptr,
	/*  9 */  nullptr,
	/* 10 */  nullptr,
	/* 11 */  nullptr,
	/* 12 */  nullptr,
	/* 13 */  nullptr,
	/* 14 */  nullptr,
	/* 15 */  nullptr,
	/* 16 */  reinterpret_cast<void*>(uart_.send_task),
	/* 17 */  reinterpret_cast<void*>(uart_.recv_task),
	/* 18 */  reinterpret_cast<void*>(uart_.error_task),
	/* 19 */  nullptr,
	/* 20 */  nullptr,
	/* 21 */  nullptr,
	/* 22 */  nullptr,
	/* 23 */  nullptr,
	/* 24 */  nullptr,
	/* 25 */  nullptr,
	/* 26 */  reinterpret_cast<void*>(itm_.task),
};

extern "C" {
	void sci_putch(char ch)
	{
		uart_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		uart_.puts(str);
	}

	char sci_getch(void)
	{
		return uart_.getch();
	}

	uint16_t sci_length()
	{
		return uart_.recv_length();
	}

	DSTATUS disk_initialize(BYTE drv) {
		return sdc_.at_mmc().disk_initialize(drv);
	}

	DSTATUS disk_status(BYTE drv) {
		return sdc_.at_mmc().disk_status(drv);
	}

	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_read(drv, buff, sector, count);
	}

	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdc_.at_mmc().disk_write(drv, buff, sector, count);
	}

	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdc_.at_mmc().disk_ioctl(drv, ctrl, buff);
	}

	DWORD get_fattime(void) {
		return 0;
	}
};

namespace {

	uint8_t v_ = 91;
	uint8_t m_ = 123;
	uint8_t rand_()
	{
		v_ += v_ << 2;
		++v_;
		uint8_t n = 0;
		if(m_ & 0x02) n = 1;
		if(m_ & 0x40) n ^= 1;
		m_ += m_;
		if(n == 0) ++m_;
		return v_ ^ m_;
	}

	bool create_test_file_(const char* fname, uint32_t size)
	{
		utils::format("SD Write test...\n");

		uint8_t buff[512];
		for(uint16_t i = 0; i < sizeof(buff); ++i) {
			buff[i] = rand_();
		}

		auto st = itm_.get_counter();
		FIL fp;
		if(f_open(&fp, fname, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) {
			utils::format("Can't create file: '%s'\n") % fname;
			return false;
		}
		auto rs = size;
		while(rs > 0) {
			UINT sz = sizeof(buff);
			if(sz > rs) sz = rs;
			UINT bw;
			f_write(&fp, buff, sz, &bw);
			rs -= bw;
		}
		f_close(&fp);

		auto ed = itm_.get_counter();
		uint32_t len;
		if(ed > st) len = ed - st;
		else len = 65536 + ed - st;
		utils::format("Write frame: %d\n") % len;
		auto pbyte = size * 60 / len;
		utils::format("Write: %d Bytes/Sec\n") % pbyte;
		utils::format("Write: %d KBytes/Sec\n") % (pbyte / 1024);

		return true;
	}

	void test_all_()
	{
		utils::format("SD Speed test start...\n");

		const char* test_file = { "TEST.BIN" };
		uint32_t size = 1024L * 1024L;
		if(!create_test_file_(test_file, size)) {
			return;
		}

		auto st = itm_.get_counter();

		utils::format("SD Read test...\n");
		FIL fp;
		if(f_open(&fp, test_file, FA_READ) != FR_OK) {
			utils::format("Can't read file: '%s'\n") % test_file;
		}
		auto rs = size;
		while(rs > 0) {
			uint8_t buff[512];
			UINT rb;
			UINT sz = sizeof(buff);
			if(sz > rs) sz = rs;
			f_read(&fp, buff, sz, &rb);
			rs -= rb;
		}
		f_close(&fp);

		auto ed = itm_.get_counter();
		uint32_t len;
		if(ed > st) len = ed - st;
		else len = 65536 + ed - st;
		utils::format("Read frame: %d\n") % len;
		auto pbyte = size * 60 / len;
		utils::format("Read: %d Bytes/Sec\n") % pbyte;
		utils::format("Read: %d KBytes/Sec\n") % (pbyte / 1024);
	}
}

int main(int argc, char* argv[])
{
	using namespace device;

	utils::port::pullup_all();  ///< 安全の為、全ての入力をプルアップ

	PM4.B3 = 0;  // output

	// インターバル・タイマー開始
	{
		uint8_t intr_level = 1;
		itm_.start(60, intr_level);
	}

	// UART 開始
	{
		uint8_t intr_level = 1;
		uart_.start(115200, intr_level);
	}

	sdc_.initialize();

	uart_.puts("Start RL78/G13 SD-CARD Access sample\n");

	command_.set_prompt("# ");

	uint8_t n = 0;
	while(1) {
		itm_.sync();

		sdc_.service();

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			auto cmdn = command_.get_words();
			if(cmdn >= 1) {
				bool f = false;
				if(command_.cmp_word(0, "dir")) {
					sdc_.dir("");
					f = true;
				} else if(command_.cmp_word(0, "speed")) {
					test_all_();
					f = true;
				}
				if(!f) {
					char tmp[16];
					command_.get_word(0, sizeof(tmp), tmp);
					utils::format("Command error: '%s'\n") % tmp;
				}
			}
		}

		++n;
		if(n >= 30) n = 0;
		P4.B3 = n < 10 ? false : true;
	}
}
<|endoftext|>


<commit_before>/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */

//---------------------------------------------------------------------------
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "Help.h"
#include "Config.h"
//---------------------------------------------------------------------------

//***************************************************************************
//
//***************************************************************************

//---------------------------------------------------------------------------
int Help()
{
    TEXTOUT("Usage: \"MediaInfo [-Options...] FileName1 [Filename2...]\"");
    TEXTOUT("");
    TEXTOUT("Options:");
    TEXTOUT("--Help, -h");
    TEXTOUT("                    Display this help and exit");
    TEXTOUT("--Help-Output");
    TEXTOUT("                    Display help for Output= option");
    TEXTOUT("--Help-AnOption");
    TEXTOUT("                    Display help for \"AnOption\"");
    TEXTOUT("--Version");
    TEXTOUT("                    Display MediaInfo version and exit");
    TEXTOUT("");
    TEXTOUT("--Full , -f");
    TEXTOUT("                    Full information Display (all internal tags)");
    TEXTOUT("--Output=HTML");
    TEXTOUT("                    Full information Display with HTML tags");
    TEXTOUT("--Output=XML");
    TEXTOUT("                    Full information Display with XML tags");
    TEXTOUT("--Output=...y");
    TEXTOUT("                    Template defined information Display");
    TEXTOUT("--Info-Parameters");
    TEXTOUT("                    Display list of Inform= parameters");
    TEXTOUT("");
    TEXTOUT("--Language=raw");
    TEXTOUT("                    Display non-translated unique identifiers (internal text)");
    TEXTOUT("--LogFile=...");
    TEXTOUT("                    Save the output in the specified file");
    TEXTOUT("--BOM");
    TEXTOUT("                    Byte order mark for UTF-8 output");
    TEXTOUT("");
    TEXTOUT("--Ssl_CertificateFileName=...");
    TEXTOUT("                    File name of the SSL certificate.");
    TEXTOUT("                    The default format is \"PEM\" and can be changed");
    TEXTOUT("                    with --Ssl_CertificateFormat.");
    TEXTOUT("--Ssl_CertificateFormat=...");
    TEXTOUT("                    File format of the SSL certificate.");
    TEXTOUT("                    Supported formats are \"PEM\" and \"DER\"");
    TEXTOUT("--Ssl_PrivateKeyFileName=...");
    TEXTOUT("                    File name of the SSL private key.");
    TEXTOUT("                    The default format is \"PEM\" and can be changed");
    TEXTOUT("                    with --Ssl_PrivateKeyFormat.");
    TEXTOUT("                    Note: private key with a password is not supported.");
    TEXTOUT("--Ssl_PrivateKeyFormat=...");
    TEXTOUT("                    File format of the SSL private key.");
    TEXTOUT("                    Supported formats are \"PEM\" and \"DER\"");
    TEXTOUT("--Ssl_CertificateAuthorityFileName=...");
    TEXTOUT("                    File name of the SSL certificate authorities");
    TEXTOUT("                    to verify the peer with.");
    TEXTOUT("--Ssl_CertificateAuthorityPath=...");
    TEXTOUT("                    Path of the SSL certificate authorities");
    TEXTOUT("                    to verify the peer with.");
    TEXTOUT("--Ssl_CertificateRevocationListFileName=...");
    TEXTOUT("                    File name of the SSL certificate revocation list.");
    TEXTOUT("                    The format is \"PEM\"");
    TEXTOUT("--Ssl_IgnoreSecurity=...");
    TEXTOUT("                    Does not verify the authenticity of the peer's certificate");
    TEXTOUT("                    Use it at your own risks");
    TEXTOUT("--Ssh_PublicKeyFileName=...");
    TEXTOUT("                    File name of the SSH private key.");
    TEXTOUT("                    Default is $HOME/.ssh/id_rsa.pub or $HOME/.ssh/id_dsa.pub");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"id_rsa.pub\" or \"id_dsa.pub\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("                    Note: you need to set both public and private key.");
    TEXTOUT("--Ssh_PrivateKeyFileName=...");
    TEXTOUT("                    File name of the SSH private key.");
    TEXTOUT("                    Default is $HOME/.ssh/id_rsa or $HOME/.ssh/id_dsa");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"id_rsa\" or \"id_dsa\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("                    Note: you need to set both public and private key.");
    TEXTOUT("                    Note: private key with a password is not supported.");
    TEXTOUT("--Ssh_KnownHostsFileName=...");
    TEXTOUT("                    File name of the known hosts");
    TEXTOUT("                    The format is the OpenSSH file format (libssh2)");
    TEXTOUT("                    Default is $HOME/.ssh/known_hosts");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"known_hosts\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("--Ssh_IgnoreSecurity");
    TEXTOUT("                    Does not verify the authenticity of the peer");
    TEXTOUT("                    (you don't need to accept the key with ssh first)");
    TEXTOUT("                    Use it at your own risks");

    return -1;
}

//---------------------------------------------------------------------------
int Help_Nothing()
{
    TEXTOUT("Usage: \"MediaInfo [-Options...] FileName1 [Filename2...]\"");
    TEXTOUT("\"MediaInfo --Help\" for displaying more information");

    return -1;
}

//---------------------------------------------------------------------------
int Help_Output()
{
    TEXTOUT("--Output=...  Specify a template (BETA)");
    TEXTOUT("Usage: \"MediaInfo --Output=[xxx;]Text FileName\"");
    TEXTOUT("");
    TEXTOUT("xxx can be: General, Video, Audio, Text, Chapter, Image, Menu");
    TEXTOUT("Text can be the template text, or a filename");
    TEXTOUT("     Filename must be in the form file://filename");
    TEXTOUT("");
    TEXTOUT("See --Info-Parameters for available parameters in the text");
    TEXTOUT("(Parameters must be surrounded by \"%\" sign)");
    TEXTOUT("");
    TEXTOUT("Example: \"MediaInfo --Output=Video;%AspectRatio% FileName\"");
    TEXTOUT("");
    TEXTOUT("Example: \"MediaInfo --Output=Video;file://Video.txt FileName\"");
    TEXTOUT("and Video.txt contains ");
    TEXTOUT("\"%DisplayAspectRatio%\"        for Video Aspect Ratio.");
    TEXTOUT("");
    TEXTOUT("Example: \"MediaInfo --Output=file://Text.txt FileName\"");
    TEXTOUT("and Text.txt contains");
    TEXTOUT("\"Video;%DisplayAspectRatio%\"  for Video Aspect Ratio.");
    TEXTOUT("\"Audio;%Format%\"              for Audio Format.");

    return -1;
}

//---------------------------------------------------------------------------
int Help_Security()
{
    TEXTOUT("Usage: \"MediaInfo [-Options...] FileName1 [Filename2...]\"");
    TEXTOUT("\"MediaInfo --Help\" for displaying more information");

    return -1;
}

<commit_msg>add EBUCore to help<commit_after>/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */

//---------------------------------------------------------------------------
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "Help.h"
#include "Config.h"
//---------------------------------------------------------------------------

//***************************************************************************
//
//***************************************************************************

//---------------------------------------------------------------------------
int Help()
{
    TEXTOUT("Usage: \"MediaInfo [-Options...] FileName1 [Filename2...]\"");
    TEXTOUT("");
    TEXTOUT("Options:");
    TEXTOUT("--Help, -h");
    TEXTOUT("                    Display this help and exit");
    TEXTOUT("--Help-Output");
    TEXTOUT("                    Display help for Output= option");
    TEXTOUT("--Help-AnOption");
    TEXTOUT("                    Display help for \"AnOption\"");
    TEXTOUT("--Version");
    TEXTOUT("                    Display MediaInfo version and exit");
    TEXTOUT("");
    TEXTOUT("--Full , -f");
    TEXTOUT("                    Full information Display (all internal tags)");
    TEXTOUT("--Output=HTML");
    TEXTOUT("                    Full information Display with HTML tags");
    TEXTOUT("--Output=XML");
    TEXTOUT("                    Full information Display with XML tags");
    TEXTOUT("--Output=EBUCore");
    TEXTOUT("                    Full information Display with EBUCore compliant XML tags")
    TEXTOUT("--Output=...y");
    TEXTOUT("                    Template defined information Display");
    TEXTOUT("--Info-Parameters");
    TEXTOUT("                    Display list of Inform= parameters");
    TEXTOUT("");
    TEXTOUT("--Language=raw");
    TEXTOUT("                    Display non-translated unique identifiers (internal text)");
    TEXTOUT("--LogFile=...");
    TEXTOUT("                    Save the output in the specified file");
    TEXTOUT("--BOM");
    TEXTOUT("                    Byte order mark for UTF-8 output");
    TEXTOUT("");
    TEXTOUT("--Ssl_CertificateFileName=...");
    TEXTOUT("                    File name of the SSL certificate.");
    TEXTOUT("                    The default format is \"PEM\" and can be changed");
    TEXTOUT("                    with --Ssl_CertificateFormat.");
    TEXTOUT("--Ssl_CertificateFormat=...");
    TEXTOUT("                    File format of the SSL certificate.");
    TEXTOUT("                    Supported formats are \"PEM\" and \"DER\"");
    TEXTOUT("--Ssl_PrivateKeyFileName=...");
    TEXTOUT("                    File name of the SSL private key.");
    TEXTOUT("                    The default format is \"PEM\" and can be changed");
    TEXTOUT("                    with --Ssl_PrivateKeyFormat.");
    TEXTOUT("                    Note: private key with a password is not supported.");
    TEXTOUT("--Ssl_PrivateKeyFormat=...");
    TEXTOUT("                    File format of the SSL private key.");
    TEXTOUT("                    Supported formats are \"PEM\" and \"DER\"");
    TEXTOUT("--Ssl_CertificateAuthorityFileName=...");
    TEXTOUT("                    File name of the SSL certificate authorities");
    TEXTOUT("                    to verify the peer with.");
    TEXTOUT("--Ssl_CertificateAuthorityPath=...");
    TEXTOUT("                    Path of the SSL certificate authorities");
    TEXTOUT("                    to verify the peer with.");
    TEXTOUT("--Ssl_CertificateRevocationListFileName=...");
    TEXTOUT("                    File name of the SSL certificate revocation list.");
    TEXTOUT("                    The format is \"PEM\"");
    TEXTOUT("--Ssl_IgnoreSecurity=...");
    TEXTOUT("                    Does not verify the authenticity of the peer's certificate");
    TEXTOUT("                    Use it at your own risks");
    TEXTOUT("--Ssh_PublicKeyFileName=...");
    TEXTOUT("                    File name of the SSH private key.");
    TEXTOUT("                    Default is $HOME/.ssh/id_rsa.pub or $HOME/.ssh/id_dsa.pub");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"id_rsa.pub\" or \"id_dsa.pub\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("                    Note: you need to set both public and private key.");
    TEXTOUT("--Ssh_PrivateKeyFileName=...");
    TEXTOUT("                    File name of the SSH private key.");
    TEXTOUT("                    Default is $HOME/.ssh/id_rsa or $HOME/.ssh/id_dsa");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"id_rsa\" or \"id_dsa\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("                    Note: you need to set both public and private key.");
    TEXTOUT("                    Note: private key with a password is not supported.");
    TEXTOUT("--Ssh_KnownHostsFileName=...");
    TEXTOUT("                    File name of the known hosts");
    TEXTOUT("                    The format is the OpenSSH file format (libssh2)");
    TEXTOUT("                    Default is $HOME/.ssh/known_hosts");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"known_hosts\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("--Ssh_IgnoreSecurity");
    TEXTOUT("                    Does not verify the authenticity of the peer");
    TEXTOUT("                    (you don't need to accept the key with ssh first)");
    TEXTOUT("                    Use it at your own risks");

    return -1;
}

//---------------------------------------------------------------------------
int Help_Nothing()
{
    TEXTOUT("Usage: \"MediaInfo [-Options...] FileName1 [Filename2...]\"");
    TEXTOUT("\"MediaInfo --Help\" for displaying more information");

    return -1;
}

//---------------------------------------------------------------------------
int Help_Output()
{
    TEXTOUT("--Output=...  Specify a template (BETA)");
    TEXTOUT("Usage: \"MediaInfo --Output=[xxx;]Text FileName\"");
    TEXTOUT("");
    TEXTOUT("xxx can be: General, Video, Audio, Text, Chapter, Image, Menu");
    TEXTOUT("Text can be the template text, or a filename");
    TEXTOUT("     Filename must be in the form file://filename");
    TEXTOUT("");
    TEXTOUT("See --Info-Parameters for available parameters in the text");
    TEXTOUT("(Parameters must be surrounded by \"%\" sign)");
    TEXTOUT("");
    TEXTOUT("Example: \"MediaInfo --Output=Video;%AspectRatio% FileName\"");
    TEXTOUT("");
    TEXTOUT("Example: \"MediaInfo --Output=Video;file://Video.txt FileName\"");
    TEXTOUT("and Video.txt contains ");
    TEXTOUT("\"%DisplayAspectRatio%\"        for Video Aspect Ratio.");
    TEXTOUT("");
    TEXTOUT("Example: \"MediaInfo --Output=file://Text.txt FileName\"");
    TEXTOUT("and Text.txt contains");
    TEXTOUT("\"Video;%DisplayAspectRatio%\"  for Video Aspect Ratio.");
    TEXTOUT("\"Audio;%Format%\"              for Audio Format.");

    return -1;
}

//---------------------------------------------------------------------------
int Help_Security()
{
    TEXTOUT("Usage: \"MediaInfo [-Options...] FileName1 [Filename2...]\"");
    TEXTOUT("\"MediaInfo --Help\" for displaying more information");

    return -1;
}

<|endoftext|>


<commit_before>/*
 * File open modal.
 */

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>

#include <algorithm>
#include <regex>
#include <string>
#include <vector>

#include <GL/gl3w.h>
#include <SDL2/SDL.h>

#include "imgui.h"

extern "C" {
#include "util.h"
#include "snepulator.h"
#include "config.h"
#include "sms.h"
}

#include "open.h"

/* Global state */
extern Snepulator_State state;

/* Open-dialogue state */
File_Open_State open_state = { .title = "Open" };

/* Current path */
/* TODO: Make size dynamic */
static char path[160] = { '\0' };

/*
 * Render the file-open modal.
 */
void snepulator_render_open_modal (void)
{
    if (ImGui::BeginPopupModal (open_state.title, NULL, ImGuiWindowFlags_AlwaysAutoResize |
                                                     ImGuiWindowFlags_NoMove |
                                                     ImGuiWindowFlags_NoScrollbar))
    {
        int width = (state.host_width / 2 > 512) ? state.host_width / 2 : 512;
        int height = (state.host_height / 2 > 384) ? state.host_width / 2 : 384;

        /* State */
        /* TODO: path_cached needs to clear whenever the regex changes */
        static bool path_cached = false;
        static std::vector<std::string> file_list;
        static int selected_file = 0;
        bool open_action = false;

        std::regex file_regex (open_state.regex);

        if (!path_cached)
        {
            /* Retrieve initial path from config */
            if (path [0] == '\0')
            {
                char *stored_path = NULL;

                if (config_string_get ("paths", "sms_roms", &stored_path) == 0)
                {
                    strncpy (path, stored_path, 179);
                }
            }

            /* Fallback to home directory */
            if (path [0] == '\0')
            {
                char *home_path = getenv ("HOME");

                if (home_path != NULL)
                {
                    sprintf (path, "%s/", home_path);
                }
                else
                {
                    snepulator_error ("Error", "${HOME} not defined.");
                    return;
                }
            }

            /* File listing */
            DIR *dir = opendir (path);
            struct dirent *entry = NULL;
            std::string entry_string;

            if (dir != NULL)
            {
                for (entry = readdir (dir); entry != NULL; entry = readdir (dir))
                {
                    /* Ignore "." directory */
                    if (strcmp (entry->d_name, ".") == 0)
                    {
                        continue;
                    }

                    /* Hide ".." directory if we're already at the root */
                    if ((strcmp (path, "/") == 0) && (strcmp (entry->d_name, "..") == 0))
                    {
                        continue;
                    }

                    entry_string = std::string (entry->d_name);

                    /* Show directories as ending with '/' */
                    if (entry->d_type == DT_DIR)
                    {
                        entry_string += '/';
                    }
                    /* Only list files that have a valid ROM extension */
                    else if (!std::regex_match (entry_string, file_regex))
                    {
                            continue;
                    }

                    file_list.push_back (entry_string);
                }
                std::sort (file_list.begin (), file_list.end ());
            }

            path_cached = true;
        }

        ImGui::Text ("%s", path);

        /* Current directory contents */
        ImGui::BeginChild ("Files", ImVec2 (width, height - 64), true);
        for (int i = 0; i < file_list.size (); i++)
        {
            /* TODO: Can we get the text height rather than hard-coding it? */
            ImVec2 draw_cursor = ImGui::GetCursorScreenPos ();
            bool hovering = ImGui::IsMouseHoveringRect (draw_cursor, ImVec2 (draw_cursor.x + 350, draw_cursor.y + 16));

            /* Click to select */
            if (hovering && ImGui::IsMouseClicked (0))
            {
                selected_file = i;
            }

            /* Double-click to open */
            if (hovering && ImGui::IsMouseDoubleClicked (0))
            {
                open_action = true;
            }

            /* Render the selected file in green, hovered file in yellow, and others with the text default */
            if (i == selected_file)
            {
                ImGui::TextColored (ImVec4 (0.5f, 1.0f, 0.5f, 1.0f), "%s", file_list[i].c_str ());
            }
            else if (hovering)
            {
                ImGui::TextColored (ImVec4 (1.0f, 1.0f, 0.5f, 1.0f), "%s", file_list[i].c_str ());
            }
            else
            {
                ImGui::Text ("%s", file_list[i].c_str ());
            }

        }
        ImGui::EndChild ();

        /* Buttons */
        ImGui::Spacing ();
        ImGui::SameLine (ImGui::GetContentRegionAvail().x + 16 - 128 - 128);
        if (ImGui::Button ("Cancel", ImVec2 (120,0))) {
            if (state.ready)
            {
                /* TODO: Preserve previous state */
                state.running = true;
            }
            ImGui::CloseCurrentPopup ();
        }
        ImGui::SameLine ();
        if (ImGui::Button ("Open", ImVec2 (120,0))) {
            open_action = true;
        }

        /* Open action */
        if (open_action)
        {
            /* Directory */
            if (file_list[selected_file].back () == '/')
            {
                char new_path[160] = { '\0' };

                if (strcmp (file_list [selected_file].c_str (), "../") == 0)
                {
                    /* Go up to the parent directory */
                    /* First, remove the final slash from the path */
                    char *end_slash = strrchr (path, '/');
                    if (end_slash == NULL)
                    {
                        snepulator_error ("Error", "Failed to change directory.");
                        return;
                    }
                    end_slash [0] = '\0';

                    /* Now, zero the path name after the new final slash */
                    end_slash = strrchr (path, '/');
                    if (end_slash == NULL)
                    {
                        snepulator_error ("Error", "Failed to change directory.");
                        return;
                    }
                    memset (&end_slash [1], 0, strlen (&end_slash [1]));
                }
                else
                {
                    /* Enter new directory */
                    sprintf (new_path, "%s%s", path, file_list [selected_file].c_str ());
                    strcpy (path, new_path);
                }
                config_string_set ("paths", "sms_roms", path);
                config_write ();
            }
            /* ROM */
            else
            {
                char new_path[160] = { '\0' };
                sprintf (new_path, "%s%s", path, file_list [selected_file].c_str ());

                open_state.callback (new_path);

                ImGui::CloseCurrentPopup ();
            }
            path_cached = false;
            file_list.clear ();
        }

        ImGui::EndPopup ();
    }
}
<commit_msg>maint: Fixup strncpy length<commit_after>/*
 * File open modal.
 */

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>

#include <algorithm>
#include <regex>
#include <string>
#include <vector>

#include <GL/gl3w.h>
#include <SDL2/SDL.h>

#include "imgui.h"

extern "C" {
#include "util.h"
#include "snepulator.h"
#include "config.h"
#include "sms.h"
}

#include "open.h"

/* Global state */
extern Snepulator_State state;

/* Open-dialogue state */
File_Open_State open_state = { .title = "Open" };

/* Current path */
/* TODO: Make size dynamic */
static char path[160] = { '\0' };

/*
 * Render the file-open modal.
 */
void snepulator_render_open_modal (void)
{
    if (ImGui::BeginPopupModal (open_state.title, NULL, ImGuiWindowFlags_AlwaysAutoResize |
                                                     ImGuiWindowFlags_NoMove |
                                                     ImGuiWindowFlags_NoScrollbar))
    {
        int width = (state.host_width / 2 > 512) ? state.host_width / 2 : 512;
        int height = (state.host_height / 2 > 384) ? state.host_width / 2 : 384;

        /* State */
        /* TODO: path_cached needs to clear whenever the regex changes */
        static bool path_cached = false;
        static std::vector<std::string> file_list;
        static int selected_file = 0;
        bool open_action = false;

        std::regex file_regex (open_state.regex);

        if (!path_cached)
        {
            /* Retrieve initial path from config */
            if (path [0] == '\0')
            {
                char *stored_path = NULL;

                if (config_string_get ("paths", "sms_roms", &stored_path) == 0)
                {
                    strncpy (path, stored_path, 159);
                }
            }

            /* Fallback to home directory */
            if (path [0] == '\0')
            {
                char *home_path = getenv ("HOME");

                if (home_path != NULL)
                {
                    sprintf (path, "%s/", home_path);
                }
                else
                {
                    snepulator_error ("Error", "${HOME} not defined.");
                    return;
                }
            }

            /* File listing */
            DIR *dir = opendir (path);
            struct dirent *entry = NULL;
            std::string entry_string;

            if (dir != NULL)
            {
                for (entry = readdir (dir); entry != NULL; entry = readdir (dir))
                {
                    /* Ignore "." directory */
                    if (strcmp (entry->d_name, ".") == 0)
                    {
                        continue;
                    }

                    /* Hide ".." directory if we're already at the root */
                    if ((strcmp (path, "/") == 0) && (strcmp (entry->d_name, "..") == 0))
                    {
                        continue;
                    }

                    entry_string = std::string (entry->d_name);

                    /* Show directories as ending with '/' */
                    if (entry->d_type == DT_DIR)
                    {
                        entry_string += '/';
                    }
                    /* Only list files that have a valid ROM extension */
                    else if (!std::regex_match (entry_string, file_regex))
                    {
                            continue;
                    }

                    file_list.push_back (entry_string);
                }
                std::sort (file_list.begin (), file_list.end ());
            }

            path_cached = true;
        }

        ImGui::Text ("%s", path);

        /* Current directory contents */
        ImGui::BeginChild ("Files", ImVec2 (width, height - 64), true);
        for (int i = 0; i < file_list.size (); i++)
        {
            /* TODO: Can we get the text height rather than hard-coding it? */
            ImVec2 draw_cursor = ImGui::GetCursorScreenPos ();
            bool hovering = ImGui::IsMouseHoveringRect (draw_cursor, ImVec2 (draw_cursor.x + 350, draw_cursor.y + 16));

            /* Click to select */
            if (hovering && ImGui::IsMouseClicked (0))
            {
                selected_file = i;
            }

            /* Double-click to open */
            if (hovering && ImGui::IsMouseDoubleClicked (0))
            {
                open_action = true;
            }

            /* Render the selected file in green, hovered file in yellow, and others with the text default */
            if (i == selected_file)
            {
                ImGui::TextColored (ImVec4 (0.5f, 1.0f, 0.5f, 1.0f), "%s", file_list[i].c_str ());
            }
            else if (hovering)
            {
                ImGui::TextColored (ImVec4 (1.0f, 1.0f, 0.5f, 1.0f), "%s", file_list[i].c_str ());
            }
            else
            {
                ImGui::Text ("%s", file_list[i].c_str ());
            }

        }
        ImGui::EndChild ();

        /* Buttons */
        ImGui::Spacing ();
        ImGui::SameLine (ImGui::GetContentRegionAvail().x + 16 - 128 - 128);
        if (ImGui::Button ("Cancel", ImVec2 (120,0))) {
            if (state.ready)
            {
                /* TODO: Preserve previous state */
                state.running = true;
            }
            ImGui::CloseCurrentPopup ();
        }
        ImGui::SameLine ();
        if (ImGui::Button ("Open", ImVec2 (120,0))) {
            open_action = true;
        }

        /* Open action */
        if (open_action)
        {
            /* Directory */
            if (file_list[selected_file].back () == '/')
            {
                char new_path[160] = { '\0' };

                if (strcmp (file_list [selected_file].c_str (), "../") == 0)
                {
                    /* Go up to the parent directory */
                    /* First, remove the final slash from the path */
                    char *end_slash = strrchr (path, '/');
                    if (end_slash == NULL)
                    {
                        snepulator_error ("Error", "Failed to change directory.");
                        return;
                    }
                    end_slash [0] = '\0';

                    /* Now, zero the path name after the new final slash */
                    end_slash = strrchr (path, '/');
                    if (end_slash == NULL)
                    {
                        snepulator_error ("Error", "Failed to change directory.");
                        return;
                    }
                    memset (&end_slash [1], 0, strlen (&end_slash [1]));
                }
                else
                {
                    /* Enter new directory */
                    sprintf (new_path, "%s%s", path, file_list [selected_file].c_str ());
                    strcpy (path, new_path);
                }
                config_string_set ("paths", "sms_roms", path);
                config_write ();
            }
            /* ROM */
            else
            {
                char new_path[160] = { '\0' };
                sprintf (new_path, "%s%s", path, file_list [selected_file].c_str ());

                open_state.callback (new_path);

                ImGui::CloseCurrentPopup ();
            }
            path_cached = false;
            file_list.clear ();
        }

        ImGui::EndPopup ();
    }
}
<|endoftext|>