電音の工場ブログ

趣味の電子工作を中心としたブログです.音モノの工作が多いです.

avr-gcc で工作(そのA)

avr-gcc で工作(そのA)

ブザーつけました。モノは秋月電子で売られているコレです。PORTBのPB4に DTC144E でオープンコレクタで VCC0 を掛ける形で接続しています。今回は回路図は省略*1。あ、消費電流を測らなくては…

これを使って、ロータリエンコーダを回すとクリック音が出るようにしてあります。経験的に 10msec ぐらいの長さをクリック音長として採用しました。

また同時にロータリエンコーダによる変化が遅れて有効となるような仕組みを入れてあります。これは、最終的な出来上がりでは制御される先にメカニカル・リレーが付くためです。ロータリエンコーダをぐりぐり回してその都度リレーがガチガチ言っていては心臓に良くないので、値が確定してから0.5秒ぐらいのちに有効となるようにしています。ここでは有効となったら PA0 の LED7セグメントLEDの一の位の dot を光らせるようにしています。

べたクロックでポートに出力*2したりして汚いですが、UIの実験と割り切って目を瞑ります*3

今後、ハードウェア的にやることは、

  • 入力プッシュスイッチ
  • 出力ポート回路
  • 設定用DIPスイッチ
  • MIDI入力回路
  • (7セグメントLED回路の作り直し)

の付加です。ケースの設計/加工と足並みを揃えながら進める予定です。

以下ソースコード

/*
  7seg. LED w/ Rotary Encoder
*/
#include 
#include 
#include 
#include 

#define RENC_DELAY_LEN 500;
#define SOUND_CLICK 10;
enum { LOW, HIGH, EDGE } ;

volatile uint8_t num = 128;
uint8_t DIGIT[] = { 0x03, 0x9F, 0x25, 0x0D, 0x99, 0x49, 0x41, 0x1B, 0x01, 0x09 };
volatile uint8_t renc = HIGH;
volatile uint16_t renc_delay_cnt = RENC_DELAY_LEN;
volatile uint8_t click = 0;

/*
  PB5 serial data
  PB6 latch clock
  PB7 shift clock
*/
void send7seg (uint8_t dat)
{
  int i;

  for (i = 0; i < 8; i++, dat >>= 1) {
    if (dat & 0x01)
      sbi(PORTB, PB5);
    else
      cbi(PORTB, PB5);
    sbi(PORTB, PB7);
    cbi(PORTB, PB7);
  }
}

void load7seg (void)
{
  sbi(PORTB, PB6);
  cbi(PORTB, PB6);
}

void send (uint8_t dat, uint8_t dot)
{
  if (dot)  send7seg(DIGIT[dat % 10] & 0xFE);
  else      send7seg(DIGIT[dat % 10]);
  send7seg(DIGIT[(dat/10) % 10]);
  send7seg(DIGIT[dat / 100]);
  load7seg();
}

SIGNAL (SIG_OVERFLOW1)
{
  TCNT1 = 65536 - 1000 + 1;
  if (renc == EDGE) {
    if (bit_is_clear(PIND, PD3)) { // true falling edge
      renc = LOW;
      if (bit_is_clear(PIND, PD4)) {
        num++;
      } else {
        num--;
      }
      send(num, 0);
      renc_delay_cnt = RENC_DELAY_LEN;
      click = SOUND_CLICK;
    } else {
      renc = HIGH;
    }
  } else {
    if (bit_is_clear(PIND, PD3)) {
      if (renc == HIGH)
        renc = EDGE;
      else
        renc = LOW;
    } else {
      renc = HIGH;
    }
  }

  if (renc_delay_cnt)    --renc_delay_cnt;
  else                   send(num, 1);
  if (click) {
    sbi(PORTB, PB4);
    --click;
  } else {
    cbi(PORTB, PB4);
  }
}

void ioinit (void)
{
  DDRA = _BV (PA0);
  DDRB = _BV (PB4) | _BV (PB5) | _BV (PB6) | _BV (PB7);
  TCCR1B = _BV (CS11);
  TCNT1 = 65536 - 1000;
  timer_enable_int (_BV (TOIE1));
  cbi(PORTA, PA0);
  cbi(PORTB, PB4);
  sei();
}

int main(void)
{
  ioinit();
  send(num, 0);
  for (;;) {
    if (!renc_delay_cnt) {
      sbi(PORTA, PA0);
    } else {
      cbi(PORTA, PA0);
    }
  }

  return 0;
}

*1:だんだんいい加減になるなぁ。

*2:変化点だけにしないと。

*3:そろそろ本番用の構成を考えなくては。