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-KURUMI フォーラム analogWriteのソフトウェアPWMが動かないようです→9月中(2017年)に修正します
  • 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 14 replies
  • Subscribers 284 subscribers
  • Views 4591 views
  • Users 0 members are here
  • GR-COTTON
  • GR-KURUMI
  • GR-ADZUKI
  • analogwrite
Options
  • Share
  • More
  • Cancel
Related Tags
  • Arduino Pro-mini
  • E1
  • GPS
  • GR-ADZUKI
  • GR-COTTON
  • GR-KURUMI
  • GR-KURUMI 書き込み
  • gr-sakura
  • Guthub
  • i2c
  • JPEG
  • Kirin
  • PMT
  • RL78 レジスタバンク
  • rx
  • S/Wシリアル
  • sd card
  • Serial2
  • WDT
  • webコンパイラ
  • xbee
  • コンパイル
  • シリコンマイク
  • 誤差補正
  • 音源
Related

analogWriteのソフトウェアPWMが動かないようです→9月中(2017年)に修正します

Okamiya Yuuki
Okamiya Yuuki over 3 years ago

がじぇるね岡宮です。

RL78/G13系のGRボードで、ライブラリバージョンV2.xxではanalogWriteのソフトPWMが動かないようです。主には3,5,6,9,10以外のピンを指定したときに発生します。(GR-ADZUKIでは10ピンもsoftwarePWM)

V2.xxにバージョンアップした際に、コンパイラバージョンを14.03→4.9.2にしたことで、下記getPinTableのアセンブルが正しく動作しなくなってしまったようです。#if 1にしてC言語の方を有効にすると、analogWriteが機能します。

Fujitaさん、ここのアセンブルの修正案をいただくことできないでしょうか?

 

(pintable.h)

#if 0 // GCC の吐くコードの効率が悪いのでインラインアセンブラを使用
#define getPinTable(u8Pin) (&PinTable[u8Pin])
#else
#define getPinTable(u8Pin) \
({ \
PinTableType* p; \
__asm __volatile( \
" mov a, %1 \n" \
" mov x, %2 \n" \
" mulu x \n" \
" addw ax, %3 \n" \
" movw %0, ax \n" \
: "=r"(p) \
: "r"((uint8_t)(u8Pin)), "i"((unsigned)&PinTable[1] - (unsigned)&PinTable[0]), "i"(PinTable) \
: "a", "x" \
); \
p; \
})
#endif

  • Reply
  • Cancel
  • Cancel
Parents
  • fujita nozomu
    fujita nozomu over 3 years ago

    とりあえず以下の修正で analogWrite() は動作するようなるようです。

    --- gr_common/cores/wiring_analog.c
    +++ gr_common/cores/wiring_analog.c
    @@ -395,2 +395,3 @@ void analogWrite(uint8_t pin, int val) {
     					} else {
    +						const PinTableType* p = getPinTable(pin);
     						g_SwPwm[i].valid = false;
    @@ -398,4 +399,4 @@ void analogWrite(uint8_t pin, int val) {
     						g_SwPwm[i].value = g_SwPwm[i].newValue = val;
    -						g_SwPwm[i].port = getPinTable(pin)->portRegisterAddr;
    -						g_SwPwm[i].mask = getPinTable(pin)->mask;
    +						g_SwPwm[i].port = p->portRegisterAddr;
    +						g_SwPwm[i].mask = p->mask;
     						g_SwPwm[i].valid = true;
    

    確認用スケッチ

    /*GR-KURUMI Sketch Template Version: V2.01*/
    #include <Arduino.h>
    
    // Pin 22,23,24 are assigned to RGB LEDs.
    #define LED_RED    22 // LOW active
    #define LED_GREEN  23 // LOW active
    #define LED_BLUE   24 // LOW active
    
    void setup()
    {
    }
    
    void loop()
    {
        analogWrite(LED_RED,   127 + int(127 * sqrtf(0.5f * cosf(M_PI * millis() / 2e3f) + 0.5f)));
        analogWrite(LED_GREEN, 127 + int(127 * sqrtf(0.5f * cosf(M_PI * millis() / 3e3f) + 0.5f)));
        analogWrite(LED_BLUE,  127 + int(127 * sqrtf(0.5f * cosf(M_PI * millis() / 5e3f) + 0.5f)));
    }
    

    問題の原因としてコンパイラの不具合臭いのですが、まだ確認に到っておりません。現在普段使いの PC を修理に出している関係で携帯用のゴミスペック PC しか使える状況になく、作業効率が著しく低下しています。問題原因の確認にまで到りましたら再度報告します。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 3 years ago in reply to fujita nozomu

    > 問題原因の確認にまで到りましたら再度報告します。

    analogWrite() の getPinTable() を呼び出している箇所で

    						g_SwPwm[i].port = getPinTable(pin)->portRegisterAddr;
    

    getPinTable() の戻り値 r12 の値を hl に代入せずにメモリアクセスを行っていることが原因のようです。

    	.loc 1 399 0
     ; 399 "gr_common/cores/wiring_analog.c" 1
    		mov	a, r20	
    	mov	x, #14	
    	mulu	x	
    	addw	ax, #_PinTable	
    	movw	r12, ax	
    
     ; 0 "" 2
    .LBE8:
    	movw	ax, [hl+12]
    	movw	r14, ax
    	movw	ax, r8
    	addw	ax, #2
    	movw	de, ax
    	movw	ax, r14
    	movw	[de], ax
    

    最適化オプション `-Os' の一部の機能を禁止する `-fno-tree-vrp -fno-expensive-optimizations -fno-gcse' を加えてコンパイルすると前述の r12 → hl の代入は行われることゝなり、恐らくはコンパイラの最適化の不具合と思われます。

    	.loc 1 399 0
     ; 399 "gr_common/cores/wiring_analog.c" 1
    		mov	a, r16	
    	mov	x, #14	
    	mulu	x	
    	addw	ax, #_PinTable	
    	movw	r12, ax	
    
     ; 0 "" 2
    .LVL33:
    .LBE8:
    	movw	hl, r12
    	movw	ax, [hl+12]
    	movw	r14, ax
    	movw	ax, r8
    	addw	ax, #2
    	movw	de, ax
    	movw	ax, r14
    	movw	[de], ax
    

    以上は時間が取れ次第 https://gcc-renesas.com/ja/ に報告しておきます。

    2017/09/25 makefile が間違ってたので添付ファイル差し替え

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 3 years ago in reply to fujita nozomu

    ちなみに、Toolchain の最新より前2つ、

    GCC for Renesas 4.9.2.201603-GNURL78 Windows Toolchain (ELF)

    GCC for Renesas 4.9.2.201604-GNURL78 Windows Toolchain (ELF)

    で確認したところでは最適化オプション `-Os' で問題ありませんでした。最新の

    GCC for Renesas 4.9.2.201701-GNURL78 Windows Toolchain (ELF)

    固有の問題のようです。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 3 years ago in reply to fujita nozomu

    Fujitaさん、ご返信が遅くなり申し訳ありません。多大なるご協力ありがとうございます。

    4.9.2.201701で以下のTPで主要ライブラリやサンプルはテストしていたのですが、analogWriteのSoftPWMは、振り返ってみるとテスト漏れしている感じがありますね。

    今のところ影響が確認できているのがSoftPWMだけのため、次のWebコンパイラでもこのバージョンを使おうと思いますが、もしGNUサポートから何か連絡がありましたら、ご一報いただけると大変ありがたく存じます。

    /*
    * test.cpp
    *
    * Created on: 2017/07/19
    * Author: a5034000
    */
    //#define STANDARD_TEST
    #include <Arduino.h>
    //#include <LiquidCrystal.h>
    //#include <Ethernet.h>
    //#include <Stepper.h>

    //#define EEPROM_TEST
    #define FIRMATA_TEST
    //#define WIRE_TEST
    //#define SD_TEST
    //#define RTC_TEST
    //#define MSTIMER2_TEST
    //#define MORTOR_TEST
    //#define SERIAL_TEST
    //#define IR_TEST
    //#define TONE_TEST
    //#define STANBY_TEST
    //#define WAVP_TEST
    //#define PULSE_TEST
    //#define GFX_TEST

    #ifdef EEPROM_TEST
    #include <EEPROM.h>
    #endif

    #if not defined (FIRMATA_TEST) \
    && not defined (WIRE_TEST) \
    && not defined (SD_TEST) \
    && not defined (RTC_TEST) \
    && not defined (MSTIMER2_TEST)\
    && not defined (MORTOR_TEST)\
    && not defined (SERIAL_TEST)\
    && not defined (IR_TEST)\
    && not defined (TONE_TEST)\
    && not defined (STANBY_TEST)\
    && not defined (WAVP_TEST)\
    && not defined (PULSE_TEST)\
    && not defined (GFX_TEST)

    #define LED_R_COM 22
    #define LED_G_COM 23
    #define LED_B_COM 24
    #define LED_1 12
    #define LED_2 13
    /*GR-ADZUKI Sketch Template Version: V1.00*/
    void sw1_push() {
    digitalWrite(LED_R_COM, LOW);
    }

    void sw2_push() {
    digitalWrite(LED_G_COM, LOW);
    }

    void P137_pin25() {
    digitalWrite(LED_B_COM, LOW);
    }

    void setup() {
    Serial.begin(9600);
    #ifdef EEPROM_TEST
    for(int i = 0; i < 8*1024; i++) {
    if(0 == i % 1024) {
    Serial.println();
    Serial.print("reading..");
    Serial.println(i, HEX);
    }
    Serial.print(EEPROM.read(i),HEX);
    }
    for(int i = 0; i < 8*1024; i++) {
    if(0 == i % 1024) {
    Serial.println();
    Serial.print("writing..");
    Serial.println(i, HEX);
    }
    EEPROM.write(i, (uint8_t)i);
    }
    #endif

    pinMode(LED_R_COM, OUTPUT);
    pinMode(LED_G_COM, OUTPUT);
    pinMode(LED_B_COM, OUTPUT);
    pinMode(LED_1, OUTPUT);
    pinMode(LED_2, OUTPUT);
    digitalWrite(LED_R_COM, HIGH); // red LED on
    digitalWrite(LED_G_COM, HIGH);// green LED on
    digitalWrite(LED_B_COM, HIGH);// blue LED on
    digitalWrite(LED_1, HIGH);
    digitalWrite(LED_2, LOW);

    pinMode(3, INPUT_PULLUP);// for sw1
    pinMode(2, INPUT_PULLUP);// for sw2
    pinMode(25, INPUT_PULLUP);// needed external PULLUP
    attachInterrupt(0, sw2_push, FALLING);
    attachInterrupt(1, sw1_push, FALLING);
    attachInterrupt(2, P137_pin25, FALLING);
    for (int i = 0; i < 31; i++) {
    Serial.print("pin");
    Serial.print(i);
    Serial.print(":\t");
    Serial.print(digitalPinToPort(i), DEC);
    Serial.print(":\t");
    Serial.println((uint8_t) digitalPinToBitMask(i), HEX);
    }
    uint16_t original_data = 0b1111000010100101;

    Serial.println("BIN");
    Serial.print("original:\t");
    Serial.println(original_data, BIN);
    Serial.print("lowByte:\t");
    Serial.println(lowByte(original_data), BIN);
    Serial.print("highByte:\t");
    Serial.println(highByte(original_data), BIN);

    Serial.println("HEX");
    Serial.print("original:\t");
    Serial.println(original_data, HEX);
    Serial.print("lowByte:\t");
    Serial.println(lowByte(original_data), HEX);
    Serial.print("highByte:\t");
    Serial.println(highByte(original_data), HEX);

    // analogWrite(3, 50);
    // tone(5, 500);
    randomSeed(millis());
    }

    void loop() {
    static uint8_t count = 0;
    static uint32_t old = millis();
    static double x = 0;

    if (millis() - old > 100) {
    digitalWrite(LED_1, !digitalRead(LED_1));
    digitalWrite(LED_2, !digitalRead(LED_2));
    Serial.print("millis:");
    Serial.print(millis());
    Serial.print(" micros:");
    Serial.print(micros());
    Serial.print(" A2:");
    Serial.print(analogRead(A2));
    Serial.print(" random:");
    Serial.print(random(0, 100));
    Serial.print(" x:");
    Serial.print(x);
    Serial.print(" sin");
    Serial.print(sin(x));
    Serial.print(" cos");
    Serial.print(cos(x));
    Serial.println();
    x += 0.01;
    if (x > PI)
    x = 0;
    old = millis();
    }
    analogWrite(6, count);
    analogWrite(9, 255 - count);
    analogWrite(10, count);
    analogWrite(11, 255 - count);
    delay(5);
    count++;
    }
    #endif
    #ifdef FIRMATA_TEST
    /*
    Firmata is a generic protocol for communicating with microcontrollers
    from software on a host computer. It is intended to work with
    any host computer software package.

    To download a host software package, please click on the following link
    to open the list of Firmata client libraries in your default browser.

    github.com/.../arduino

    Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
    Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
    Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
    Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    See file LICENSE.txt for further informations on licensing terms.

    Last updated October 16th, 2016
    */

    #include <Servo.h>
    #include <Wire.h>
    #include <Firmata.h>

    #define I2C_WRITE B00000000
    #define I2C_READ B00001000
    #define I2C_READ_CONTINUOUSLY B00010000
    #define I2C_STOP_READING B00011000
    #define I2C_READ_WRITE_MODE_MASK B00011000
    #define I2C_10BIT_ADDRESS_MODE_MASK B00100000
    #define I2C_END_TX_MASK B01000000
    #define I2C_STOP_TX 1
    #define I2C_RESTART_TX 0
    #define I2C_MAX_QUERIES 8
    #define I2C_REGISTER_NOT_SPECIFIED -1

    // the minimum interval for sampling analog input
    #define MINIMUM_SAMPLING_INTERVAL 1

    /*==============================================================================
    * GLOBAL VARIABLES
    *============================================================================*/

    #ifdef FIRMATA_SERIAL_FEATURE
    SerialFirmata serialFeature;
    #endif

    /* analog inputs */
    int analogInputsToReport = 0; // bitwise array to store pin reporting

    /* digital input ports */
    byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
    byte previousPINs[TOTAL_PORTS];// previous 8 bits sent

    /* pins configuration */
    byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else

    /* timer variables */
    unsigned long currentMillis; // store the current value from millis()
    unsigned long previousMillis;// for comparison with currentMillis
    unsigned int samplingInterval = 19;// how often to run the main loop (in ms)

    /* i2c data */
    struct i2c_device_info {
    byte addr;
    int reg;
    byte bytes;
    byte stopTX;
    };

    /* for i2c read continuous more */
    i2c_device_info query[I2C_MAX_QUERIES];

    byte i2cRxData[64];
    boolean isI2CEnabled = false;
    signed char queryIndex = -1;
    // default delay time between i2c read request and Wire.requestFrom()
    unsigned int i2cReadDelayTime = 0;

    Servo servos[MAX_SERVOS];
    byte servoPinMap[TOTAL_PINS];
    byte detachedServos[MAX_SERVOS];
    byte detachedServoCount = 0;
    byte servoCount = 0;

    boolean isResetting = false;

    // Forward declare a few functions to avoid compiler errors with older versions
    // of the Arduino IDE.
    void setPinModeCallback(byte, int);
    void reportAnalogCallback(byte analogPin, int value);
    void sysexCallback(byte, byte, byte*);

    /* utility functions */
    void wireWrite(byte data)
    {
    #if ARDUINO >= 100
    Wire.write((byte)data);
    #else
    Wire.send(data);
    #endif
    }

    byte wireRead(void)
    {
    #if ARDUINO >= 100
    return Wire.read();
    #else
    return Wire.receive();
    #endif
    }

    /*==============================================================================
    * FUNCTIONS
    *============================================================================*/

    void attachServo(byte pin, int minPulse, int maxPulse)
    {
    if (servoCount < MAX_SERVOS) {
    // reuse indexes of detached servos until all have been reallocated
    if (detachedServoCount > 0) {
    servoPinMap[pin] = detachedServos[detachedServoCount - 1];
    if (detachedServoCount > 0) detachedServoCount--;
    } else {
    servoPinMap[pin] = servoCount;
    servoCount++;
    }
    if (minPulse > 0 && maxPulse > 0) {
    servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
    } else {
    servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
    }
    } else {
    Firmata.sendString("Max servos attached");
    }
    }

    void detachServo(byte pin)
    {
    servos[servoPinMap[pin]].detach();
    // if we're detaching the last servo, decrement the count
    // otherwise store the index of the detached servo
    if (servoPinMap[pin] == servoCount && servoCount > 0) {
    servoCount--;
    } else if (servoCount > 0) {
    // keep track of detached servos because we want to reuse their indexes
    // before incrementing the count of attached servos
    detachedServoCount++;
    detachedServos[detachedServoCount - 1] = servoPinMap[pin];
    }

    servoPinMap[pin] = 255;
    }

    void enableI2CPins()
    {
    byte i;
    // is there a faster way to do this? would probaby require importing
    // Arduino.h to get SCL and SDA pins
    for (i = 0; i < TOTAL_PINS; i++) {
    if (IS_PIN_I2C(i)) {
    // mark pins as i2c so they are ignore in non i2c data requests
    setPinModeCallback(i, PIN_MODE_I2C);
    }
    }

    isI2CEnabled = true;

    Wire.begin();
    }

    /* disable the i2c pins so they can be used for other functions */
    void disableI2CPins() {
    isI2CEnabled = false;
    // disable read continuous mode for all devices
    queryIndex = -1;
    }

    void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
    // allow I2C requests that don't require a register read
    // for example, some devices using an interrupt pin to signify new data available
    // do not always require the register read so upon interrupt you call Wire.requestFrom()
    if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
    Wire.beginTransmission(address);
    wireWrite((byte)theRegister);
    Wire.endTransmission(stopTX); // default = true
    // do not set a value of 0
    if (i2cReadDelayTime > 0) {
    // delay is necessary for some devices such as WiiNunchuck
    delayMicroseconds(i2cReadDelayTime);
    }
    } else {
    theRegister = 0; // fill the register with a dummy value
    }

    Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom

    // check to be sure correct number of bytes were returned by slave
    if (numBytes < Wire.available()) {
    Firmata.sendString("I2C: Too many bytes received");
    } else if (numBytes > Wire.available()) {
    Firmata.sendString("I2C: Too few bytes received");
    }

    i2cRxData[0] = address;
    i2cRxData[1] = theRegister;

    for (int i = 0; i < numBytes && Wire.available(); i++) {
    i2cRxData[2 + i] = wireRead();
    }

    // send slave address, register and received bytes
    Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
    }

    void outputPort(byte portNumber, byte portValue, byte forceSend)
    {
    // pins not configured as INPUT are cleared to zeros
    portValue = portValue & portConfigInputs[portNumber];
    // only send if the value is different than previously sent
    if (forceSend || previousPINs[portNumber] != portValue) {
    Firmata.sendDigitalPort(portNumber, portValue);
    previousPINs[portNumber] = portValue;
    }
    }

    /* -----------------------------------------------------------------------------
    * check all the active digital inputs for change of state, then add any events
    * to the Serial output queue using Serial.print() */
    void checkDigitalInputs(void)
    {
    /* Using non-looping code allows constants to be given to readPort().
    * The compiler will apply substantial optimizations if the inputs
    * to readPort() are compile-time constants. */
    if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
    if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
    if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
    if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
    if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
    if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
    if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
    if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
    if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
    if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
    if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
    if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
    if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
    if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
    if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
    if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
    }

    // -----------------------------------------------------------------------------
    /* sets the pin mode to the correct state and sets the relevant bits in the
    * two bit-arrays that track Digital I/O and PWM status
    */
    void setPinModeCallback(byte pin, int mode)
    {
    if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
    return;

    if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
    // disable i2c so pins can be used for other functions
    // the following if statements should reconfigure the pins properly
    disableI2CPins();
    }
    if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
    if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
    detachServo(pin);
    }
    }
    if (IS_PIN_ANALOG(pin)) {
    reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting
    }
    if (IS_PIN_DIGITAL(pin)) {
    if (mode == INPUT || mode == PIN_MODE_PULLUP) {
    portConfigInputs[pin / 8] |= (1 << (pin & 7));
    } else {
    portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
    }
    }
    Firmata.setPinState(pin, 0);
    switch (mode) {
    case PIN_MODE_ANALOG:
    if (IS_PIN_ANALOG(pin)) {
    if (IS_PIN_DIGITAL(pin)) {
    pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
    #if ARDUINO <= 100
    // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
    digitalWrite(PIN_TO_DIGITAL(pin), LOW);// disable internal pull-ups
    #endif
    }
    Firmata.setPinMode(pin, PIN_MODE_ANALOG);
    }
    break;
    case INPUT:
    if (IS_PIN_DIGITAL(pin)) {
    pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
    #if ARDUINO <= 100
    // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
    digitalWrite(PIN_TO_DIGITAL(pin), LOW);// disable internal pull-ups
    #endif
    Firmata.setPinMode(pin, INPUT);
    }
    break;
    case PIN_MODE_PULLUP:
    if (IS_PIN_DIGITAL(pin)) {
    pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
    Firmata.setPinMode(pin, PIN_MODE_PULLUP);
    Firmata.setPinState(pin, 1);
    }
    break;
    case OUTPUT:
    if (IS_PIN_DIGITAL(pin)) {
    if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
    // Disable PWM if pin mode was previously set to PWM.
    digitalWrite(PIN_TO_DIGITAL(pin), LOW);
    }
    pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
    Firmata.setPinMode(pin, OUTPUT);
    }
    break;
    case PIN_MODE_PWM:
    if (IS_PIN_PWM(pin)) {
    pinMode(PIN_TO_PWM(pin), OUTPUT);
    analogWrite(PIN_TO_PWM(pin), 0);
    Firmata.setPinMode(pin, PIN_MODE_PWM);
    }
    break;
    case PIN_MODE_SERVO:
    if (IS_PIN_DIGITAL(pin)) {
    Firmata.setPinMode(pin, PIN_MODE_SERVO);
    if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
    // pass -1 for min and max pulse values to use default values set
    // by Servo library
    attachServo(pin, -1, -1);
    }
    }
    break;
    case PIN_MODE_I2C:
    if (IS_PIN_I2C(pin)) {
    // mark the pin as i2c
    // the user must call I2C_CONFIG to enable I2C for a device
    Firmata.setPinMode(pin, PIN_MODE_I2C);
    }
    break;
    case PIN_MODE_SERIAL:
    #ifdef FIRMATA_SERIAL_FEATURE
    serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
    #endif
    break;
    default:
    Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
    }
    // TODO: save status to EEPROM here, if changed
    }

    /*
    * Sets the value of an individual pin. Useful if you want to set a pin value but
    * are not tracking the digital port state.
    * Can only be used on pins configured as OUTPUT.
    * Cannot be used to enable pull-ups on Digital INPUT pins.
    */
    void setPinValueCallback(byte pin, int value)
    {
    if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
    if (Firmata.getPinMode(pin) == OUTPUT) {
    Firmata.setPinState(pin, value);
    digitalWrite(PIN_TO_DIGITAL(pin), value);
    }
    }
    }

    void analogWriteCallback(byte pin, int value)
    {
    if (pin < TOTAL_PINS) {
    switch (Firmata.getPinMode(pin)) {
    case PIN_MODE_SERVO:
    if (IS_PIN_DIGITAL(pin))
    servos[servoPinMap[pin]].write(value);
    Firmata.setPinState(pin, value);
    break;
    case PIN_MODE_PWM:
    if (IS_PIN_PWM(pin))
    analogWrite(PIN_TO_PWM(pin), value);
    Firmata.setPinState(pin, value);
    break;
    }
    }
    }

    void digitalWriteCallback(byte port, int value)
    {
    byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;

    if (port < TOTAL_PORTS) {
    // create a mask of the pins on this port that are writable.
    lastPin = port * 8 + 8;
    if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
    for (pin = port * 8; pin < lastPin; pin++) {
    // do not disturb non-digital pins (eg, Rx & Tx)
    if (IS_PIN_DIGITAL(pin)) {
    // do not touch pins in PWM, ANALOG, SERVO or other modes
    if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
    pinValue = ((byte)value & mask) ? 1 : 0;
    if (Firmata.getPinMode(pin) == OUTPUT) {
    pinWriteMask |= mask;
    } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
    // only handle INPUT here for backwards compatibility
    #if ARDUINO > 100
    pinMode(pin, INPUT_PULLUP);
    #else
    // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
    pinWriteMask |= mask;
    #endif
    }
    Firmata.setPinState(pin, pinValue);
    }
    }
    mask = mask << 1;
    }
    writePort(port, (byte)value, pinWriteMask);
    }
    }

    // -----------------------------------------------------------------------------
    /* sets bits in a bit array (int) to toggle the reporting of the analogIns
    */
    //void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
    //}
    void reportAnalogCallback(byte analogPin, int value)
    {
    if (analogPin < TOTAL_ANALOG_PINS) {
    if (value == 0) {
    analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
    } else {
    analogInputsToReport = analogInputsToReport | (1 << analogPin);
    // prevent during system reset or all analog pin values will be reported
    // which may report noise for unconnected analog pins
    if (!isResetting) {
    // Send pin value immediately. This is helpful when connected via
    // ethernet, wi-fi or bluetooth so pin states can be known upon
    // reconnecting.
    Firmata.sendAnalog(analogPin, analogRead(analogPin));
    }
    }
    }
    // TODO: save status to EEPROM here, if changed
    }

    void reportDigitalCallback(byte port, int value)
    {
    if (port < TOTAL_PORTS) {
    reportPINs[port] = (byte)value;
    // Send port value immediately. This is helpful when connected via
    // ethernet, wi-fi or bluetooth so pin states can be known upon
    // reconnecting.
    if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
    }
    // do not disable analog reporting on these 8 pins, to allow some
    // pins used for digital, others analog. Instead, allow both types
    // of reporting to be enabled, but check if the pin is configured
    // as analog when sampling the analog inputs. Likewise, while
    // scanning digital pins, portConfigInputs will mask off values from any
    // pins configured as analog
    }

    /*==============================================================================
    * SYSEX-BASED commands
    *============================================================================*/

    void sysexCallback(byte command, byte argc, byte *argv)
    {
    byte mode;
    byte stopTX;
    byte slaveAddress;
    byte data;
    int slaveRegister;
    unsigned int delayTime;

    switch (command) {
    case I2C_REQUEST:
    mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
    if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
    Firmata.sendString("10-bit addressing not supported");
    return;
    }
    else {
    slaveAddress = argv[0];
    }

    // need to invert the logic here since 0 will be default for client
    // libraries that have not updated to add support for restart tx
    if (argv[1] & I2C_END_TX_MASK) {
    stopTX = I2C_RESTART_TX;
    }
    else {
    stopTX = I2C_STOP_TX; // default
    }

    switch (mode) {
    case I2C_WRITE:
    Wire.beginTransmission(slaveAddress);
    for (byte i = 2; i < argc; i += 2) {
    data = argv[i] + (argv[i + 1] << 7);
    wireWrite(data);
    }
    Wire.endTransmission();
    delayMicroseconds(70);
    break;
    case I2C_READ:
    if (argc == 6) {
    // a slave register is specified
    slaveRegister = argv[2] + (argv[3] << 7);
    data = argv[4] + (argv[5] << 7);// bytes to read
    }
    else {
    // a slave register is NOT specified
    slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
    data = argv[2] + (argv[3] << 7);// bytes to read
    }
    readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
    break;
    case I2C_READ_CONTINUOUSLY:
    if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
    // too many queries, just ignore
    Firmata.sendString("too many queries");
    break;
    }
    if (argc == 6) {
    // a slave register is specified
    slaveRegister = argv[2] + (argv[3] << 7);
    data = argv[4] + (argv[5] << 7);// bytes to read
    }
    else {
    // a slave register is NOT specified
    slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
    data = argv[2] + (argv[3] << 7);// bytes to read
    }
    queryIndex++;
    query[queryIndex].addr = slaveAddress;
    query[queryIndex].reg = slaveRegister;
    query[queryIndex].bytes = data;
    query[queryIndex].stopTX = stopTX;
    break;
    case I2C_STOP_READING:
    byte queryIndexToSkip;
    // if read continuous mode is enabled for only 1 i2c device, disable
    // read continuous reporting for that device
    if (queryIndex <= 0) {
    queryIndex = -1;
    } else {
    queryIndexToSkip = 0;
    // if read continuous mode is enabled for multiple devices,
    // determine which device to stop reading and remove it's data from
    // the array, shifiting other array data to fill the space
    for (byte i = 0; i < queryIndex + 1; i++) {
    if (query[i].addr == slaveAddress) {
    queryIndexToSkip = i;
    break;
    }
    }

    for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
    if (i < I2C_MAX_QUERIES) {
    query[i].addr = query[i + 1].addr;
    query[i].reg = query[i + 1].reg;
    query[i].bytes = query[i + 1].bytes;
    query[i].stopTX = query[i + 1].stopTX;
    }
    }
    queryIndex--;
    }
    break;
    default:
    break;
    }
    break;
    case I2C_CONFIG:
    delayTime = (argv[0] + (argv[1] << 7));

    if (delayTime > 0) {
    i2cReadDelayTime = delayTime;
    }

    if (!isI2CEnabled) {
    enableI2CPins();
    }

    break;
    case SERVO_CONFIG:
    if (argc > 4) {
    // these vars are here for clarity, they'll optimized away by the compiler
    byte pin = argv[0];
    int minPulse = argv[1] + (argv[2] << 7);
    int maxPulse = argv[3] + (argv[4] << 7);

    if (IS_PIN_DIGITAL(pin)) {
    if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
    detachServo(pin);
    }
    attachServo(pin, minPulse, maxPulse);
    setPinModeCallback(pin, PIN_MODE_SERVO);
    }
    }
    break;
    case SAMPLING_INTERVAL:
    if (argc > 1) {
    samplingInterval = argv[0] + (argv[1] << 7);
    if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
    samplingInterval = MINIMUM_SAMPLING_INTERVAL;
    }
    } else {
    //Firmata.sendString("Not enough data");
    }
    break;
    case EXTENDED_ANALOG:
    if (argc > 1) {
    int val = argv[1];
    if (argc > 2) val |= (argv[2] << 7);
    if (argc > 3) val |= (argv[3] << 14);
    analogWriteCallback(argv[0], val);
    }
    break;
    case CAPABILITY_QUERY:
    Firmata.write(START_SYSEX);
    Firmata.write(CAPABILITY_RESPONSE);
    for (byte pin = 0; pin < TOTAL_PINS; pin++) {
    if (IS_PIN_DIGITAL(pin)) {
    Firmata.write((byte)INPUT);
    Firmata.write(1);
    Firmata.write((byte)PIN_MODE_PULLUP);
    Firmata.write(1);
    Firmata.write((byte)OUTPUT);
    Firmata.write(1);
    }
    if (IS_PIN_ANALOG(pin)) {
    Firmata.write(PIN_MODE_ANALOG);
    Firmata.write(10); // 10 = 10-bit resolution
    }
    if (IS_PIN_PWM(pin)) {
    Firmata.write(PIN_MODE_PWM);
    Firmata.write(DEFAULT_PWM_RESOLUTION);
    }
    if (IS_PIN_DIGITAL(pin)) {
    Firmata.write(PIN_MODE_SERVO);
    Firmata.write(14);
    }
    if (IS_PIN_I2C(pin)) {
    Firmata.write(PIN_MODE_I2C);
    Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
    }
    #ifdef FIRMATA_SERIAL_FEATURE
    serialFeature.handleCapability(pin);
    #endif
    Firmata.write(127);
    }
    Firmata.write(END_SYSEX);
    break;
    case PIN_STATE_QUERY:
    if (argc > 0) {
    byte pin = argv[0];
    Firmata.write(START_SYSEX);
    Firmata.write(PIN_STATE_RESPONSE);
    Firmata.write(pin);
    if (pin < TOTAL_PINS) {
    Firmata.write(Firmata.getPinMode(pin));
    Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
    if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
    if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
    }
    Firmata.write(END_SYSEX);
    }
    break;
    case ANALOG_MAPPING_QUERY:
    Firmata.write(START_SYSEX);
    Firmata.write(ANALOG_MAPPING_RESPONSE);
    for (byte pin = 0; pin < TOTAL_PINS; pin++) {
    Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
    }
    Firmata.write(END_SYSEX);
    break;

    case SERIAL_MESSAGE:
    #ifdef FIRMATA_SERIAL_FEATURE
    serialFeature.handleSysex(command, argc, argv);
    #endif
    break;
    }
    }

    /*==============================================================================
    * SETUP()
    *============================================================================*/

    void systemResetCallback()
    {
    isResetting = true;

    // initialize a defalt state
    // TODO: option to load config from EEPROM instead of default

    #ifdef FIRMATA_SERIAL_FEATURE
    serialFeature.reset();
    #endif

    if (isI2CEnabled) {
    disableI2CPins();
    }

    for (byte i = 0; i < TOTAL_PORTS; i++) {
    reportPINs[i] = false; // by default, reporting off
    portConfigInputs[i] = 0;// until activated
    previousPINs[i] = 0;
    }

    for (byte i = 0; i < TOTAL_PINS; i++) {
    // pins with analog capability default to analog input
    // otherwise, pins default to digital output
    if (IS_PIN_ANALOG(i)) {
    // turns off pullup, configures everything
    setPinModeCallback(i, PIN_MODE_ANALOG);
    } else if (IS_PIN_DIGITAL(i)) {
    // sets the output to 0, configures portConfigInputs
    setPinModeCallback(i, OUTPUT);
    }

    servoPinMap[i] = 255;
    }
    // by default, do not report any analog inputs
    analogInputsToReport = 0;

    detachedServoCount = 0;
    servoCount = 0;

    /* send digital inputs to set the initial state on the host computer,
    * since once in the loop(), this firmware will only send on change */
    /*
    TODO: this can never execute, since no pins default to digital input
    but it will be needed when/if we support EEPROM stored config
    for (byte i=0; i < TOTAL_PORTS; i++) {
    outputPort(i, readPort(i, portConfigInputs[i]), true);
    }
    */
    isResetting = false;
    }

    void setup()
    {
    Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);

    Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
    Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
    Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
    Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
    Firmata.attach(SET_PIN_MODE, setPinModeCallback);
    Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
    Firmata.attach(START_SYSEX, sysexCallback);
    Firmata.attach(SYSTEM_RESET, systemResetCallback);

    // to use a port other than Serial, such as Serial1 on an Arduino Leonardo or Mega,
    // Call begin(baud) on the alternate serial port and pass it to Firmata to begin like this:
    // Serial1.begin(57600);
    // Firmata.begin(Serial1);
    // However do not do this if you are using SERIAL_MESSAGE

    Firmata.begin(57600);
    while (!Serial) {
    ; // wait for serial port to connect. Needed for ATmega32u4-based boards and Arduino 101
    }

    systemResetCallback(); // reset to default config
    }

    /*==============================================================================
    * LOOP()
    *============================================================================*/
    void loop()
    {
    byte pin, analogPin;

    /* DIGITALREAD - as fast as possible, check for changes and output them to the
    * FTDI buffer using Serial.print() */
    checkDigitalInputs();

    /* STREAMREAD - processing incoming messagse as soon as possible, while still
    * checking digital inputs. */
    while (Firmata.available())
    Firmata.processInput();

    // TODO - ensure that Stream buffer doesn't go over 60 bytes

    currentMillis = millis();
    if (currentMillis - previousMillis > samplingInterval) {
    previousMillis += samplingInterval;
    /* ANALOGREAD - do all analogReads() at the configured sampling interval */
    for (pin = 0; pin < TOTAL_PINS; pin++) {
    if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
    analogPin = PIN_TO_ANALOG(pin);
    if (analogInputsToReport & (1 << analogPin)) {
    Firmata.sendAnalog(analogPin, analogRead(analogPin));
    }
    }
    }
    // report i2c data for all device with read continuous mode enabled
    if (queryIndex > -1) {
    for (byte i = 0; i < queryIndex + 1; i++) {
    readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
    }
    }
    }

    #ifdef FIRMATA_SERIAL_FEATURE
    serialFeature.update();
    #endif
    }

    #endif // FIRMATATEST

    #ifdef WIRE_TEST
    #include <Wire.h>

    #define HMC5883L_ADDRESS 0x1E //7bit ADDRESS

    //*********************************************************
    void setup()
    {
    //Initialize Serial and I2C communications
    Serial.begin(9600);
    Wire.begin();

    //Put the HMC5883 IC into the correct operating mode
    Wire.beginTransmission(HMC5883L_ADDRESS);
    Wire.write(0x02);//select mode register
    Wire.write(0x00);//continuous measurement mode
    Wire.endTransmission();

    }
    //------------------------------------------------------
    void loop()
    {
    int x,y,z; //triple axis data

    //set address where to begin reading data
    Wire.beginTransmission(HMC5883L_ADDRESS);
    Wire.write(0x03);//select register 3, X MSB register
    Wire.endTransmission();

    //Read data from each axis, 2 registers per axis
    Wire.requestFrom(HMC5883L_ADDRESS, 6);
    if(6 <= Wire.available()) {
    x = Wire.read()<<8; x |= Wire.read();
    z = Wire.read()<<8; z |= Wire.read();
    y = Wire.read()<<8; y |= Wire.read();
    }

    //Print out values of each axis
    Serial.print("x: ");
    Serial.print(x);
    Serial.print(" y: ");
    Serial.print(y);
    Serial.print(" z: ");
    Serial.println(z);

    delay(100);

    }
    #endif // WIRE_TEST

    #ifdef SD_TEST
    #include <SD.h>

    File myFile;

    //#define SD2_TEST

    void setup() {
    Serial.begin(9600);
    while (!Serial) {
    }

    Serial.print("Initializing SD card...");

    #ifndef SD2_TEST
    if (!SD.begin(SS)) {
    #else
    if (!SD2.begin(SS2)) {
    #endif
    Serial.println("initialization failed!");
    return;
    }
    Serial.println("initialization done.");

    #ifndef SD2_TEST
    myFile = SD.open("test.txt", FILE_WRITE);
    #else
    myFile = SD2.open("test.txt", FILE_WRITE);
    #endif

    if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
    } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
    }

    // re-open the file for reading:
    #ifndef SD2_TEST
    myFile = SD.open("test.txt");
    #else
    myFile = SD2.open("test.txt");
    #endif
    if (myFile) {
    Serial.println("test.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
    Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
    } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
    }
    }

    void loop() {
    }
    #endif

    #ifdef RTC_TEST
    #include <RTC.h>

    #define LED_ERROR 12
    #define LED_ALARM 13
    #define LED_ON HIGH
    #define LED_OFF LOW

    RTC rtc;
    void alarm_handler();

    void setup()
    {
    Serial.begin(9600);
    pinMode(LED_ALARM, OUTPUT); // LED for alarm
    pinMode(LED_ERROR, OUTPUT);// LED for error
    digitalWrite(LED_ALARM, LED_OFF);//turn off
    digitalWrite(LED_ERROR, LED_OFF);//turn off

    if(!rtc.begin()) {
    digitalWrite(LED_ERROR, LED_ON); // error
    }
    rtc.setDateTime(2016, 9, 22, 23, 20, 50, RTC_WEEK_SATURDAY);

    rtc.attachAlarmHandler(alarm_handler);
    rtc.setAlarmTime(23, 21, RTC_ALARM_EVERYDAY);
    rtc.alarmOn();

    }

    void loop()
    {
    int year, mon, day, hour, min, sec, week;
    rtc.getDateTime(year, mon, day, hour, min, sec, week);

    Serial.print(year, DEC);Serial.print("/");
    Serial.print(mon, DEC); Serial.print("/");
    Serial.print(day, DEC); Serial.print(" ");
    Serial.print(hour, DEC); Serial.print(":");
    Serial.print(min, DEC); Serial.print(":");
    Serial.println(sec, DEC);

    delay(500);

    }

    void alarm_handler()
    {
    digitalWrite(LED_ALARM, LED_ON); // led for alarm
    }
    #endif

    #ifdef MSTIMER2_TEST
    #include <libraries/MsTimer2/MsTimer2.h>

    volatile unsigned long timerCount = 0;

    void timer()
    {
    timerCount++;
    }

    void setup()
    {
    Serial.begin(9600);
    Serial.println("start");
    #if 0
    attachMicroIntervalTimerHandler(timer, 1000);
    #elif 0
    MsTimer2::set(1, timer);
    MsTimer2::start();
    #elif 1
    MsTimer2::setMicros(1000, timer);
    MsTimer2::start();
    #endif
    }

    void loop()
    {
    static unsigned long lastMicros = micros();
    unsigned long currentMicros;
    do {
    currentMicros = micros();
    }while (currentMicros - lastMicros < 1000000UL);
    lastMicros = currentMicros;

    unsigned long securedTimerCount;
    do {
    securedTimerCount = timerCount;
    }while (securedTimerCount != timerCount);
    Serial.println(securedTimerCount);
    }

    #endif
    #ifdef MORTOR_TEST
    #include <Servo.h>
    Servo servo;
    void setup() {
    pinMode(13, OUTPUT);
    // analogWrite(9, 100);
    servo.attach(4);

    }

    void loop() {
    if(analogRead(A2) < 30) {
    analogWrite(10, 0);
    servo.write(0);
    } else {
    analogWrite(10, 150);
    servo.write(180);
    }
    }
    #endif
    #ifdef SERIAL_TEST

    void setup() {
    Serial.begin(9600);
    Serial1.begin(9600, SERIAL_8N1, 64, 64);
    Serial2.begin(9600, SERIAL_8N1, 256, 64);
    }

    void loop() {
    #if 0
    delay(1000);
    Serial.print("RX_BufSize Ch0:");
    Serial.print(Serial.availableForRead());
    Serial.print(" Ch1:");
    Serial.print(Serial1.availableForRead());
    Serial.print(" Ch2:");
    Serial.println(Serial2.availableForRead());
    #endif
    #if 1
    if(Serial.available()) {
    Serial2.write(Serial.read());
    }
    if(Serial2.available()) {
    Serial.write(Serial2.read());
    }
    #endif
    }
    #endif

    #ifdef IR_TEST
    #include <Servo.h>
    #define IR_PIN 2
    #define IR_INTERRUPT 0

    uint8_t g_ir_data = 0;
    bool g_ir_available = false;

    void ir_receive_interrupt();
    void ir_receive_start();
    uint8_t ir_getData();
    bool ir_available();
    Servo servo;
    void setup() {
    // setPowerManagementMode(PM_STOP_MODE);
    Serial.begin(9600);
    pinMode(IR_PIN, INPUT_PULLUP);
    ir_receive_start();
    servo.attach(4);
    servo.write(0);

    pinMode(22, OUTPUT);
    pinMode(23, OUTPUT);
    pinMode(24, OUTPUT);
    digitalWrite(22, HIGH);
    digitalWrite(23, HIGH);
    digitalWrite(24, HIGH);

    }

    void loop() {

    static int srv_angle = 0;
    ir_receive_start();
    srv_angle++;
    servo.write(srv_angle);
    delay(10);
    if (srv_angle >= 180)
    srv_angle = 0;

    // delay(0xFFFFFFFF); // hold STOP mode until receiving IR signal.

    if (ir_available()) {
    Serial.println(ir_getData(), HEX);
    Serial.flush();
    switch (ir_getData()) {
    case 0xD8: // POWER BUTTON
    break;
    case 0xF8: // A BUTTON
    break;
    case 0x78: // B BUTTON
    break;
    case 0x58: // C BUTTON
    break;
    default:
    break;
    }
    }
    }

    /************ IR utility function ***************/
    void ir_receive_interrupt() {

    unsigned long last_time;

    detachInterrupt(IR_INTERRUPT);
    interrupts()
    ;
    last_time = micros();

    // confirm if reader code is correct
    uint8_t err = 0;
    while (!digitalRead(IR_PIN)) { // until change from low to high
    if ((micros() - last_time) > 10000) { // interval low should be 9ms or less
    err = true;
    break;
    }
    }
    while (digitalRead(IR_PIN)) { // until change from high to low
    if ((micros() - last_time) > 15000) { // interval of reader code should be 13.5ms or less
    err = true;
    break;
    }
    }
    if (((micros() - last_time) < 13000) || (err == true)) { // Unknown code
    attachInterrupt(0, ir_receive_interrupt, FALLING);
    g_ir_available = false;
    return; // not available remote controller
    }

    // get data
    uint8_t receive_count = 0;
    uint8_t temp_ir_data[4] = { 0 };
    g_ir_data = 0;
    last_time = micros();
    while ((32 > receive_count) && ((micros() - last_time) < 80000)) {
    // interval of a frame data should be 76.5ms or less
    last_time = micros();
    while (!digitalRead(IR_PIN) && ((micros() - last_time) < 1000)) {
    // interval of low state is about 0.56ms.
    }
    while (digitalRead(IR_PIN) && ((micros() - last_time) < 2500)) {
    // interval of a bit is between 1.125ms and 2.25ms
    }
    if ((micros() - last_time) > 1500) {
    bitSet(temp_ir_data[receive_count / 8], receive_count % 8);
    }
    receive_count++;
    }

    if (temp_ir_data[2] == (uint8_t) ~temp_ir_data[3]) {
    g_ir_data = temp_ir_data[2]; // set actual data
    g_ir_available = true;
    }

    }

    void ir_receive_start() {
    attachInterrupt(IR_INTERRUPT, ir_receive_interrupt, FALLING);
    }

    uint8_t ir_getData() {
    g_ir_available = false;
    return g_ir_data;
    }

    bool ir_available() {
    return g_ir_available;
    }
    #endif

    #ifdef TONE_TEST
    void setup(){
    for(int i = 0; i < 500; i+=10){
    tone(5, 500 + i);
    delay(10);
    }
    for(int i = 0; i < 500; i+=10){
    tone(5, 1000 - i);
    delay(10);
    }
    noTone(5);
    delay(500);
    tone(5, 400, 200);
    delay(500);
    tone(5, 400, 1000);
    }

    void loop(){

    }

    #endif

    #ifdef STANBY_TEST
    #include <Arduino.h>
    void setup()
    {
    Serial.begin(9600);
    pinMode(13, OUTPUT);
    }

    void loop()
    {
    int value;
    setPowerManagementMode(PM_SNOOZE_MODE, 500, 1023);
    value = analogRead(A0);
    Serial.println(value);
    Serial.flush();
    Serial.println(getTemperature(0));
    Serial.flush();
    setPowerManagementMode(PM_NORMAL_MODE);
    value = analogRead(A0);
    Serial.println(value);
    Serial.flush();
    Serial.println(getTemperature(0));
    Serial.flush();
    delay(100);
    }
    #endif

    #ifdef WAVP_TEST
    #include <Wavp.h>
    Wavp wavp(44100, WAVP_OUTPUT_35);
    void setup(){
    Serial.begin(9600);
    pinMode(24, OUTPUT);
    digitalWrite(24, LOW);
    // wavp.play("organ.wav");
    // analogWrite(6, 50);
    // analogWrite(9, 100);
    // analogWrite(10,0);
    // tone(5, 600);
    // delay(1000);
    // noTone(5);
    wavp.begin(WAVP_SPI1);
    // digitalWrite(24, HIGH);
    wavp.play("okoto.wav");
    // tone(5, 500);
    // delay(500);
    // noTone(5);
    wavp.play("jingle2.wav");

    while(1);
    }

    void loop(){

    tone(3, 500);
    delay(1000);

    // wavp.play("1.wav");
    tone(3, 500);
    delay(1000);
    }
    #endif

    #ifdef PULSE_TEST
    const int pinPulseOut = 3;
    const int pinPulseIn = 2;

    void setup()
    {
    Serial.begin(9600);
    }

    void loop()
    {
    for (int i = 1; i <= 255; i++) {
    analogWrite(pinPulseOut, i);
    for (int j = 0; j < 10; j++) {
    noInterrupts();
    unsigned long highWidth = pulseIn(pinPulseIn, HIGH, 100000UL);
    unsigned long lowWidth = pulseIn(pinPulseIn, LOW, 100000UL);
    interrupts();
    char buf[100];
    sprintf(buf, "%8ld: high(%3d) low(%3d) => high(%3ld) low(%3ld)", millis(), 8 * i, 8 * (255 - i), highWidth, lowWidth);
    Serial.println(buf);
    Serial.flush();
    }
    }
    }
    #endif

    #ifdef GFX_TEST
    void setup()
    {
    }

    void loop()
    {
    }
    #endif




    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 3 years ago in reply to Okamiya Yuuki
    現在のところ原因が不明であり、最適化オプションでの対処で問題が完全に解決するとも分かりませんので、前の版であるGCC for Renesas 4.9.2.201604-GNURL78 Windows Toolchain (ELF)等の使用も考慮すべきと思います。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
Reply
  • fujita nozomu
    fujita nozomu over 3 years ago in reply to Okamiya Yuuki
    現在のところ原因が不明であり、最適化オプションでの対処で問題が完全に解決するとも分かりませんので、前の版であるGCC for Renesas 4.9.2.201604-GNURL78 Windows Toolchain (ELF)等の使用も考慮すべきと思います。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
Children
  • Okamiya Yuuki
    Okamiya Yuuki over 3 years ago in reply to fujita nozomu

    Fujitaさん、ご返信ありがとうございます。

    GCC 4.9.2.201701-GNURL78のリリースノートをGoogle翻訳したのが以下ですが、10が前バージョンを使うのにためらうところでしょうかね。

    できれば、種々の改善がみられ、テストがあらかた済んでいる201701バージョンを使いたいと思っていますが、いかがですかね?

     

    1. [改善]新しい穴の最適化:特定の8ビットの移動の代わりに16ビットの移動を使用する
    (コードサイズと速度向上)
    2. [改善]論理演算( "cstoreqi4"と "cstorehi4")の新しいRTLパターン、ビット操作
    (「insvmisalign_qi」)、スイッチ文(「casesi」)、8ビット算術演算(「udivqi3」および「umodqi3」)
    3. [改善点] SFRアドレッシングの改善(コードサイズ縮小)
    4. [改善]サイズ(-Os)を最適化するときにデフォルトで有効になるリンカの緩和により、改善されています
    セクションの破棄(実行可能ファイルの中には実行可能コードとデータサイズの縮小があります)
    5. [改善点] libgccライブラリのメモリフットプリントが小さくなりました。
    6. [改善]ファイルの古い8.3命名規則の使用を必要とする制限を削除しました。
    libgen
    7. [改善点] Optlibのsnprintfサポートを追加しました。
    8. [Bug-Fix]最適化の際に関数の引数がスタックに上書きされることがあったまれなケースを修正しました
    サイズ(-Os)
    9. [Bug-Fix] __far関数で32ビット右シフトを実行したときに発生する内部エラーを修正しました。
    引数
    10. [Bug-Fix] G13 MCUで不正な結果を返す乗算関連のプリミティブを修正

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 3 years ago in reply to Okamiya Yuuki
    > 10が前バージョンを使うのにためらうところでしょうかね。

    > 10. [Bug-Fix] G13 MCUで不正な結果を返す乗算関連のプリミティブを修正

    `-mmul=g13' を指定して RL78-S2 コアの乗除算器を使用した場合のことだと思いますが、web コンパイラではこの機能は使ってないので関係ないと思います。
    ちなみに、リリースノートにはfixしたとありますが GCC 4.9.2.201701-GNURL78 ではまだ RL78-S2 コアの乗除算器の使用には不具合があり、使い物にならない感じです。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 3 years ago in reply to fujita nozomu
    Fujitaさん、アドバイスをいただきありがとうございます。
    今回の不具合の原因や改善についての見解が出るまで 「4.9.2.201604」を使うようにしたいと思います。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 3 years ago in reply to Okamiya Yuuki

    新しいツールチェーンがリリースされたようです。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 3 years ago in reply to fujita nozomu
    そのようですね。私にもV-upメールが来ました。
    Fujitaさんのクエリには何かございましたか?
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • fujita nozomu
    fujita nozomu over 3 years ago in reply to Okamiya Yuuki

    新しいツールチェーン GCC for Renesas 4.9.2.201703-GNURL78 で https://japan.renesasrulz.com/gr_user_forum_japanese/f/gr-kurumi/4548/analogwrite-pwm-9-2017/24284#24284 の確認をしてみましたが、

    	.loc 1 399 0
     ; 399 "gr_common/cores/wiring_analog.c" 1
    		mov	a, r20	
    	mov	x, #14	
    	mulu	x	
    	addw	ax, #_PinTable	
    	movw	r12, ax	
    
     ; 0 "" 2
    .LBE8:
    	movw	ax, [hl+12]
    	movw	r14, ax
    	movw	ax, r8
    	addw	ax, #2
    	movw	de, ax
    	movw	ax, r14
    	movw	[de], ax
    

    出力コードの不具合は変わらんですね。問題の修正がされる前に現象が再現されなくなることを恐れていましたが良かったです。

    > Fujitaさんのクエリには何かございましたか?

    リリースノートにある

    > 2.[Improvement]objdumpimproved to display the multiplication/division registers by their name instead of their memory-mapped addresses.
    > 3.[Improvement]The following patterns were added for G10, G13 and G14 cores -udivmodqi4, udivhi3, umodhi3, udivmodhi4, divhi3, modhi3, divmodhi4, udivsi3, umodsi3, divsi3, modsi
    > 5.[Improvement]Implemented aliases for -mcpu=g10,g13,g14to resemble the manual (s1,s2,s3)
    > 7.[Bug Fix]Fixed the generation of "es:" before the sfr address.
    > 8.[Bug Fix]Fixed:mov [de],#IMMis interpreted now as mov [de+0],#IMMmov [hl],#IMMis interpreted now as mov [hl+0],#IMM
    > 9.[Bug Fix]Fixed the behaviorof lo16, hi16, hi8local symbols to resemblelo16, hi16, hi8global symbols
    > 11.[Bug Fix]Fixed compile error on accessing sfr with __farpointer.
    > 14.[Bug Fix]Corrected the save/restore of multiply registers in interrupts.

    この辺りが自分が出した要望や報告した不具合だと思います。(業務でもないし面倒なので)まだ確認していませんがうまく対応されてると良いですね。

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Okamiya Yuuki
    Okamiya Yuuki over 3 years ago in reply to fujita nozomu
    Fujitaさん、201703版のご確認ありがとうございました。
    hlに代入しないでメモリアクセスする不具合が修正されていないとのことで、201703版の適用は見合わせようと思います。
    しかし、これだけのBug報告をされるのもすごいですね。
    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
サイト使用条件
プライバシーポリシー
お問い合わせ
© 2010-2020 Renesas Electronics Corporation. All rights reserved.