UIAP KEYER

KEYERサンプルコード (電波文化祭5)

#include <Arduino.h>
#include <Wire.h>
#include <HardwareTimer.h>

// ==== ピン設定 ====
#define PIN_DOT   7   //パドル左
#define PIN_DASH  8   //パドル右
#define PIN_TONE  9   //トーン出力
#define PIN_SPEED A0  //速度調整用(ADC)
#define PIN_KEYOUT 2  //無線機用KEYOUT
#define PIN_SWA 10    //SW A
#define PIN_SWB 5     //SW B

// ==== 定数 ====

//スクイズ状態
#define SQZ_FREE 0
#define SQZ_SPC0 1
#define SQZ_SPC 2
#define SQZ_DOT0 3
#define SQZ_DOT 4
#define SQZ_DAH_CONT0 5
#define SQZ_DAH_CONT1 6
#define SQZ_DAH_CONT 7
#define SQZ_DASH 8

//パドル状態
#define PDL_DOT 1
#define PDL_DASH 2
#define PDL_FREE 0

#define SQUEEZE_TYPE 0  //スクイーズモード
#define PDL_RATIO 4 //短点・長点比率

#define WPM_MAX 40  //スピード最大値(WPM)
#define WPM_MIN 5   //スピード最小値(WPM)

// ==== 変数 ====
int key_spd = 1000;
int wpm = 20;
bool tone_enabled = false;
int squeeze = 0;
int paddle = PDL_FREE;
int paddle_old = PDL_FREE;

HardwareTimer timer(TIM1);  // TIM1を使用

// ==== パドル処理 ====
uint8_t job_paddle() {
  static uint32_t left_time = 0;
  uint8_t key_dot, key_dash;

  key_dot = (!digitalRead(PIN_DOT) || !digitalRead(PIN_SWA));
  key_dash = (!digitalRead(PIN_DASH) || !digitalRead(PIN_SWB));

  if (left_time != 0) {
    left_time--;
  } else {
    left_time = key_spd / 2;
    if (squeeze != SQZ_FREE) {
      squeeze--;
    }
  }

  if (squeeze != SQZ_FREE) {
    if (paddle_old == PDL_DOT && key_dash) paddle = PDL_DASH;
    else if (paddle_old == PDL_DASH && key_dot) paddle = PDL_DOT;
  }

  if (SQUEEZE_TYPE == 0) {
    if (squeeze > SQZ_DASH) paddle = PDL_FREE;
  } else {
    if (squeeze > SQZ_SPC) paddle = PDL_FREE;
  }

  if (squeeze > SQZ_SPC) return 1;
  else if (squeeze == SQZ_SPC || squeeze == SQZ_SPC0) return 0;

  if (paddle == PDL_FREE) {
    if (key_dot) paddle = PDL_DOT;
    else if (key_dash) paddle = PDL_DASH;
  }

  if (paddle == PDL_FREE) return 0;
  else {
    if (paddle == PDL_DOT) squeeze = SQZ_DOT;
    else {
      uint8_t dash_len = (SQZ_SPC * PDL_RATIO + 5) / 2;
      squeeze = SQZ_SPC + dash_len;
    }
    left_time = key_spd / 2;
    paddle_old = paddle;
    paddle = PDL_FREE;
    return 1;
  }

  return 0;
}

// ==== トーン制御ON ====
void startTone() {
  if (tone_enabled) return;
  tone_enabled = true;
  tone(PIN_TONE, 600);  // 600Hz
  digitalWrite(PIN_KEYOUT, HIGH);  // ON
}

// ==== トーン制御OFF ====
void stopTone() {
  noTone(PIN_TONE);
  tone_enabled = false;
  digitalWrite(PIN_KEYOUT, LOW);   // OFF
}

// ==== ADCからスピード読み込み ====
void update_speed_from_adc() {
  int adc = analogRead(PIN_SPEED);        // 0 .. 1023
  wpm = map(adc, 0, 1023, WPM_MIN, WPM_MAX);
  key_spd = 4687.5 / wpm;  // = (1200/wpm) /0.256
}

// ==== キーダウン ====
void keydown() {
  startTone();
}

// ==== キーアップ ====
void keyup() {
  stopTone();
}

// ==== タイマー割り込み ====
void onTimerInterrupt() {
  if (job_paddle()) keydown();
  else keyup();
}

// ==== セットアップ ====
void setup() {
  pinMode(PIN_DOT, INPUT_PULLUP);
  pinMode(PIN_DASH, INPUT_PULLUP);
  pinMode(PIN_SWA, INPUT_PULLUP);
  pinMode(PIN_SWB, INPUT_PULLUP);
  pinMode(PIN_TONE, OUTPUT);
  pinMode(PIN_KEYOUT, OUTPUT);
  pinMode(PIN_SPEED,INPUT_ANALOG);

  //タイマー設定 0.256msごとにタイマー割り込み
  timer.setOverflow(256, MICROSEC_FORMAT);  // 周期設定(256us)
  timer.attachInterrupt(onTimerInterrupt); // 割り込み設定
  timer.resume(); // タイマー開始
}

// ==== メインループ ====
void loop() {
  update_speed_from_adc(); // スピード調整用
  delay(100);
}


タイトルとURLをコピーしました