Renesas Rulz - Japan
Renesas Rulz - Japan
  • User
    Join or sign in
  • Site
  • Search Japan.RenesasRulz.com
  • User
  • Renesas Rulz
  • FAQ
  • パートナー
  • 半導体セミナ
  • eラーニング
  • ヘルプ
  • More
  • Cancel
  • かふぇルネ
  • がじぇるね
  • English Community
  • More
  • Cancel
がじぇっとるねさすコミュニティ
がじぇっとるねさすコミュニティ
GR-CITRUS 九州工業大学 情報工学部さんのArduino 簡易オシロスコープをGR-CITRUSに移植トライ中
  • Forums
  • Blog
  • Files
  • がじぇっとるねさす ゆーざー会 - Wiki
  • Tags
  • More
  • Cancel
  • New

 

 GR-SAKURA

 GR-KURUMI

 GR-COTTON

 GR-CITRUS

 GR-PEACH

 GR-KAEDE

 GR-ADZUKI

 GR-LYCHEE

 GR-ROSE

 GR-MANGO(*)

 SNShield

 Web Compiler

 IDE for GR

 TOPPERS関連

 女子美コラボ

 その他

 ※プロデューサミーティング中

 作り方使い方資料

 イベント関連

 作品記事

 体験記事

 その他

 

 ライブラリ

 ツール

 その他・過去ファイル

  • Replies 5 replies
  • Subscribers 434 subscribers
  • Views 8597 views
  • Users 0 members are here
  • 簡易オシロスコープ
  • gr-citrus
Options
  • Share
  • More
  • Cancel
Related Tags
  • DS18B20
  • gr-citrus
  • gr-sakura
  • i2c
  • IDE for GR
  • led
  • NeoPixel
  • WS8212B
  • 簡易オシロスコープ
Related

九州工業大学 情報工学部さんのArduino 簡易オシロスコープをGR-CITRUSに移植トライ中

NoMaY
NoMaY over 3 years ago

九州工業大学 情報工学部さんが公開されているArduino 簡易オシロスコープをGR-CITRUSに移植し始めました。(かふぇルネに投稿された質問で、もし何とか波形を見ることが出来ればデバッグの進み具合が変わって来そうなのになぁ、と思われるものが幾つかあったのが発端です。) ソースコードはArduino側とPC側に分かれていて、Arduino側はATmega328の内蔵周辺を直接操作していますのでGR-CITRUSのRX631に移植するのは簡単では無いのですが、まずは手始めに、PC側はそのままで兎にも角にも(多少インチキして)GR-CITRUSで読み込んだアナログデータの波形を表示させてみました。様子は以下の通りです。




PC側のソースコードはダウンロードしたものそのままですが、Arduino側のソースコードは最低限の部分のみ残して殆どをコメントアウトしてしまっています。そして、あくまで手始めとしてですが、アナログデータの読み込みに標準関数のanalogRead()を使用しました。更に、多少インチキしているのは、コンデンサ充電時の電圧上昇でトリガ検出してデータ読み込みを開始している訳ではなく、データ読み込み直前に予めコンデンサ充電開始操作を行ってからデータ読み込みを開始するようにハードコーディングしている点です。(ソースコード上では★★★★マークを付けています。)

Arduino側のオリジナルのkit_scope.ino

3771.kit_scope_20160320_original.ino.txt
// Kyutech Arduino Scope Prototype  v0.72                     Mar 20, 2016
//
//    (C) 2012-2016 M.Kurata Kyushu Institute of Technology
//
//    for Arduinos with a 5V-16MHz ATmega328.
//
//    use with "kit_scope.pde", a Proce55ing GUI sketch.
//
//    You don't need to worry about this warning message produced by the IDE.
//    "Low memory available, stability problems may occur."
//    コンパイル時、下記メッセージが表示されますが、問題ありません。
//    "スケッチが使用できるメモリが少なくなっています。動作が不安定になる可能性があります。"
//
//
//    Pin usage
//    
//    A0  trigger level voltage input    (connected to D6)
//    A1  oscilloscope probe ch1
//    A2  oscilloscope probe ch2
//    A3  oscilloscope probe ext  trigger
//    A4  reserved
//    A5  reserved
//    A6  reserved
//    A7  reserved
//    
//    D0  uart-rx
//    D1  uart-tx
//    D2  reserved
//    D3  calibration pulse wave output
//    D4  reserved
//    D5  pwm output for generating trigger level voltage
//    D6  analog comparator input (trigger level)
//    D7  reserved
//    D8  reserved
//    D9  reserved
//    D10 reserved
//    D11 reserved
//    D12 reserved
//    D13 LED output
//
//    different usage for dks2014 board.
//    A4  fgen-sync
//    D8  CH1 mode input  0..[0-10V]  1..[-5..5V]  (pull-up needed)
//    D9  CH2 mode input  0..[0-10V]  1..[-5..5V]  (pull-up needed)



const byte cfg_cupgain = 0; // the usage definition of the pins D7..D12
                            // 0: input  1:input(pulled-up)  2:output

word  oscversion = 0x0001;
word  oscvbg;              // band gap voltage in 10bits  0 means a failure.
word  oscconfig;           // bit0 -> if trigger voltage is 0:uncontrollable
                           //                               1:controllable
                           // bit1 -> optional-fgen is      0:not attached
                           //                               1:attached
                           // bit2 -> cupgain is            0:input
                           //                               1:output
byte  oscspeed   = 0;      // 0..3:real 4..7:equiv 8:roll
byte  oscinput   = 0;      // input signal selection  0:CH1 1:CH2 2:DUAL

byte  osctrig    = 0;      // trigger bit012-> 000:CH1 001:CH2 010:EXT
                           //                  011:built-in-pulse
                           //                  100:optional-fgen
                           //         bit4  -> 0:rising 1:falling
                           //         bit5  -> 0:auto   1:normal
word  osctdly    = 100;    // time of delayed trigger  100..30000 usec
byte  osctvolt;            // trigger level voltage (measured by adc) 0..255
byte  osctduty;            // trigger level duty  0..255

byte  osccupgain = 0;      // bit0  -> CH1 coupling        0:dc  1:ac
                           // bit1  -> CH2 coupling        0:dc  1:ac
                           // bit23 -> CH1 gain-selection  0,1,2,3
                           // bit45 -> CH2 gain-selection  0,1,2,3

long  oscofreq   = 1000;   // 31 .. 2000000Hz
byte  oscoduty   =   50;   // 0..100%

byte  fgen;                // 0..3: fgen-dipsw  255:no-fgen


#define TXBSZ 1100
#define RXBSZ  256 //  this must be 256.
#define RMBSZ  256 //  this must be 256.  for rollmode

int  txn, txr;
byte txcrc, rxn;
byte rmw, rmr, rmon;

byte txbuf[TXBSZ];
byte rxbuf[RXBSZ];

// since no huge packets are sent in rollmode,
// the last 256 bytes of the txbuf[] can be used
// as another buffer during the rollmode.
//
// byte rmbuf[RMBSZ];
#define rmbuf (&txbuf[TXBSZ - RMBSZ])

static const unsigned char crctbl[256] = {
    0x00, 0x85, 0x8F, 0x0A, 0x9B, 0x1E, 0x14, 0x91,
    0xB3, 0x36, 0x3C, 0xB9, 0x28, 0xAD, 0xA7, 0x22,
    0xE3, 0x66, 0x6C, 0xE9, 0x78, 0xFD, 0xF7, 0x72,
    0x50, 0xD5, 0xDF, 0x5A, 0xCB, 0x4E, 0x44, 0xC1,
    0x43, 0xC6, 0xCC, 0x49, 0xD8, 0x5D, 0x57, 0xD2,
    0xF0, 0x75, 0x7F, 0xFA, 0x6B, 0xEE, 0xE4, 0x61,
    0xA0, 0x25, 0x2F, 0xAA, 0x3B, 0xBE, 0xB4, 0x31,
    0x13, 0x96, 0x9C, 0x19, 0x88, 0x0D, 0x07, 0x82,

    0x86, 0x03, 0x09, 0x8C, 0x1D, 0x98, 0x92, 0x17,
    0x35, 0xB0, 0xBA, 0x3F, 0xAE, 0x2B, 0x21, 0xA4,
    0x65, 0xE0, 0xEA, 0x6F, 0xFE, 0x7B, 0x71, 0xF4,
    0xD6, 0x53, 0x59, 0xDC, 0x4D, 0xC8, 0xC2, 0x47,
    0xC5, 0x40, 0x4A, 0xCF, 0x5E, 0xDB, 0xD1, 0x54,
    0x76, 0xF3, 0xF9, 0x7C, 0xED, 0x68, 0x62, 0xE7,
    0x26, 0xA3, 0xA9, 0x2C, 0xBD, 0x38, 0x32, 0xB7,
    0x95, 0x10, 0x1A, 0x9F, 0x0E, 0x8B, 0x81, 0x04,

    0x89, 0x0C, 0x06, 0x83, 0x12, 0x97, 0x9D, 0x18,
    0x3A, 0xBF, 0xB5, 0x30, 0xA1, 0x24, 0x2E, 0xAB,
    0x6A, 0xEF, 0xE5, 0x60, 0xF1, 0x74, 0x7E, 0xFB,
    0xD9, 0x5C, 0x56, 0xD3, 0x42, 0xC7, 0xCD, 0x48,
    0xCA, 0x4F, 0x45, 0xC0, 0x51, 0xD4, 0xDE, 0x5B,
    0x79, 0xFC, 0xF6, 0x73, 0xE2, 0x67, 0x6D, 0xE8,
    0x29, 0xAC, 0xA6, 0x23, 0xB2, 0x37, 0x3D, 0xB8,
    0x9A, 0x1F, 0x15, 0x90, 0x01, 0x84, 0x8E, 0x0B,

    0x0F, 0x8A, 0x80, 0x05, 0x94, 0x11, 0x1B, 0x9E,
    0xBC, 0x39, 0x33, 0xB6, 0x27, 0xA2, 0xA8, 0x2D,
    0xEC, 0x69, 0x63, 0xE6, 0x77, 0xF2, 0xF8, 0x7D,
    0x5F, 0xDA, 0xD0, 0x55, 0xC4, 0x41, 0x4B, 0xCE,
    0x4C, 0xC9, 0xC3, 0x46, 0xD7, 0x52, 0x58, 0xDD,
    0xFF, 0x7A, 0x70, 0xF5, 0x64, 0xE1, 0xEB, 0x6E,
    0xAF, 0x2A, 0x20, 0xA5, 0x34, 0xB1, 0xBB, 0x3E,
    0x1C, 0x99, 0x93, 0x16, 0x87, 0x02, 0x08, 0x8D,
};


void initt0();
void rxinit(void);
void sett0(byte duty);
void sett2(long hz, byte duty);
void sysdown(int dly);
void txput0(byte ch);
void uartjob();
void wait0(word num, boolean uart);


void
rxinit(void)
{
    rxn = 0;
}


int
rxnum(void)
{
    return  rxn;
}


void
txinit(void)
{
    if (txn >= TXBSZ)
        sysdown(200);      // tx buffer overflow has been detected.
    txn = 0;
    txr = TXBSZ;
}

void
txgo(void)
{
    if (txr == TXBSZ)
        txr = 0;
}


boolean
txrunning()
{
    if (txn > txr)
        return  true;
    if (txr == TXBSZ)
        return  false;
    return  (UCSR0A & 0x40) ? false : true;
}


void
txfinish(boolean epilogue, boolean waircv __attribute__((unused)))
{
    byte    i;

    if (epilogue) {    // output epilogue mark
        for(i = 0; i < 4; i++) {
            txput0(0xa0);
            txput0(0xa0);
            txput0(0xa0);
            txput0(0xa0);
            uartjob();
        }
    }
    while(txrunning())
        uartjob();
    //if (waircv) {
    //    wait0(600, true);  // about 10ms wait
    //}
}


void
txput0(byte ch)
{
    // to reduce the cpu consumption,
    // venture to omit txn overflow check.
    // if programmed properly, such an overflow never occurs.
    // rxn(appears later) check is omitted as well.
    txbuf[txn++] = ch;
    txcrc = 0;
}


void
txput1(byte ch)
{
    txbuf[txn++] = ch;
    txcrc = crctbl[txcrc ^ ch];
}


void
txputcrc(boolean force_error)
{
    txput0((force_error) ? ++txcrc : txcrc);
}


void
rminit(boolean on)
{
    rmw = rmr = 0;
    rmon = (on) ? 1 : 0;
}


void
uartjob()
{
    byte    sts;

    sts = UCSR0A;
    if ((char)sts < 0)
        rxbuf[rxn++] = UDR0;
    // in case rxbuf[] overflow, no fatal situation happens.
    // because rxn is an 8 bit variable and rxbuf[] size is 256.

    if (rmon) {
        if (TIFR1 & 0x20)
            TIFR1  = 0x27;  // clear timer1 flags;
        if (ADCSRA & 0x10) {
            if (rmon == 1) {
                ICR1  = 100 - 1;      // 50us
                ADMUX = 0x62;
                rmon = 2;
                rmbuf[rmw++] = ADCH;  // CH1(A1pin) value
            }
            else if (rmon == 2) {
                ICR1  = 400 - 1;      // 200us
                ADMUX = 0x60;
                rmbuf[rmw++] = ADCH;  // CH2(A2pin) value
                rmon = 3;
            }
            else {
                ICR1  = 500 - 1;      // 250us
                ADMUX = 0x61;
                rmon = 1;
                osctvolt = ADCH;       // trigger level
            }
            ADCSRA = 0xb4;  // clear flags, 1MHz, adate on
            return; //in order to release cpu quickly
        }
    }

    if (txr < txn && (sts & 0x20)) {
        UCSR0A = (sts & 0xe3) | 0x40;
        UDR0 = txbuf[txr++];
    }
}


void
header(byte typ, byte reqid)
{
    static byte seq;

    txinit();
    uartjob();

    // prologue
    txput0(0xaa);
    txput0(0x55);
    txput0(0xa5);
    txput0(0x5a);

    uartjob();

    txput1(typ);
    if (typ == 3)
        txput1(seq++);  // rollmode
    else
        txput1(reqid);
    txput1(oscspeed);
    txput1(oscinput);
    uartjob();

    txput1(osctrig);
    txput1(osccupgain);
    txput1(osctdly >> 8);
    txput1(osctdly);
    uartjob();

    txput1(oscofreq >> 16);
    txput1(oscofreq >> 8);
    txput1(oscofreq);
    txput1(oscoduty);
    uartjob();
}


void
modereal()
{
    static const byte sitbl[4] = {20, 50, 100, 200}; // 20,50,100,200usec
    int    i, realnum;
    byte   vh, adch0, adch1, crcnt;
    word   ui1, sint1, sint2;

    rminit(false);

    realnum = 520;                                    // == 1040 >> 1
    sint1 = sint2 = ((word)sitbl[oscspeed & 3]) << 1;
    switch(oscinput) {
    default:
    case 0x00: adch0 = 0x61; adch1 = 0x61; break;
    case 0x01: adch0 = 0x62; adch1 = 0x62; break;
    case 0x02: adch0 = 0x61; adch1 = 0x62;
               sint1 = 40;  // 20usec
               sint2 = sint2 + sint2 - sint1;
               break;
    }

    uartjob();

    header(1, 0);
    // This data packet contines to MARC-A

    // reset and initialize timer1
    TCCR1B = 0x00; // stop, set normal mode
    TCCR1A = 0x00;
    TIMSK1 = 0x00; // no irq
    ICR1   = 0x0000;
    TCNT1  = 0x0000;
    TIFR1  = 0x27; // clear flags;

    // analog comparator setting
    // The D6 pin is the positive input.
    // The negative input is A1, A2, A3, or A4 pin.
    ACSR   = 0x94;  // analog comparator off
    DIDR1  = 0x03;  // disable the digital input function of D6 and D7.
    ADMUX  = 0x61 + (osctrig & 7); // select the negative input
    ADCSRA = 0x04;
    ADCSRB = 0x40;

    // start timer1 with pre=1/8
    // input capture noise canceler ON
    TCCR1B = (osctrig & 0x10) ? 0xc2 : 0x82;  // falling or rising edge
    ACSR   = 0x14; // capture-on, aco to caputure timer1
    TIFR1  = 0x27;

    // falling edge detection(rising edge for ICES1)
    // doesn't stabilize without a 20usec wait below.
    while(TCNT1 < 40)
        ;
    TIFR1 = 0x27;

    ui1 = (osctdly << 1);
    // wait until a trigger event happens
    while(true) {
        if (TIFR1 & 0x20) {
            // trigger event has happened.
            ui1 += ICR1;
            crcnt = 0; // to indicate that a trigger event has happened.
            break;
        }
        if (TCNT1 > 60000) {  // 30ms == 60000/2 us
            // 30ms has passed without detecting a trigger event.
            ui1 += TCNT1;
            crcnt = 1;
            break;
        }
        uartjob();
    }

    // trigger event has happened here or timeout.
    ACSR   = 0x94; // disable analog comparator
    ADCSRB = 0x00;
    ADCSRA = 0x84; // adc enable

    TCCR1B = 0x1a; // timer1 CTC-ICR1 mode pre1/8
    TCCR1A = 0x00; //             CTC mode;
    ICR1   = ui1;
    TIFR1  = 0x27; // clear flags

    ADMUX  = 0x60; // adc target is A0 pin to get trigger value;
    ADCSRB = 0x07; // timer1 capture event;
    ADCSRA = 0xf4; // adc auto trigger, force start 1st conversion

    // wait until the 1st conversion finishes. 
    while((ADCSRA & 0x10) == 0x00)
        uartjob();
    vh = ADCH;  // trigger level
    osctvolt = vh;

    ADMUX  = adch0;
    ADCSRA = 0xb4;   // clear flag, 1MHz, adate on

    // MARC-A  continued
    txput1(crcnt);  // 0:triggered  1:freerun
    txput1(vh);     // trigger level voltage
    txputcrc(false);
    txgo(); // start to trasmit a packet

    if (crcnt && (osctrig & 0x20) != 0)
        goto  ex;  // when no-trigger and normal/single

    sint1--;
    sint2--;
    crcnt = 0;
    for(i = 0; i < realnum; i++) {
        while(1) {
            if (TIFR1 & 0x20) {
                ICR1  = sint1;
                TIFR1 = 0x27; // clear timer1 flags;
            }
            if ((ADCSRA & 0x10) != 0x00)
                break;
            uartjob();
        }
        vh = ADCH;
        ADMUX = adch1;
        ADCSRA = 0xb4;   // clear flag, 1MHz, adate on
        txput1(vh);

        while(1) {
            if (TIFR1 & 0x20) {
                ICR1  = sint2;
                TIFR1 = 0x27; // clear timer1 flags;
            }
            if ((ADCSRA & 0x10) != 0x00)
                break;
            uartjob();
        }
        vh = ADCH;
        ADMUX = adch0;
        ADCSRA = 0xb4;   // clear flag, 1MHz, adate on
        txput1(vh);

        if (++crcnt >= 100) {
            crcnt = 0;
            txputcrc(false);
        }
    }
    if (crcnt == 20) {
        txputcrc(false);
    }
    else
        sysdown(1000);

ex:
    txfinish(true, true);
}


void
modeequiv()
{
    static const struct eqdic_s {
        byte   tkn;
        byte   tdif;
        int    rnum;
        word   wu;
    } eqdic[] = {
        {20,  2,  52,  4000},
        {10,  4, 104,  4000},
        { 4, 10, 260, 10000},
        { 2, 20, 520, 20000},
    };
    const struct eqdic_s   *eq;
    int    realnum, i;
    byte   at, crcnt, tokadif, toka, tokanum;
    byte   ch, chnum, vh, adch, adchT;
    word   ui1, waituntil, sinterval;

    rminit(false);

    eq = &eqdic[oscspeed & 3];
    tokanum   = eq->tkn;
    waituntil = eq->wu;
    realnum   = eq->rnum;
    tokadif   = eq->tdif;
    sinterval = 40;      // 20us

    uartjob();

    // ADMUX reg values
    switch(oscinput) {
    default:
    case 0x00: adch = 0x61; chnum = 1;  break;
    case 0x01: adch = 0x62; chnum = 1;  break;
    case 0x02: adch = 0x61; chnum = 2;
        tokanum >>= 1;
        tokadif <<= 1;
        break;
    }
    adchT = 0x61 + (osctrig & 7);

    header(2, 0);
    // This data packet contines to MARC-A

    sinterval--;
    crcnt = 0;
    at = 0;
    for(toka = 0; toka < tokanum; toka++) {
        for(ch = 0; ch < chnum; ch++) {
            // reset and initialize timer1
            TCCR1B = 0x00; // stop, set normal mode
            TCCR1A = 0x00;
            TIMSK1 = 0x00; // no irq
            ICR1   = 0x0000;
            TCNT1  = 0x0000;
            TIFR1  = 0x27; // clear flags;

            // analog comparator setting
            // The D6 pin is the positive input.
            // The negative input is A1, A2, A3, or A4 pin.
            ACSR   = 0x94;  // analog comparator off
            DIDR1  = 0x03;  // disable the digital input func of D6 and D7.
            ADMUX  = adchT; // select the negative input
            ADCSRA = 0x04;
            ADCSRB = 0x40;

            // start time1 with pre=1/8 (2MHz)
            // input capture noise canceler ON
            TCCR1B = (osctrig & 0x10) ? 0xc2 : 0x82;  // edge selection
            ACSR   = 0x14; // capture-on, aco to caputure timer1
            TIFR1  = 0x27; // clear flags again

            ui1 = (tokadif * toka) + (osctdly << 1);

            // falling edge detection(rising edge for ICES1)
            // doesn't stabilize without a 20usec wait below.
            while(TCNT1 < 40)
                ;
            TIFR1 = 0x27;
            // wait until a trigger event happens
            while(true) {
                if (TIFR1 & 0x20) {
                    // trigger event has happened.
                    ui1 += ICR1;
                    at = 0; // a trigger event has happened.
                    break;
                }
                if (TCNT1 > waituntil) {
                    ui1 += TCNT1;
                    at = 1; // trigger failed.
                    break;
                }
                uartjob();
            }

            // at:0 -> trigger event has happened, 1 -> not happened
            ACSR   = 0x94; // disable analog comparator
            ADCSRB = 0x00;
            ADCSRA = 0x84; // adc enable

            TCCR1B = 0x1a; // timer1 CTC-ICR1 mode pre1/8
            TCCR1A = 0x00; //             CTC mode;
            ICR1   = ui1;
            TIFR1  = 0x27; // clear flags

            ADMUX  = 0x60; // adc target is A0 pin to get trigger value;
            ADCSRB = 0x07; // timer1 capture event;
            ADCSRA = 0xf4; // adc auto trigger, force 1st conversion

            // wait until the 1st conversion finishes. 
            while((ADCSRA & 0x10) == 0x00)
                uartjob();
            vh = ADCH;  // trigger level
            osctvolt = vh;

            ADMUX = adch + ch;
            ADCSRA = 0xb4;   // clear flag, 1MHz, adate on

            if (toka == 0 && ch == 0) {   // needed only for the 1st loop
                // MARC-A  continued
                txput1(at);
                txput1(vh);
                txputcrc(false);
                txgo(); // start to trasmit a packet
                if (at)
                    goto  ex;  // send header only when trigger failed
            }

            for(i = 0; i < realnum; i++) {
                while(true) {
                    if (TIFR1 & 0x20) {
                        ICR1 = sinterval;
                        TIFR1 = 0x27; // clear timer1 flags;
                    }
                    if ((ADCSRA & 0x10) != 0x00)
                        break;
                    uartjob();
                }
                vh = ADCH;
                ADCSRA = 0xb4;   // clear flag, 1MHz, adate on
                txput1(vh);

                if (++crcnt >= 200) {
                    crcnt = 0;
                    // cause crc error on purpose if trigger failed(at > 0).
                    txputcrc((at > 0) ? true : false);
                }
            }
        }
    }
    //if (crcnt > 0)
    //    sysdown(800);
    if (crcnt == 40) {
        txputcrc((at > 0) ? true : false);
    }
    else
        sysdown(800);


ex:
    txfinish(true, true);
}


void
moderoll()
{
    byte    i;

    if (rmon == 0) {                         // start rollmode
        // reset and initialize timer1
        TCCR1B = 0x00;   // stop
        TCCR1A = 0x00;
        TIMSK1 = 0x00;   // no irq
        TCNT1  = 0x0000;
        ICR1   = 200;    // 100 usec
        TIFR1  = 0x27;   // clear flags;

        ACSR   = 0x94; // disable analog comparator
        ADCSRB = 0x00;
        ADCSRA = 0x84; // adc enable
        ADMUX  = 0x60; // adc target is A0 pin to get trigger value;
        ADCSRB = 0x07; // timer1 capture event;
        ADCSRA = 0xf4; // adc auto trigger, force start 1st conversion

        TCCR1B = 0x1a; // timer1 CTC-ICR1 mode pre1/8
        TCCR1A = 0x00; //             CTC mode;

        // wait until the 1st conversion finishes. 
        while((ADCSRA & 0x10) == 0x00)
            uartjob();
        osctvolt = ADCH;  // trigger level

        ADMUX  = 0x61;
        ADCSRA = 0xb4;   // clear flag, 1MHz, adate on

        rminit(true);
    }

    header(3, 0);

    txput1(0);
    txput1(osctvolt);
    txputcrc(false);

    txgo(); // start to trasmit a packet

    for(i = 0; i < 200; i++) {
        while(rmw == rmr)
            uartjob();
        txput1(rmbuf[rmr++]);
    }
    txputcrc(false);

    txfinish(true, true);
}


void
oscinfo(boolean restarted, byte id)
{
    if (restarted) {
        int    i;

        // send 300 bytes dummy data, since the host may be
        // receiving a 200 byte long packet. otherwise,
        // the first 201 bytes at most may be thrown away.
        txinit();
        for(i = 0; i < 300; i++)
            txput0(0);
        txgo();
        txfinish(false, false);
    }

    header(0, id);

    txput1(8);         // size of the additional info (bytes)
    txput1(osctvolt);
    txputcrc(false);
    uartjob();

    // additional info starts here
    txput1(oscversion >> 8);
    txput1(oscversion);
    txput1(oscconfig >> 8);
    txput1(oscconfig);
    uartjob();
    txput1(oscvbg >> 8);
    txput1(oscvbg >> 0);
    txput1((restarted) ? 1 : 0);
    txput1(fgen);
    uartjob();
    // additional info ended

    txputcrc(false);
    txgo();
    txfinish(true, true);
}


void
cupgain_set(byte val)
{
    if (cfg_cupgain != 2)
        return;

    val = ~val & 0x3f;
    osccupgain = val;
    PORTB = (PORTB & 0xe0) | (val >> 1);
    PORTD = (PORTD & 0x7f) | ((val & 1) ? 0x80 : 0x00);
}


void
cupgain_get()
{
    byte    val;

    if (cfg_cupgain == 2)
        return;

    val = (PINB & 0x1f) << 1;
    if (PIND & 0x80)
        val |= 1;
    osccupgain = ~val & 0x3f;
}


void
cupgain_init(byte ini)
{
    if (cfg_cupgain == 2) {
        DDRB |= 0x1f;
        DDRD |= 0x80;
        cupgain_set(ini);
    }
    else {
        DDRB  &= 0xe0;
        DDRD  &= 0x7f;
        if (cfg_cupgain == 1) {
            PORTB |= 0x1f;
            PORTD |= 0x80;
        }
        else {
            PORTB &= 0xe0;
            PORTD &= 0x7f;
        }
        cupgain_get();
    }
}


word
oscadc10(byte mux)
{
    word    val, tmp;
    int     i, j;

    // reset and initialize timer1
    TCCR1B = 0x00;
    TCCR1A = 0x00;
    TIMSK1 = 0x00; // no irq
    ICR1   = 0x0000;
    TCNT1  = 0x0000;
    TIFR1  = 0x27; // clear flags;

    ACSR   = 0x90; // disable analog comparator
    ADCSRB = 0x00;
    ADCSRA = 0x97; // adc enable  pre=1/128.  i.e. adc clock = 12.5khz
    ADMUX  = 0x40 | (mux & 0xf);

    // when bandgap reference is selected as a source,
    // a certain interval is needed for the stabilization
    // of the bandgap voltage.
    tmp = 0;
    i = 0;
    for(j = 5000; j > 0; j--) {
        ADCSRA = 0xd7; // adc start
        while((ADCSRA & 0x10) == 0x00)
            uartjob();
        val = (word)ADCL;
        val |= ((word)ADCH << 8);
        if (tmp != val) {
            tmp = val;
            i = 0;
            continue;
        }
        // if the same value continued 5 times, regard it as
        // the stabilized result
        if (++i >= 5)
            return  val;
    }
    return  0xffff;  // didn't stabilize
}


void
oscinit()
{
    word    val0, val1;

    if ((oscvbg = oscadc10(0xe)) == 0xffff) // bandgap voltage
        oscvbg = 0;

    cupgain_init(osccupgain);
    if (cfg_cupgain == 2)
        oscconfig |= 4;

    initt0();  // start trigger level generator

    // test if the trigger level generator circuit is equipped.
    sett0(192);
    wait0(4500, false);  // wai 72ms
    val1 = oscadc10(0);
    sett0( 64);
    wait0(4500, false);  // wai 72ms
    val0 = oscadc10(0);
    if ((val1 | val0) != 0xffff) {
        if (abs(val0 - 0x100) < 0x10 && abs(val1 - 0x300) < 0x10)
            oscconfig |= 1;  // yes, it worked properly.
    }
    osctduty = 0x80;
    sett0(osctduty);

    sett2(oscofreq, oscoduty);

}


// trigger level pwm voltage at D5 pin using timer0.
// Remember that time0 provides delay().
// So, millis(), micros(), delay(), and delayMicroseconds()
// are no longer available.

void
initt0()
{
    TCCR0B = 0x00; // stop timer0
    TCCR0A = 0x23; // FastPWM mode3 with OC0B output (D5)
    TIMSK0 = 0x00; // Disable all timer0 irqs
    TIFR0  = 0x07; // clear flags
    TCNT0  = 0x00;
    OCR0B  = 0x80; // duty 50%
    TCCR0B = 0x01; // start timer0  pre = 1/1  i.e 16MHz
}


void
wait0(word num, boolean uart)      // wait (num * 16) usecs
{
    while(num-- != 0) {
        TIFR0  = 0x07; // clear flags
        while((TIFR0 & 1) == 0) {
            if (uart)
                uartjob();
        }
    }
}


void
sett0(byte duty)
{
    if (duty == 0) {   // special care is needed to produce just low level
        TCCR0A = 0x33;
        OCR0B  = 0xff;
    }
    else {
        TCCR0A = 0x23;
        OCR0B = duty;   // 0..255
    }
}


// calibration oscillator using timer2
// outout pin is D3
// when hz == 0, change the D3 mode to Hi-Z.
void
sett2(long hz, byte duty) {
    long   top;
    int    ocr;
    byte   cmd2a, pre;

    if (hz < 1) {
        oscofreq = 0;
        oscoduty = 0;
        TCCR2B = 0x00;  // stop timer2
        TCCR2A = 0x00;
        DDRD  &= 0xf7;  // D3 is input
        PORTD &= 0xf7;  // D3 is Hi-Z
        return;
    }
    else {
        PORTD &= 0xf7;  // D3 is low
        DDRD  |= 0x08;  // D3 is output
    }

    hz = constrain(hz, 31, 2000000);  // 31Hz .. 2MHz
    oscofreq = hz;
    oscoduty = duty;

    cmd2a = 0x23;

    if (hz >= 62500L) {
        pre = 1;  // pre = 1/1 i.e. F_CPU = 16MHz    1..256
        top = 32000000L;
    }
    else if (hz >= 7813L) {
        pre = 2;  // pre = 1/8 i.e. F_CPU/8 = 2MHz   32..256
        top = 4000000L;
    }
    else if (hz >= 1954L) {
        pre = 3;  // pre = 1/32 i.e. F_CPU/32 = 500KHz  64..256
        top = 1000000L;
    }
    else if (hz >= 977L) {
        pre = 4;  // pre = 1/64 i.e. F_CPU/64 = 250KHz  128..256
        top = 500000L;
    }
    else if (hz >= 489L) {
        pre = 5;  // pre = 1/128i.e. F_CPU/128= 125KHz  128..256
        top = 250000L;
    }
    else if (hz >=  245L) {
        pre = 6;  // pre = 1/256 i.e. F_CPU/256= 62.5KHz  128..256
        top = 125000L;
    }
    else if (hz >= 61L) {
        pre = 7;  // pre = 1/1024 i.e. F_CPU/1024 = 15625KHz  64..256
        top = 31250L;
    }
    else {
        if (hz < 31)
            hz = 31L;
        cmd2a = 0x21; // or 0x31
        pre = 7;  // pre = 1/1024 i.e. F_CPU/1024 = 15625KHz  130..252
        top = 15625L;
    }
    top = ((top + hz) / hz) >> 1;
    ocr = (int)((top * (long)duty + 50L) / 100L);
    top--;
    if (ocr > top || (cmd2a != 0x21 && ocr > 0))
        ocr--;

    // special care for 0%
    if (ocr == 0)
        cmd2a = 0x21;

    TCCR2B = 0x00; // disable ocr2x buffering
    TCCR2A = 0x00;
    TCNT2  = 0x00;
    OCR2A  = (byte)top;
    OCR2B  = (byte)ocr;
    TCCR2B = 0x08;
    TCCR2A = cmd2a;
    TCCR2B |= pre;  // start timer2
}


byte
nib2asc(byte nib)
{
    return  (nib >= 10) ? (nib - 10 + 'a') : (nib + '0');
}


void
bin2hex(byte dat)
{
    txput0(nib2asc((dat >> 4) & 0xf));
    txput0(nib2asc((dat >> 0) & 0xf));
}


boolean
gen_cmd(const byte *p, byte id)
{
    static const byte defpkt[13] = {'M', 8};  // set memory DIPSW
    byte       sum, i, c, n;
    int        j;
    boolean    fgenconnected;

    fgenconnected = false;

    if (p == 0) {
        p = &defpkt[0];
        fgen = 255;
    }

    txfinish(false, false);
    txinit();
    PORTD &= 0xfb;  // D2 = LOW
    UDR0 = '%'; // tell funcgen to exit the gen loop
    for(j = 0; j < 1200; j++) // about 2msec wait
        uartjob();
    txput0('%');
    txput0('%');
    txput0('%');
    txput0('S');
    sum = p[0];
    txput0(sum);
    for(i = 1; i < 13; i++) {
        sum += p[i];
        bin2hex(p[i]);
        uartjob();
    }
    bin2hex(sum);
    txput0('\r');
    txput0('\n');
    txgo();
    txfinish(false, false);

    header(4, id);
    rxinit();
    sum = c = 0;
    for(j = 0; j < 20000; j++) {
        uartjob();
        n = rxnum();
        if (sum == n)
            continue;
        sum = n;
        c = rxbuf[n - 1];
        if (c == '=' || sum >= 200)
            break;
    }
    if (c != '=')
        goto  ex;
    fgenconnected = true;
    if (fgen == 255)
        fgen = rxbuf[n - 2] - '0';  // dipsw value 0..3

    txput1(sum);
    txput1(osctvolt);
    txputcrc(false);

    for(i = 0; i < sum; i++)
        txput1(rxbuf[i]);
    txputcrc(false);

    PORTD |= 0x04;  // D2 = HIGH
    txgo();
    txfinish(false, true);

ex:
    PORTD |= 0x04;  // D2 = HIGH
    rxinit();
    txinit();
    return  fgenconnected;
}


void
cmdproc()
{
    if (rxbuf[1] == 'A') {
        long  hz;
        int   treq;

        oscspeed = rxbuf[3];
        oscinput = rxbuf[4];
        osctrig  = rxbuf[5];
        osctdly  = rxbuf[8];
        uartjob();
        osctdly  = (osctdly << 8) | rxbuf[9];
        osctdly  = constrain(osctdly, 100, 30000);
        uartjob();

        treq = (int)rxbuf[6];
        if (treq > 0) {
            if (treq == 255) {
                treq = 128;  // reset
            }
            else if (treq == 254) {
                treq = (int)rxbuf[7];
            }
            else {
                treq = osctduty + (treq - 60);
            }
            treq = constrain(treq, 0, 255);
            uartjob();
            if (treq != osctduty) {
                osctduty = (byte)treq;
                sett0(osctduty);
                uartjob();
            }
        }
        hz = rxbuf[10];
        hz = (hz << 8) | rxbuf[11];
        hz = (hz << 8) | rxbuf[12];
        uartjob();
        sett2(hz, rxbuf[13]);
        uartjob();
        cupgain_set(rxbuf[14]);
        uartjob();

        // when osc settings are changed, send an info packet.
        oscinfo(false, rxbuf[2]);

    }
    else if (rxbuf[1] == 'G') {
        gen_cmd(&rxbuf[3], rxbuf[2]);
    }
    else if (rxbuf[1] == 'Q') {
        // freeze for about 5 seconds
        byte   sec;

        header(5, rxbuf[2]);
        txput1(0);         // size of the additional info (bytes)
        txput1(osctvolt);
        txputcrc(false);
        txgo();
        txfinish(true, true);

        rminit(false);
        rxinit();
        txinit();
        for(sec = 0; sec < 20; sec++) {
            PORTB |= 0x20;  // D13 led-on
            wait0(3125, false);
            PORTB &= 0xdf;  // D13 led-off
            wait0(3125, false);
        }
    }
    uartjob();
}


#define CMDLEN 16

void
cmdrecv() {
    static byte  reqid = 0;
    byte  crc, i, num;
    int    j, retry;

    retry = 1;
    for(j = 0; j < retry; j++) {
        if (j > 0)
            wait0(1, true);
        num = rxnum();
        if (num == 0)
            continue;
        if (rxbuf[0] != '$') {
            rxinit();
            continue;
        }
        if (num < (CMDLEN + 1))
            continue;
        crc = 0;
        for(i = 0; i < CMDLEN; i++) {
            crc = crctbl[crc ^ rxbuf[i]];
            uartjob();
        }
        if (rxbuf[CMDLEN] != crc) {
            retry = 20000;  // max 320msecs
            rxinit();
            continue;
        }
        if (rxbuf[2] != reqid) {
            reqid = rxbuf[2];
            cmdproc();
        }
        rxinit();
        break;
    }
    uartjob();
}


void
loop()
{
    cupgain_get();

    if (oscspeed == 8)
        moderoll();
    else if (oscspeed >= 4)
        modeequiv();
    else
        modereal();
    cmdrecv();
}


void
setup()
{
    cli();

    DDRB  |= 0x20;   // output  D13
    PORTB &= 0xdf;   // D13 = LOW
    DDRD  |= 0x2c;   // output  D2, D3, D5
    PORTD |= 0x04;   // D2 == HIGH  disconnect the funcgen

    UCSR0A = 0x02;   // uart async 230400bps 8bit non-parity 1 stopbit
    UBRR0H = 0x00;
    UBRR0L = 0x08;
    UCSR0C = 0x06;
    UCSR0B = 0x18;

    txinit();
    rxinit();
    rminit(false);

    oscinit();

    // when the function generator seems not to be attached,
    // check again up to 2 more times.
    if (gen_cmd(0, 0) || gen_cmd(0, 0) || gen_cmd(0, 0))
        oscconfig |= 2;  // fgen is connected
    oscinfo(true, 0);
}


void
sysdown(int dly)  // dly .. in msec
{
    int    i;
    byte   s;

    SPCR   = 0x00; // disable SPI
    TCCR0B = 0x00; // stop timer0
    TCCR0A = 0x02; // ctc mode
    TIMSK0 = 0x00; // Disable all timer0 irqs
    TIFR0  = 0x07; // clear flags
    TCNT0  = 0x00;
    OCR0A  = 250 - 1;
    TCCR0B = 0x03; // start timer0  pre = 1/64  i.e 250kHz

    s = 0;
    while(true) {
        if (++s & 1)
            PORTB |= 0x20;  // D13 == HIGH  (LED on)
        else
            PORTB &= 0xdf;  // D13 == LOW   (LED off)
        for(i = 0; i < dly; i++) {
            while((TIFR0 & 2) == 0)
                ;
            TIFR0  = 0x07; // clear flags
        }
    }
}


Arduino側の手始めに改変したkit_scope.ino

6404.kit_scope_citrus_try_20170220.ino.txt
// Kyutech Arduino Scope Prototype  v0.72                     Mar 20, 2016
//
//    (C) 2012-2016 M.Kurata Kyushu Institute of Technology
//
//    for Arduinos with a 5V-16MHz ATmega328.
//
//    use with "kit_scope.pde", a Proce55ing GUI sketch.
//
//    You don't need to worry about this warning message produced by the IDE.
//    "Low memory available, stability problems may occur."
//    コンパイル時、下記メッセージが表示されますが、問題ありません。
//    "スケッチが使用できるメモリが少なくなっています。動作が不安定になる可能性があります。"
//
//
//    Pin usage
//    
//    A0  trigger level voltage input    (connected to D6)
//    A1  oscilloscope probe ch1
//    A2  oscilloscope probe ch2
//    A3  oscilloscope probe ext  trigger
//    A4  reserved
//    A5  reserved
//    A6  reserved
//    A7  reserved
//    
//    D0  uart-rx
//    D1  uart-tx
//    D2  reserved
//    D3  calibration pulse wave output
//    D4  reserved
//    D5  pwm output for generating trigger level voltage
//    D6  analog comparator input (trigger level)
//    D7  reserved
//    D8  reserved
//    D9  reserved
//    D10 reserved
//    D11 reserved
//    D12 reserved
//    D13 LED output
//
//    different usage for dks2014 board.
//    A4  fgen-sync
//    D8  CH1 mode input  0..[0-10V]  1..[-5..5V]  (pull-up needed)
//    D9  CH2 mode input  0..[0-10V]  1..[-5..5V]  (pull-up needed)



const byte cfg_cupgain = 0; // the usage definition of the pins D7..D12
                            // 0: input  1:input(pulled-up)  2:output

word  oscversion = 0x0001;
word  oscvbg;              // band gap voltage in 10bits  0 means a failure.
word  oscconfig;           // bit0 -> if trigger voltage is 0:uncontrollable
                           //                               1:controllable
                           // bit1 -> optional-fgen is      0:not attached
                           //                               1:attached
                           // bit2 -> cupgain is            0:input
                           //                               1:output
byte  oscspeed   = 0;      // 0..3:real 4..7:equiv 8:roll
byte  oscinput   = 0;      // input signal selection  0:CH1 1:CH2 2:DUAL

byte  osctrig    = 0;      // trigger bit012-> 000:CH1 001:CH2 010:EXT
                           //                  011:built-in-pulse
                           //                  100:optional-fgen
                           //         bit4  -> 0:rising 1:falling
                           //         bit5  -> 0:auto   1:normal
word  osctdly    = 100;    // time of delayed trigger  100..30000 usec
byte  osctvolt;            // trigger level voltage (measured by adc) 0..255
byte  osctduty;            // trigger level duty  0..255

byte  osccupgain = 0;      // bit0  -> CH1 coupling        0:dc  1:ac
                           // bit1  -> CH2 coupling        0:dc  1:ac
                           // bit23 -> CH1 gain-selection  0,1,2,3
                           // bit45 -> CH2 gain-selection  0,1,2,3

long  oscofreq   = 1000;   // 31 .. 2000000Hz
byte  oscoduty   =   50;   // 0..100%

byte  fgen;                // 0..3: fgen-dipsw  255:no-fgen


#define TXBSZ 1100
#define RXBSZ  256 //  this must be 256.
#define RMBSZ  256 //  this must be 256.  for rollmode

int  txn, txr;
byte txcrc, rxn;
byte rmw, rmr, rmon;

byte txbuf[TXBSZ];
byte rxbuf[RXBSZ];

// since no huge packets are sent in rollmode,
// the last 256 bytes of the txbuf[] can be used
// as another buffer during the rollmode.
//
// byte rmbuf[RMBSZ];
#define rmbuf (&txbuf[TXBSZ - RMBSZ])

static const unsigned char crctbl[256] = {
    0x00, 0x85, 0x8F, 0x0A, 0x9B, 0x1E, 0x14, 0x91,
    0xB3, 0x36, 0x3C, 0xB9, 0x28, 0xAD, 0xA7, 0x22,
    0xE3, 0x66, 0x6C, 0xE9, 0x78, 0xFD, 0xF7, 0x72,
    0x50, 0xD5, 0xDF, 0x5A, 0xCB, 0x4E, 0x44, 0xC1,
    0x43, 0xC6, 0xCC, 0x49, 0xD8, 0x5D, 0x57, 0xD2,
    0xF0, 0x75, 0x7F, 0xFA, 0x6B, 0xEE, 0xE4, 0x61,
    0xA0, 0x25, 0x2F, 0xAA, 0x3B, 0xBE, 0xB4, 0x31,
    0x13, 0x96, 0x9C, 0x19, 0x88, 0x0D, 0x07, 0x82,

    0x86, 0x03, 0x09, 0x8C, 0x1D, 0x98, 0x92, 0x17,
    0x35, 0xB0, 0xBA, 0x3F, 0xAE, 0x2B, 0x21, 0xA4,
    0x65, 0xE0, 0xEA, 0x6F, 0xFE, 0x7B, 0x71, 0xF4,
    0xD6, 0x53, 0x59, 0xDC, 0x4D, 0xC8, 0xC2, 0x47,
    0xC5, 0x40, 0x4A, 0xCF, 0x5E, 0xDB, 0xD1, 0x54,
    0x76, 0xF3, 0xF9, 0x7C, 0xED, 0x68, 0x62, 0xE7,
    0x26, 0xA3, 0xA9, 0x2C, 0xBD, 0x38, 0x32, 0xB7,
    0x95, 0x10, 0x1A, 0x9F, 0x0E, 0x8B, 0x81, 0x04,

    0x89, 0x0C, 0x06, 0x83, 0x12, 0x97, 0x9D, 0x18,
    0x3A, 0xBF, 0xB5, 0x30, 0xA1, 0x24, 0x2E, 0xAB,
    0x6A, 0xEF, 0xE5, 0x60, 0xF1, 0x74, 0x7E, 0xFB,
    0xD9, 0x5C, 0x56, 0xD3, 0x42, 0xC7, 0xCD, 0x48,
    0xCA, 0x4F, 0x45, 0xC0, 0x51, 0xD4, 0xDE, 0x5B,
    0x79, 0xFC, 0xF6, 0x73, 0xE2, 0x67, 0x6D, 0xE8,
    0x29, 0xAC, 0xA6, 0x23, 0xB2, 0x37, 0x3D, 0xB8,
    0x9A, 0x1F, 0x15, 0x90, 0x01, 0x84, 0x8E, 0x0B,

    0x0F, 0x8A, 0x80, 0x05, 0x94, 0x11, 0x1B, 0x9E,
    0xBC, 0x39, 0x33, 0xB6, 0x27, 0xA2, 0xA8, 0x2D,
    0xEC, 0x69, 0x63, 0xE6, 0x77, 0xF2, 0xF8, 0x7D,
    0x5F, 0xDA, 0xD0, 0x55, 0xC4, 0x41, 0x4B, 0xCE,
    0x4C, 0xC9, 0xC3, 0x46, 0xD7, 0x52, 0x58, 0xDD,
    0xFF, 0x7A, 0x70, 0xF5, 0x64, 0xE1, 0xEB, 0x6E,
    0xAF, 0x2A, 0x20, 0xA5, 0x34, 0xB1, 0xBB, 0x3E,
    0x1C, 0x99, 0x93, 0x16, 0x87, 0x02, 0x08, 0x8D,
};


void initt0();
void rxinit(void);
void sett0(byte duty);
void sett2(long hz, byte duty);
void sysdown(int dly);
void txput0(byte ch);
void uartjob();
void wait0(word num, boolean uart);


void
rxinit(void)
{
    rxn = 0;
}


int
rxnum(void)
{
    return  rxn;
}


void
txinit(void)
{
    if (txn >= TXBSZ)
        sysdown(200);      // tx buffer overflow has been detected.
    txn = 0;
    txr = TXBSZ;
}

void
txgo(void)
{
    if (txr == TXBSZ)
        txr = 0;
}


boolean
txrunning()
{
    if (txn > txr)
        return  true;
    if (txr == TXBSZ)
        return  false;
//    return  (UCSR0A & 0x40) ? false : true;
return false;
}


void
txfinish(boolean epilogue, boolean waircv __attribute__((unused)))
{
    byte    i;

    if (epilogue) {    // output epilogue mark
        for(i = 0; i < 4; i++) {
            txput0(0xa0);
            txput0(0xa0);
            txput0(0xa0);
            txput0(0xa0);
            uartjob();
        }
    }
    while(txrunning())
        uartjob();
    //if (waircv) {
    //    wait0(600, true);  // about 10ms wait
    //}
}


void
txput0(byte ch)
{
    // to reduce the cpu consumption,
    // venture to omit txn overflow check.
    // if programmed properly, such an overflow never occurs.
    // rxn(appears later) check is omitted as well.
    txbuf[txn++] = ch;
    txcrc = 0;
}


void
txput1(byte ch)
{
    txbuf[txn++] = ch;
    txcrc = crctbl[txcrc ^ ch];
}


void
txputcrc(boolean force_error)
{
    txput0((force_error) ? ++txcrc : txcrc);
}


void
rminit(boolean on)
{
    rmw = rmr = 0;
    rmon = (on) ? 1 : 0;
}


void
uartjob()
{
//    byte    sts;
//
//    sts = UCSR0A;
//    if ((char)sts < 0)
//        rxbuf[rxn++] = UDR0;
//    // in case rxbuf[] overflow, no fatal situation happens.
//    // because rxn is an 8 bit variable and rxbuf[] size is 256.
//
//    if (rmon) {
//        if (TIFR1 & 0x20)
//            TIFR1  = 0x27;  // clear timer1 flags;
//        if (ADCSRA & 0x10) {
//            if (rmon == 1) {
//                ICR1  = 100 - 1;      // 50us
//                ADMUX = 0x62;
//                rmon = 2;
//                rmbuf[rmw++] = ADCH;  // CH1(A1pin) value
//            }
//            else if (rmon == 2) {
//                ICR1  = 400 - 1;      // 200us
//                ADMUX = 0x60;
//                rmbuf[rmw++] = ADCH;  // CH2(A2pin) value
//                rmon = 3;
//            }
//            else {
//                ICR1  = 500 - 1;      // 250us
//                ADMUX = 0x61;
//                rmon = 1;
//                osctvolt = ADCH;       // trigger level
//            }
//            ADCSRA = 0xb4;  // clear flags, 1MHz, adate on
//            return; //in order to release cpu quickly
//        }
//    }
//
//    if (txr < txn && (sts & 0x20)) {
//        UCSR0A = (sts & 0xe3) | 0x40;
//        UDR0 = txbuf[txr++];
//    }
while (Serial.available()) {
    rxbuf[rxn++] = Serial.read();
}
while (txr < txn) {
    Serial.write(txbuf[txr++]);
}
}


void
header(byte typ, byte reqid)
{
    static byte seq;

    txinit();
    uartjob();

    // prologue
    txput0(0xaa);
    txput0(0x55);
    txput0(0xa5);
    txput0(0x5a);

    uartjob();

    txput1(typ);
    if (typ == 3)
        txput1(seq++);  // rollmode
    else
        txput1(reqid);
    txput1(oscspeed);
    txput1(oscinput);
    uartjob();

    txput1(osctrig);
    txput1(osccupgain);
    txput1(osctdly >> 8);
    txput1(osctdly);
    uartjob();

    txput1(oscofreq >> 16);
    txput1(oscofreq >> 8);
    txput1(oscofreq);
    txput1(oscoduty);
    uartjob();
}


void
modereal()
{
    static const byte sitbl[4] = {20, 50, 100, 200}; // 20,50,100,200usec
    int    i, realnum;
    byte   vh, adch0, adch1, crcnt;
    word   ui1, sint1, sint2;

    rminit(false);

    realnum = 520;                                    // == 1040 >> 1
    sint1 = sint2 = ((word)sitbl[oscspeed & 3]) << 1;
    switch(oscinput) {
    default:
    case 0x00: adch0 = 0x61; adch1 = 0x61; break;
    case 0x01: adch0 = 0x62; adch1 = 0x62; break;
    case 0x02: adch0 = 0x61; adch1 = 0x62;
               sint1 = 40;  // 20usec
               sint2 = sint2 + sint2 - sint1;
               break;
    }

    uartjob();

    header(1, 0);
    // This data packet contines to MARC-A

//    // reset and initialize timer1
//    TCCR1B = 0x00; // stop, set normal mode
//    TCCR1A = 0x00;
//    TIMSK1 = 0x00; // no irq
//    ICR1   = 0x0000;
//    TCNT1  = 0x0000;
//    TIFR1  = 0x27; // clear flags;
//
//    // analog comparator setting
//    // The D6 pin is the positive input.
//    // The negative input is A1, A2, A3, or A4 pin.
//    ACSR   = 0x94;  // analog comparator off
//    DIDR1  = 0x03;  // disable the digital input function of D6 and D7.
//    ADMUX  = 0x61 + (osctrig & 7); // select the negative input
//    ADCSRA = 0x04;
//    ADCSRB = 0x40;
//
//    // start timer1 with pre=1/8
//    // input capture noise canceler ON
//    TCCR1B = (osctrig & 0x10) ? 0xc2 : 0x82;  // falling or rising edge
//    ACSR   = 0x14; // capture-on, aco to caputure timer1
//    TIFR1  = 0x27;
//
//    // falling edge detection(rising edge for ICES1)
//    // doesn't stabilize without a 20usec wait below.
//    while(TCNT1 < 40)
//        ;
//    TIFR1 = 0x27;
//
//    ui1 = (osctdly << 1);
//    // wait until a trigger event happens
//    while(true) {
//        if (TIFR1 & 0x20) {
//            // trigger event has happened.
//            ui1 += ICR1;
//            crcnt = 0; // to indicate that a trigger event has happened.
//            break;
//        }
//        if (TCNT1 > 60000) {  // 30ms == 60000/2 us
//            // 30ms has passed without detecting a trigger event.
//            ui1 += TCNT1;
//            crcnt = 1;
//            break;
//        }
//        uartjob();
//    }
digitalWrite(0, HIGH);//★★★★
//
//    // trigger event has happened here or timeout.
//    ACSR   = 0x94; // disable analog comparator
//    ADCSRB = 0x00;
//    ADCSRA = 0x84; // adc enable
//
//    TCCR1B = 0x1a; // timer1 CTC-ICR1 mode pre1/8
//    TCCR1A = 0x00; //             CTC mode;
//    ICR1   = ui1;
//    TIFR1  = 0x27; // clear flags
//
//    ADMUX  = 0x60; // adc target is A0 pin to get trigger value;
//    ADCSRB = 0x07; // timer1 capture event;
//    ADCSRA = 0xf4; // adc auto trigger, force start 1st conversion
//
//    // wait until the 1st conversion finishes. 
//    while((ADCSRA & 0x10) == 0x00)
//        uartjob();
//    vh = ADCH;  // trigger level
//    osctvolt = vh;
//
//    ADMUX  = adch0;
//    ADCSRA = 0xb4;   // clear flag, 1MHz, adate on
vh = 0;
osctvolt = vh;

    // MARC-A  continued
    txput1(crcnt);  // 0:triggered  1:freerun
    txput1(vh);     // trigger level voltage
    txputcrc(false);
    txgo(); // start to trasmit a packet

    if (crcnt && (osctrig & 0x20) != 0)
        goto  ex;  // when no-trigger and normal/single

    sint1--;
    sint2--;
    crcnt = 0;
    for(i = 0; i < realnum; i++) {
//        while(1) {
//            if (TIFR1 & 0x20) {
//                ICR1  = sint1;
//                TIFR1 = 0x27; // clear timer1 flags;
//            }
//            if ((ADCSRA & 0x10) != 0x00)
//                break;
//            uartjob();
//        }
//        vh = ADCH;
//        ADMUX = adch1;
//        ADCSRA = 0xb4;   // clear flag, 1MHz, adate on
//        txput1(vh);
//txput1(min(max(i - 100, 0), 255));
txput1(analogRead(A0) >> 2);//★★★★
delay(1);

//        while(1) {
//            if (TIFR1 & 0x20) {
//                ICR1  = sint2;
//                TIFR1 = 0x27; // clear timer1 flags;
//            }
//            if ((ADCSRA & 0x10) != 0x00)
//                break;
//            uartjob();
//        }
//        vh = ADCH;
//        ADMUX = adch0;
//        ADCSRA = 0xb4;   // clear flag, 1MHz, adate on
//        txput1(vh);
//txput1(min(max(i - 100, 0), 255));
txput1(analogRead(A0) >> 2);//★★★★
delay(1);

        if (++crcnt >= 100) {
            crcnt = 0;
            txputcrc(false);
        }
    }
    if (crcnt == 20) {
        txputcrc(false);
    }
    else
        sysdown(1000);
//
digitalWrite(0, LOW);
delay(100);

ex:
    txfinish(true, true);
}


void
modeequiv()
{
//    static const struct eqdic_s {
//        byte   tkn;
//        byte   tdif;
//        int    rnum;
//        word   wu;
//    } eqdic[] = {
//        {20,  2,  52,  4000},
//        {10,  4, 104,  4000},
//        { 4, 10, 260, 10000},
//        { 2, 20, 520, 20000},
//    };
//    const struct eqdic_s   *eq;
//    int    realnum, i;
//    byte   at, crcnt, tokadif, toka, tokanum;
//    byte   ch, chnum, vh, adch, adchT;
//    word   ui1, waituntil, sinterval;
//
//    rminit(false);
//
//    eq = &eqdic[oscspeed & 3];
//    tokanum   = eq->tkn;
//    waituntil = eq->wu;
//    realnum   = eq->rnum;
//    tokadif   = eq->tdif;
//    sinterval = 40;      // 20us
//
//    uartjob();
//
//    // ADMUX reg values
//    switch(oscinput) {
//    default:
//    case 0x00: adch = 0x61; chnum = 1;  break;
//    case 0x01: adch = 0x62; chnum = 1;  break;
//    case 0x02: adch = 0x61; chnum = 2;
//        tokanum >>= 1;
//        tokadif <<= 1;
//        break;
//    }
//    adchT = 0x61 + (osctrig & 7);
//
//    header(2, 0);
//    // This data packet contines to MARC-A
//
//    sinterval--;
//    crcnt = 0;
//    at = 0;
//    for(toka = 0; toka < tokanum; toka++) {
//        for(ch = 0; ch < chnum; ch++) {
//            // reset and initialize timer1
//            TCCR1B = 0x00; // stop, set normal mode
//            TCCR1A = 0x00;
//            TIMSK1 = 0x00; // no irq
//            ICR1   = 0x0000;
//            TCNT1  = 0x0000;
//            TIFR1  = 0x27; // clear flags;
//
//            // analog comparator setting
//            // The D6 pin is the positive input.
//            // The negative input is A1, A2, A3, or A4 pin.
//            ACSR   = 0x94;  // analog comparator off
//            DIDR1  = 0x03;  // disable the digital input func of D6 and D7.
//            ADMUX  = adchT; // select the negative input
//            ADCSRA = 0x04;
//            ADCSRB = 0x40;
//
//            // start time1 with pre=1/8 (2MHz)
//            // input capture noise canceler ON
//            TCCR1B = (osctrig & 0x10) ? 0xc2 : 0x82;  // edge selection
//            ACSR   = 0x14; // capture-on, aco to caputure timer1
//            TIFR1  = 0x27; // clear flags again
//
//            ui1 = (tokadif * toka) + (osctdly << 1);
//
//            // falling edge detection(rising edge for ICES1)
//            // doesn't stabilize without a 20usec wait below.
//            while(TCNT1 < 40)
//                ;
//            TIFR1 = 0x27;
//            // wait until a trigger event happens
//            while(true) {
//                if (TIFR1 & 0x20) {
//                    // trigger event has happened.
//                    ui1 += ICR1;
//                    at = 0; // a trigger event has happened.
//                    break;
//                }
//                if (TCNT1 > waituntil) {
//                    ui1 += TCNT1;
//                    at = 1; // trigger failed.
//                    break;
//                }
//                uartjob();
//            }
//
//            // at:0 -> trigger event has happened, 1 -> not happened
//            ACSR   = 0x94; // disable analog comparator
//            ADCSRB = 0x00;
//            ADCSRA = 0x84; // adc enable
//
//            TCCR1B = 0x1a; // timer1 CTC-ICR1 mode pre1/8
//            TCCR1A = 0x00; //             CTC mode;
//            ICR1   = ui1;
//            TIFR1  = 0x27; // clear flags
//
//            ADMUX  = 0x60; // adc target is A0 pin to get trigger value;
//            ADCSRB = 0x07; // timer1 capture event;
//            ADCSRA = 0xf4; // adc auto trigger, force 1st conversion
//
//            // wait until the 1st conversion finishes. 
//            while((ADCSRA & 0x10) == 0x00)
//                uartjob();
//            vh = ADCH;  // trigger level
//            osctvolt = vh;
//
//            ADMUX = adch + ch;
//            ADCSRA = 0xb4;   // clear flag, 1MHz, adate on
//
//            if (toka == 0 && ch == 0) {   // needed only for the 1st loop
//                // MARC-A  continued
//                txput1(at);
//                txput1(vh);
//                txputcrc(false);
//                txgo(); // start to trasmit a packet
//                if (at)
//                    goto  ex;  // send header only when trigger failed
//            }
//
//            for(i = 0; i < realnum; i++) {
//                while(true) {
//                    if (TIFR1 & 0x20) {
//                        ICR1 = sinterval;
//                        TIFR1 = 0x27; // clear timer1 flags;
//                    }
//                    if ((ADCSRA & 0x10) != 0x00)
//                        break;
//                    uartjob();
//                }
//                vh = ADCH;
//                ADCSRA = 0xb4;   // clear flag, 1MHz, adate on
//                txput1(vh);
//
//                if (++crcnt >= 200) {
//                    crcnt = 0;
//                    // cause crc error on purpose if trigger failed(at > 0).
//                    txputcrc((at > 0) ? true : false);
//                }
//            }
//        }
//    }
//    //if (crcnt > 0)
//    //    sysdown(800);
//    if (crcnt == 40) {
//        txputcrc((at > 0) ? true : false);
//    }
//    else
//        sysdown(800);
//
//
//ex:
//    txfinish(true, true);
}


void
moderoll()
{
//    byte    i;
//
//    if (rmon == 0) {                         // start rollmode
//        // reset and initialize timer1
//        TCCR1B = 0x00;   // stop
//        TCCR1A = 0x00;
//        TIMSK1 = 0x00;   // no irq
//        TCNT1  = 0x0000;
//        ICR1   = 200;    // 100 usec
//        TIFR1  = 0x27;   // clear flags;
//
//        ACSR   = 0x94; // disable analog comparator
//        ADCSRB = 0x00;
//        ADCSRA = 0x84; // adc enable
//        ADMUX  = 0x60; // adc target is A0 pin to get trigger value;
//        ADCSRB = 0x07; // timer1 capture event;
//        ADCSRA = 0xf4; // adc auto trigger, force start 1st conversion
//
//        TCCR1B = 0x1a; // timer1 CTC-ICR1 mode pre1/8
//        TCCR1A = 0x00; //             CTC mode;
//
//        // wait until the 1st conversion finishes. 
//        while((ADCSRA & 0x10) == 0x00)
//            uartjob();
//        osctvolt = ADCH;  // trigger level
//
//        ADMUX  = 0x61;
//        ADCSRA = 0xb4;   // clear flag, 1MHz, adate on
//
//        rminit(true);
//    }
//
//    header(3, 0);
//
//    txput1(0);
//    txput1(osctvolt);
//    txputcrc(false);
//
//    txgo(); // start to trasmit a packet
//
//    for(i = 0; i < 200; i++) {
//        while(rmw == rmr)
//            uartjob();
//        txput1(rmbuf[rmr++]);
//    }
//    txputcrc(false);
//
//    txfinish(true, true);
}


void
oscinfo(boolean restarted, byte id)
{
    if (restarted) {
        int    i;

        // send 300 bytes dummy data, since the host may be
        // receiving a 200 byte long packet. otherwise,
        // the first 201 bytes at most may be thrown away.
        txinit();
        for(i = 0; i < 300; i++)
            txput0(0);
        txgo();
        txfinish(false, false);
    }

    header(0, id);

    txput1(8);         // size of the additional info (bytes)
    txput1(osctvolt);
    txputcrc(false);
    uartjob();

    // additional info starts here
    txput1(oscversion >> 8);
    txput1(oscversion);
    txput1(oscconfig >> 8);
    txput1(oscconfig);
    uartjob();
    txput1(oscvbg >> 8);
    txput1(oscvbg >> 0);
    txput1((restarted) ? 1 : 0);
    txput1(fgen);
    uartjob();
    // additional info ended

    txputcrc(false);
    txgo();
    txfinish(true, true);
}


void
cupgain_set(byte val)
{
//    if (cfg_cupgain != 2)
//        return;
//
//    val = ~val & 0x3f;
//    osccupgain = val;
//    PORTB = (PORTB & 0xe0) | (val >> 1);
//    PORTD = (PORTD & 0x7f) | ((val & 1) ? 0x80 : 0x00);
}


void
cupgain_get()
{
//    byte    val;
//
//    if (cfg_cupgain == 2)
//        return;
//
//    val = (PINB & 0x1f) << 1;
//    if (PIND & 0x80)
//        val |= 1;
//    osccupgain = ~val & 0x3f;
}


void
cupgain_init(byte ini)
{
//    if (cfg_cupgain == 2) {
//        DDRB |= 0x1f;
//        DDRD |= 0x80;
//        cupgain_set(ini);
//    }
//    else {
//        DDRB  &= 0xe0;
//        DDRD  &= 0x7f;
//        if (cfg_cupgain == 1) {
//            PORTB |= 0x1f;
//            PORTD |= 0x80;
//        }
//        else {
//            PORTB &= 0xe0;
//            PORTD &= 0x7f;
//        }
//        cupgain_get();
//    }
}


word
oscadc10(byte mux)
{
//    word    val, tmp;
//    int     i, j;
//
//    // reset and initialize timer1
//    TCCR1B = 0x00;
//    TCCR1A = 0x00;
//    TIMSK1 = 0x00; // no irq
//    ICR1   = 0x0000;
//    TCNT1  = 0x0000;
//    TIFR1  = 0x27; // clear flags;
//
//    ACSR   = 0x90; // disable analog comparator
//    ADCSRB = 0x00;
//    ADCSRA = 0x97; // adc enable  pre=1/128.  i.e. adc clock = 12.5khz
//    ADMUX  = 0x40 | (mux & 0xf);
//
//    // when bandgap reference is selected as a source,
//    // a certain interval is needed for the stabilization
//    // of the bandgap voltage.
//    tmp = 0;
//    i = 0;
//    for(j = 5000; j > 0; j--) {
//        ADCSRA = 0xd7; // adc start
//        while((ADCSRA & 0x10) == 0x00)
//            uartjob();
//        val = (word)ADCL;
//        val |= ((word)ADCH << 8);
//        if (tmp != val) {
//            tmp = val;
//            i = 0;
//            continue;
//        }
//        // if the same value continued 5 times, regard it as
//        // the stabilized result
//        if (++i >= 5)
//            return  val;
//    }
//    return  0xffff;  // didn't stabilize
return 0;
}


void
oscinit()
{
//    word    val0, val1;
//
//    if ((oscvbg = oscadc10(0xe)) == 0xffff) // bandgap voltage
//        oscvbg = 0;
oscvbg = 222;
//
//    cupgain_init(osccupgain);
//    if (cfg_cupgain == 2)
//        oscconfig |= 4;
//
//    initt0();  // start trigger level generator
//
//    // test if the trigger level generator circuit is equipped.
//    sett0(192);
//    wait0(4500, false);  // wai 72ms
//    val1 = oscadc10(0);
//    sett0( 64);
//    wait0(4500, false);  // wai 72ms
//    val0 = oscadc10(0);
//    if ((val1 | val0) != 0xffff) {
//        if (abs(val0 - 0x100) < 0x10 && abs(val1 - 0x300) < 0x10)
//            oscconfig |= 1;  // yes, it worked properly.
//    }
//    osctduty = 0x80;
//    sett0(osctduty);
//
//    sett2(oscofreq, oscoduty);
//
}


// trigger level pwm voltage at D5 pin using timer0.
// Remember that time0 provides delay().
// So, millis(), micros(), delay(), and delayMicroseconds()
// are no longer available.

void
initt0()
{
//    TCCR0B = 0x00; // stop timer0
//    TCCR0A = 0x23; // FastPWM mode3 with OC0B output (D5)
//    TIMSK0 = 0x00; // Disable all timer0 irqs
//    TIFR0  = 0x07; // clear flags
//    TCNT0  = 0x00;
//    OCR0B  = 0x80; // duty 50%
//    TCCR0B = 0x01; // start timer0  pre = 1/1  i.e 16MHz
}


void
wait0(word num, boolean uart)      // wait (num * 16) usecs
{
//    while(num-- != 0) {
//        TIFR0  = 0x07; // clear flags
//        while((TIFR0 & 1) == 0) {
//            if (uart)
//                uartjob();
//        }
//    }
}


void
sett0(byte duty)
{
//    if (duty == 0) {   // special care is needed to produce just low level
//        TCCR0A = 0x33;
//        OCR0B  = 0xff;
//    }
//    else {
//        TCCR0A = 0x23;
//        OCR0B = duty;   // 0..255
//    }
}


// calibration oscillator using timer2
// outout pin is D3
// when hz == 0, change the D3 mode to Hi-Z.
void
sett2(long hz, byte duty) {
//    long   top;
//    int    ocr;
//    byte   cmd2a, pre;
//
//    if (hz < 1) {
//        oscofreq = 0;
//        oscoduty = 0;
//        TCCR2B = 0x00;  // stop timer2
//        TCCR2A = 0x00;
//        DDRD  &= 0xf7;  // D3 is input
//        PORTD &= 0xf7;  // D3 is Hi-Z
//        return;
//    }
//    else {
//        PORTD &= 0xf7;  // D3 is low
//        DDRD  |= 0x08;  // D3 is output
//    }
//
//    hz = constrain(hz, 31, 2000000);  // 31Hz .. 2MHz
//    oscofreq = hz;
//    oscoduty = duty;
//
//    cmd2a = 0x23;
//
//    if (hz >= 62500L) {
//        pre = 1;  // pre = 1/1 i.e. F_CPU = 16MHz    1..256
//        top = 32000000L;
//    }
//    else if (hz >= 7813L) {
//        pre = 2;  // pre = 1/8 i.e. F_CPU/8 = 2MHz   32..256
//        top = 4000000L;
//    }
//    else if (hz >= 1954L) {
//        pre = 3;  // pre = 1/32 i.e. F_CPU/32 = 500KHz  64..256
//        top = 1000000L;
//    }
//    else if (hz >= 977L) {
//        pre = 4;  // pre = 1/64 i.e. F_CPU/64 = 250KHz  128..256
//        top = 500000L;
//    }
//    else if (hz >= 489L) {
//        pre = 5;  // pre = 1/128i.e. F_CPU/128= 125KHz  128..256
//        top = 250000L;
//    }
//    else if (hz >=  245L) {
//        pre = 6;  // pre = 1/256 i.e. F_CPU/256= 62.5KHz  128..256
//        top = 125000L;
//    }
//    else if (hz >= 61L) {
//        pre = 7;  // pre = 1/1024 i.e. F_CPU/1024 = 15625KHz  64..256
//        top = 31250L;
//    }
//    else {
//        if (hz < 31)
//            hz = 31L;
//        cmd2a = 0x21; // or 0x31
//        pre = 7;  // pre = 1/1024 i.e. F_CPU/1024 = 15625KHz  130..252
//        top = 15625L;
//    }
//    top = ((top + hz) / hz) >> 1;
//    ocr = (int)((top * (long)duty + 50L) / 100L);
//    top--;
//    if (ocr > top || (cmd2a != 0x21 && ocr > 0))
//        ocr--;
//
//    // special care for 0%
//    if (ocr == 0)
//        cmd2a = 0x21;
//
//    TCCR2B = 0x00; // disable ocr2x buffering
//    TCCR2A = 0x00;
//    TCNT2  = 0x00;
//    OCR2A  = (byte)top;
//    OCR2B  = (byte)ocr;
//    TCCR2B = 0x08;
//    TCCR2A = cmd2a;
//    TCCR2B |= pre;  // start timer2
}


byte
nib2asc(byte nib)
{
    return  (nib >= 10) ? (nib - 10 + 'a') : (nib + '0');
}


void
bin2hex(byte dat)
{
    txput0(nib2asc((dat >> 4) & 0xf));
    txput0(nib2asc((dat >> 0) & 0xf));
}


boolean
gen_cmd(const byte *p, byte id)
{
    static const byte defpkt[13] = {'M', 8};  // set memory DIPSW
    byte       sum, i, c, n;
    int        j;
    boolean    fgenconnected;

    fgenconnected = false;

    if (p == 0) {
        p = &defpkt[0];
        fgen = 255;
    }

    txfinish(false, false);
    txinit();
//    PORTD &= 0xfb;  // D2 = LOW
//????UDR0 = '%'; // tell funcgen to exit the gen loop
    for(j = 0; j < 1200; j++) // about 2msec wait
        uartjob();
    txput0('%');
    txput0('%');
    txput0('%');
    txput0('S');
    sum = p[0];
    txput0(sum);
    for(i = 1; i < 13; i++) {
        sum += p[i];
        bin2hex(p[i]);
        uartjob();
    }
    bin2hex(sum);
    txput0('\r');
    txput0('\n');
    txgo();
    txfinish(false, false);

    header(4, id);
    rxinit();
    sum = c = 0;
    for(j = 0; j < 20000; j++) {
        uartjob();
        n = rxnum();
        if (sum == n)
            continue;
        sum = n;
        c = rxbuf[n - 1];
        if (c == '=' || sum >= 200)
            break;
    }
    if (c != '=')
        goto  ex;
    fgenconnected = true;
    if (fgen == 255)
        fgen = rxbuf[n - 2] - '0';  // dipsw value 0..3

    txput1(sum);
    txput1(osctvolt);
    txputcrc(false);

    for(i = 0; i < sum; i++)
        txput1(rxbuf[i]);
    txputcrc(false);

//    PORTD |= 0x04;  // D2 = HIGH
    txgo();
    txfinish(false, true);

ex:
//    PORTD |= 0x04;  // D2 = HIGH
    rxinit();
    txinit();
    return  fgenconnected;
}


void
cmdproc()
{
    if (rxbuf[1] == 'A') {
        long  hz;
        int   treq;

        oscspeed = rxbuf[3];
        oscinput = rxbuf[4];
        osctrig  = rxbuf[5];
        osctdly  = rxbuf[8];
        uartjob();
        osctdly  = (osctdly << 8) | rxbuf[9];
        osctdly  = constrain(osctdly, 100, 30000);
        uartjob();

        treq = (int)rxbuf[6];
        if (treq > 0) {
            if (treq == 255) {
                treq = 128;  // reset
            }
            else if (treq == 254) {
                treq = (int)rxbuf[7];
            }
            else {
                treq = osctduty + (treq - 60);
            }
            treq = constrain(treq, 0, 255);
            uartjob();
            if (treq != osctduty) {
                osctduty = (byte)treq;
                sett0(osctduty);
                uartjob();
            }
        }
        hz = rxbuf[10];
        hz = (hz << 8) | rxbuf[11];
        hz = (hz << 8) | rxbuf[12];
        uartjob();
        sett2(hz, rxbuf[13]);
        uartjob();
        cupgain_set(rxbuf[14]);
        uartjob();

        // when osc settings are changed, send an info packet.
        oscinfo(false, rxbuf[2]);

    }
    else if (rxbuf[1] == 'G') {
        gen_cmd(&rxbuf[3], rxbuf[2]);
    }
    else if (rxbuf[1] == 'Q') {
        // freeze for about 5 seconds
        byte   sec;

        header(5, rxbuf[2]);
        txput1(0);         // size of the additional info (bytes)
        txput1(osctvolt);
        txputcrc(false);
        txgo();
        txfinish(true, true);

        rminit(false);
        rxinit();
        txinit();
        for(sec = 0; sec < 20; sec++) {
//            PORTB |= 0x20;  // D13 led-on
            wait0(3125, false);
//            PORTB &= 0xdf;  // D13 led-off
            wait0(3125, false);
        }
    }
    uartjob();
}


#define CMDLEN 16

void
cmdrecv() {
    static byte  reqid = 0;
    byte  crc, i, num;
    int    j, retry;

    retry = 1;
    for(j = 0; j < retry; j++) {
        if (j > 0)
            wait0(1, true);
        num = rxnum();
        if (num == 0)
            continue;
        if (rxbuf[0] != '$') {
            rxinit();
            continue;
        }
        if (num < (CMDLEN + 1))
            continue;
        crc = 0;
        for(i = 0; i < CMDLEN; i++) {
            crc = crctbl[crc ^ rxbuf[i]];
            uartjob();
        }
        if (rxbuf[CMDLEN] != crc) {
            retry = 20000;  // max 320msecs
            rxinit();
            continue;
        }
        if (rxbuf[2] != reqid) {
            reqid = rxbuf[2];
            cmdproc();
        }
        rxinit();
        break;
    }
    uartjob();
}


void
loop()
{
    cupgain_get();

    if (oscspeed == 8)
        moderoll();
    else if (oscspeed >= 4)
        modeequiv();
    else
        modereal();
    cmdrecv();
}


void
setup()
{
//    cli();
//
//    DDRB  |= 0x20;   // output  D13
//    PORTB &= 0xdf;   // D13 = LOW
//    DDRD  |= 0x2c;   // output  D2, D3, D5
//    PORTD |= 0x04;   // D2 == HIGH  disconnect the funcgen
//
//    UCSR0A = 0x02;   // uart async 230400bps 8bit non-parity 1 stopbit
//    UBRR0H = 0x00;
//    UBRR0L = 0x08;
//    UCSR0C = 0x06;
//    UCSR0B = 0x18;
Serial.begin(9600);
analogReference(DEFAULT);
pinMode(0, OUTPUT);

    txinit();
    rxinit();
    rminit(false);

    oscinit();

    // when the function generator seems not to be attached,
    // check again up to 2 more times.
    if (gen_cmd(0, 0) || gen_cmd(0, 0) || gen_cmd(0, 0))
        oscconfig |= 2;  // fgen is connected
    oscinfo(true, 0);
}


void
sysdown(int dly)  // dly .. in msec
{
//    int    i;
//    byte   s;
//
//    SPCR   = 0x00; // disable SPI
//    TCCR0B = 0x00; // stop timer0
//    TCCR0A = 0x02; // ctc mode
//    TIMSK0 = 0x00; // Disable all timer0 irqs
//    TIFR0  = 0x07; // clear flags
//    TCNT0  = 0x00;
//    OCR0A  = 250 - 1;
//    TCCR0B = 0x03; // start timer0  pre = 1/64  i.e 250kHz
//
//    s = 0;
//    while(true) {
//        if (++s & 1)
//            _PORTB |= 0x20;  // D13 == HIGH  (LED on)
//        else
//            _PORTB &= 0xdf;  // D13 == LOW   (LED off)
//        for(i = 0; i < dly; i++) {
//            while((TIFR0 & 2) == 0)
//                ;
//            TIFR0  = 0x07; // clear flags
//        }
//    }
}


次のステップですが、PC側のGUI仕様に合うように20μsecなり1μsecなりの正確な時間単位でアナログデータを読み込めるようにRX631の内蔵周辺を直接操作するようにしてみたいと思っています。(今回は概ね1msec毎にデータ読み込みを行うようになっています。) うまく行ったら(もしくは挫折したら)、また投稿しようと思います。(最終的にはブログ形式で纏めたいです。)

  • Reply
  • Cancel
  • Cancel
  • @chobichan
    @chobichan over 3 years ago
    いいですね!とてもいいですね。特にUIが可愛くて女性にも受けそう。
    1μsサンプリングとかはDMAの登場ですかね。そんな難しい話ではないので、是非チャレンジしていただきたい。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 3 years ago
    これはいいですね!

    そういえば以前にFujitaさんがGR-SAKURAでデジタル信号をやってくれてましたね。
    japan.renesasrulz.com/.../3185

    今回のはGUIがいいですね。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • @chobichan
    @chobichan over 3 years ago in reply to Okamiya Yuuki
    可能ならUIとのインタフェースが公開されれば、スペックは低くてもGR-KURUMIでもこのUIを利用できる?したい?感じですね。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • NoMaY
    NoMaY over 3 years ago in reply to @chobichan

    @chobichan様 wrote: said:
    可能ならUIとのインタフェースが公開されれば、スペックは低くてもGR-KURUMIでもこのUIを利用できる?したい?感じですね。
    引用終わり

    UIとのインタフェースというのはArduino⇔PCの通信フォーマットのことだと思いますが、Arduino側もPC側もソースコードが丸ごと公開されていますので、インタフェースは公開されているけれどもドキュメント化されていない、というところでしょうか。GR-KURUMIもGR-CITRUSと同じような感じの移植で出来る筈ですかね。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • NoMaY
    NoMaY over 3 years ago

    別スレッドで岡宮様から頂いたanalogBulkRead()という関数のソースコードを改造して、A/D変換レートとして10μsec毎と2μsec毎を試してみました。前回は C × R に 10μF × 10KΩ を使用してA/D変換レートを約1msecとしてデータを取ってみたのですが、今回は 0.01μF × 100KΩを使用してデータを取ってみました。ひとまず、うまく取れているようです。(とは言え、今回の版も前回の版と同様にインチキをしてトリガ検出をサボっていますので、次はそこを何とかしないといけませんが。) analogBulkRead()のソースコードは今暫く見直してみるつもりです。

    今回改変したkit_scope.ino




    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
サイト使用条件
プライバシーポリシー
お問い合わせ
© 2010-2020 Renesas Electronics Corporation. All rights reserved.