i2c_t3 compile error

grinch

Well-known member
Hi, I am recompiling an old sketch using i2c_t3 on the new Arduino IDE and it no longer builds. I get a library error saying that Wire and Wire1 have multiple definitions like the original Wire library is getting defined somewhere.

How do I fix this? I also tried on an older Teensyduino IDE install with similar results, something has changed as it's been about a year since I've had to build this sketch.

Here is my error:


C-like:
/Users/emmettpalaima/Library/Arduino15/packages/teensy/tools/teensy-compile/11.3.1/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/arduino/sketches/454FF7FE197B280F1F02F6D915A39469/libraries/Wire/WireKinetis.cpp.o: in function `i2c0_isr':
/Users/emmettpalaima/Library/Arduino15/packages/teensy/hardware/avr/1.59.0/libraries/Wire/WireKinetis.cpp:914: multiple definition of `i2c0_isr'; /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/arduino/sketches/454FF7FE197B280F1F02F6D915A39469/libraries/i2c_t3/i2c_t3.cpp.o:/Users/emmettpalaima/Library/Arduino15/packages/teensy/hardware/avr/1.59.0/libraries/i2c_t3/i2c_t3.cpp:1134: first defined here
/Users/emmettpalaima/Library/Arduino15/packages/teensy/tools/teensy-compile/11.3.1/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/arduino/sketches/454FF7FE197B280F1F02F6D915A39469/libraries/Wire/WireKinetis.cpp.o: in function `i2c1_isr':
/Users/emmettpalaima/Library/Arduino15/packages/teensy/hardware/avr/1.59.0/libraries/Wire/WireKinetis.cpp:919: multiple definition of `i2c1_isr'; /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/arduino/sketches/454FF7FE197B280F1F02F6D915A39469/libraries/i2c_t3/i2c_t3.cpp.o:/Users/emmettpalaima/Library/Arduino15/packages/teensy/hardware/avr/1.59.0/libraries/i2c_t3/i2c_t3.cpp:1141: first defined here
/Users/emmettpalaima/Library/Arduino15/packages/teensy/tools/teensy-compile/11.3.1/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/arduino/sketches/454FF7FE197B280F1F02F6D915A39469/libraries/Wire/WireKinetis.cpp.o:/Users/emmettpalaima/Library/Arduino15/packages/teensy/hardware/avr/1.59.0/libraries/Wire/WireKinetis.cpp:918: multiple definition of `Wire1'; /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/arduino/sketches/454FF7FE197B280F1F02F6D915A39469/libraries/i2c_t3/i2c_t3.cpp.o:/Users/emmettpalaima/Library/Arduino15/packages/teensy/hardware/avr/1.59.0/libraries/i2c_t3/i2c_t3.cpp:1659: first defined here
/Users/emmettpalaima/Library/Arduino15/packages/teensy/tools/teensy-compile/11.3.1/arm/bin/../lib/gcc/arm-none-eabi/11.3.1/../../../../arm-none-eabi/bin/ld: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/arduino/sketches/454FF7FE197B280F1F02F6D915A39469/libraries/Wire/WireKinetis.cpp.o:/Users/emmettpalaima/Library/Arduino15/packages/teensy/hardware/avr/1.59.0/libraries/Wire/WireKinetis.cpp:913: multiple definition of `Wire'; /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/arduino/sketches/454FF7FE197B280F1F02F6D915A39469/libraries/i2c_t3/i2c_t3.cpp.o:/Users/emmettpalaima/Library/Arduino15/packages/teensy/hardware/avr/1.59.0/libraries/i2c_t3/i2c_t3.cpp:1657: first defined here
collect2: error: ld returned 1 exit status

Here is the section of my code that uses i2c_t3

C++:
#include <i2c_t3.h>

#define IS31_ADDR 0x3C
#define EN_PIN 20

#define FOIL 5
#define TCP 6
#define BCP 7
#define ATK 8
#define DEF 9
#define HRT 10

const uint8_t rfall[9] = { 19, 18, 17, 16, 15, 14, 13, 12, 11 };
const uint8_t lfall[9] = { 20, 21, 22, 23, 24, 25, 26, 27, 28 };

#define HG 29

uint8_t data_buf[37] = {};
uint8_t led_default[36] = {};

void write_is31_buffer(uint8_t reg, uint8_t *data, int len){
  Wire.beginTransmission(IS31_ADDR);
  Wire.write(reg);
  Wire.write(data, len);
  Wire.sendTransmission();
}

void write_is31_byte(uint8_t reg, uint8_t data){
  Wire.beginTransmission(IS31_ADDR);
  Wire.write(reg);
  Wire.write(data);
  Wire.sendTransmission();
}

void write_is31_pwm(uint8_t *data){
  Wire.beginTransmission(IS31_ADDR);
  Wire.write(0x01);
  Wire.write(data, 37); //37 is zero written to update reg
//  for(int i = 0; i < 37; ++i){
//    Wire.write(data[i]);
//  }
  Wire.sendTransmission();
}

void init_is31( void ){
  pinMode(EN_PIN, OUTPUT);
  digitalWriteFast(EN_PIN, HIGH);
  for(int i = 5; i < 30; ++i){ led_default[i] = 1; }
  delay(10);
  write_is31_byte(0x00, 0x01);
  delay(10);
  write_is31_byte(0x4B, 0x01);
  delay(10);
  write_is31_buffer(0x26, led_default, 36);
  delay(10);
}

Here is my main file that includes this file:

Code:
#include <Audio.h>
#include "HarmonicDistortion.h"

// GUItool: begin automatically generated code
AudioSynthWaveformDc     dc1;            //xy=55,1513
AudioSynthWaveformDc     dc2;            //xy=62,1783
AudioEffectEnvelope      env2;      //xy=74,1724
AudioSynthWaveformDc     dc3;            //xy=85,1651
AudioEffectEnvelope      env1;      //xy=155,1441
AudioSynthWaveformSineModulated sine4;       //xy=225,1878
AudioSynthWaveformSineModulated sine3;       //xy=231,1827
AudioSynthWaveformSine   sine5;          //xy=232,1935
AudioMixer4              mix3;         //xy=262,1662
AudioSynthWaveformSineModulated sine2;       //xy=279,1578
AudioMixer4              mix2;         //xy=365,1450
AudioMixer4              sinemix2;         //xy=420,1818
AudioSynthWaveformDc     dc4;            //xy=437,1995
AudioSynthWaveformSineModulated testSine;       //xy=469,1603
AudioSynthWaveformDc     testDc;
AudioEffectMultiply      testMult;
AudioEffectMultiply      mult2;      //xy=469,1678
AudioSynthWaveformSineModulated sine1;       //xy=494,1449
AudioEffectMultiply      mult1;      //xy=529,1571
AudioEffectEnvelope      env3;      //xy=628,1895
AudioEffectEnvelope      env4;      //xy=641,1950
AudioMixer4              sinemix1;         //xy=663,1451
AudioSynthNoiseWhite     noise1;         //xy=670,1768
AudioMixer4              mix1;         //xy=671,1623
AudioSynthWaveformDc     dc5;            //xy=710,2041
AudioMixer4              mixer6;         //xy=835,1936
AudioAmplifier           amp1;           //xy=846,1618
AudioAmplifier           amp2;           //xy=846,1618
HarmonicDistortion       dist1;
AudioEffectMultiply      multiply3;      //xy=956,1817
AudioOutputAnalog        dac1;           //xy=997,1615

AudioFilterBiquad        filt;
AudioAmplifier           makeup;

AudioConnection          patchCord1(dc1, env1);
AudioConnection          patchCord2(dc2, env2);
AudioConnection          patchCord3(env2, 0, mix3, 0);
AudioConnection          patchCord4(env2, 0, mult2, 1);
AudioConnection          patchCord5(dc3, 0, mix3, 1);
AudioConnection          patchCord6(dc3, 0, mix2, 1);
AudioConnection          patchCord7(env1, 0, mult1, 1);
AudioConnection          patchCord8(env1, 0, mix2, 0);
AudioConnection          patchCord9(sine4, 0, sinemix1, 2);
AudioConnection          patchCord10(sine4, 0, sinemix2, 2);
AudioConnection          patchCord11(sine3, 0, sinemix1, 1);
AudioConnection          patchCord12(sine3, 0, sinemix2, 1);
AudioConnection          patchCord13(sine5, 0, sinemix1, 3);
AudioConnection          patchCord14(sine5, 0, sinemix2, 3);
AudioConnection          patchCord15(mix3, sine2);
AudioConnection          patchCord16(sine2, 0, sinemix2, 0);
AudioConnection          patchCord17(mix2, sine1);
AudioConnection          patchCord18(sinemix2, 0, mult2, 0);
AudioConnection          patchCord19(dc4, env3);
AudioConnection          patchCord20(dc4, env4);
//AudioConnection          patchCord21(testSine, 0, mix1, 3);
AudioConnection          patchCord22(mult2, 0, mix1, 1);
AudioConnection          patchCord23(sine1, 0, sinemix1, 0);
AudioConnection          patchCord24(mult1, 0, mix1, 0);
AudioConnection          patchCord25(env3, 0, mixer6, 0);
AudioConnection          patchCord26(env4, 0, mixer6, 1);
AudioConnection          patchCord27(sinemix1, 0, mult1, 0);
AudioConnection          patchCord28(noise1, 0, multiply3, 0);
AudioConnection          patchCord29(mix1, amp2);
AudioConnection          patchCord30(dc5, 0, mixer6, 2);
AudioConnection          patchCord31(mixer6, 0, multiply3, 1);


AudioConnection          patchCord32(amp1, filt);
AudioConnection          patchCord32b(filt, makeup);
AudioConnection          patchCord32c(makeup, dac1);

AudioConnection          patchCord33(multiply3, 0, mix1, 2);

AudioConnection          patchCordA(amp2, dist1);
AudioConnection          patchCordB(dist1, amp1);

AudioConnection          patchCordC(testSine, 0, testMult, 0);
AudioConnection          patchCordD(testDc, 0, testMult, 1);
AudioConnection          patchCordE(testMult, 0, mix1, 3);
// GUItool: end automatically generated code

unsigned long audioTimer = 0;
bool at = false;

float atk = 50;
float dec = 300;

float atk2 = atk;
float dec2 = dec;

float amp = 1;

float freq = 35;

float topper = amp;

void setupAudio(){
  AudioMemory(100);

  dist1.thirdOrder(1);
  dist1.secondOrder(0);
  dist1.gain(6);
 
  sine1.amplitude(amp);
  sine1.frequency(freq);
  sine2.amplitude(amp);
  sine2.frequency(freq-1);

  sine3.frequency(200);
  sine3.amplitude(0.01*topper);
  sine4.frequency(100);
  sine4.amplitude(0.01*topper);
  sine5.frequency(400);
  sine5.amplitude(0.01*topper);

  testSine.amplitude(1);
  testSine.frequency(120);

  noise1.amplitude(1);
 
  env1.attack(atk);
  env1.hold(0);
  env1.decay(dec);
  env1.sustain(0);
  env1.release(1.0f);
  env1.releaseNoteOn(1);
 
  env2.attack(atk);
  env2.hold(0);
  env2.decay(dec);
  env2.sustain(0);
  env2.release(1.0f);
  env2.releaseNoteOn(1);

  env3.attack(atk2);
  env3.hold(0);
  env3.decay(dec2);
  env3.sustain(0);
  env3.release(1.0f);
  env3.releaseNoteOn(1);

  env4.attack(atk2);
  env4.hold(0);
  env4.decay(dec2);
  env4.sustain(0);
  env4.release(1.0f);
  env4.releaseNoteOn(1);

  dc1.amplitude(1);
  dc2.amplitude(1);
  dc3.amplitude(-1);
  dc4.amplitude(-1);
  dc5.amplitude(1);

  testDc.amplitude(0);

  const float sine_mix = 1;
  const float noise_mix = 1;
  const float test_mix = 4;

  mix1.gain(0, sine_mix);
  mix1.gain(1, sine_mix);
  mix1.gain(2, noise_mix);
  mix1.gain(3, test_mix);

  mix2.gain(0, 1);
  mix2.gain(1, 1);
  mix2.gain(2, 1);
  mix2.gain(3, 1);

  mix3.gain(0, 1);
  mix3.gain(1, 1);
  mix3.gain(2, 1);
  mix3.gain(3, 1);

  sinemix1.gain(0, 1);
  sinemix1.gain(1, 1);
  sinemix1.gain(2, 1);
  sinemix1.gain(3, 1);

  sinemix2.gain(0, 1);
  sinemix2.gain(1, 1);
  sinemix2.gain(2, 1);
  sinemix2.gain(3, 1);

  float vol = float(analogRead(A8)) / 1023.0f;

  amp2.gain(1);
  amp1.gain(vol);
 
  dac1.analogReference(EXTERNAL);

  for(int i = 0; i < 3; ++i){
    filt.setLowpass(i, 250, 0.7);
  }
  makeup.gain(2);
}

#include "TombAudio.h"
#include "IS31_I2C.h"
#include "Utility.h"

#define REFRESH 40

#define CLK_IN 21
#define CLK_NORM 17
#define ATK_OUT 16

const uint8_t pot[3] = { A1, A0, A8 };

pwm_port foil_led;
pwm_port tcp_led;
pwm_port bcp_led;
pwm_port atk_led;
pwm_port def_led;
pwm_port hrt_led;
pwm_port hg_led;

pwm_port lfall_led[9];
pwm_port rfall_led[9];

pwm_port clk_norm;

ms_delta clk_pulse;
ms_delta clk_delta;
ms_delta beat_delta;
trig_delay beat2;
trig_delay beat3;

ms_timer led_refresh;
ms_timer fall_timer;

void setup() {

  pinMode(CLK_NORM, OUTPUT);
  pinMode(CLK_IN, INPUT_PULLUP);
  pinMode(ATK_OUT, OUTPUT);

  foil_led.init(0, REFRESH);
  tcp_led.init(0, REFRESH);
  bcp_led.init(0, REFRESH);
  atk_led.init(0, REFRESH);
  def_led.init(0, REFRESH);
  hrt_led.init(0, REFRESH);
  hg_led.init(0, REFRESH);

  for(int i = 0; i < 9; ++i){
    rfall_led[i].init(0, REFRESH);
    lfall_led[i].init(0, REFRESH);
  }

  led_refresh.set_timer(REFRESH);

  clk_pulse.set_pulse_len(100);
 
//  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(EN_PIN, OUTPUT);
  digitalWrite(EN_PIN, HIGH);

  setupAudio();
 
  // Setup for Master mode, pins 18/19, external pullups, 400kHz
  Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
  Wire.begin();

  Wire.setDefaultTimeout(250000); // 250ms default timeout
 
  delay(1000);
// put your setup code here, to run once:
   digitalWrite(LED_BUILTIN,LOW);         // LED on

   //     Set operating mode to DMA
//  Serial.print("Trying to set DMA mode : ");
  Wire.setOpMode(I2C_OP_MODE_DMA);
//  if(Wire.i2c->opMode == I2C_OP_MODE_DMA){
////      Serial.printf("OK (Channel %d)\n",Wire.i2c->DMA->channel);
//  }else{
////      Serial.print("Failed, using DMA\n");
//  }
  init_is31();
}

unsigned long beat_del = 1000;

bool firstfall = true;

void heartbeat(unsigned long stamp){
  if(clk_delta.last_delta < 100){
//    if(!env1.isActive() || env1.isSustain()){
    if(firstfall){
      firstfall = false;
//      Serial.println("long");
      AudioNoInterrupts();
//      testDc.amplitude(0.01, 1);
      env1.decay(11880*2.5);
      env3.decay(11880*2.5);
      env1.release(11880*2.5);
      env3.release(11880*2.5);
      env1.sustain(0.5);
      env3.sustain(0.5);
      env1.noteOn();
      env3.noteOn();
      AudioInterrupts();
    }else if(env3.isSustain()){
      env1.noteOff();
      env3.noteOff();
    }
    hrt_led.line(255, 0, clk_delta.last_delta * 0.4);
    tcp_led.line(255, 0, clk_delta.last_delta);
  }else if(stamp == clk_delta.stamp){
    firstfall = true;
    unsigned long len = clk_delta.last_delta * 0.25;
    AudioNoInterrupts();
    unsigned long atk = len < 100 ? len / 2 : 50;
    unsigned long dec = 400;

//    testDc.amplitude(0, 1);
//    if(dec > 400){ dec = 400; }

//    if(len < 40 ){
////      dec += (40 - len;
//    }

//    if(len < 100){
//      testDc.amplitude((100.0f - float(len)) / 50.0f, 1);
//    }else{
//      testDc.amplitude(0, 1);
//    }
//
//    if(len < 50){
//      dec = 11880;
//      atk = 0;
//      env1.decay(dec);
//      env2.decay(dec);
//      env3.decay(dec);
//      env4.decay(dec);
//    }

    env1.sustain(0);
    env3.sustain(0); 
    env2.sustain(0);
    env4.sustain(0);

    env1.attack(atk);
    env2.attack(atk);
    env3.attack(atk);
    env4.attack(atk);
    
    env1.decay(dec);
    env2.decay(dec);
    env3.decay(dec);
    env4.decay(dec);

    env1.release(0.0f);
    env3.release(0.0f);
    
    env1.noteOn();
    env3.noteOn();
    env2.noteOff();
    env4.noteOff();
    AudioInterrupts();

//    Serial.println(clk_delta.get_delta(stamp));
//    if(!clk_delta.get_delta(stamp)){
//      AudioNoInterrupts();
//      env1.attack(0);
//      env3.attack(0);
//      env1.attack(0);
//      env4.attack(0);
//      AudioInterrupts();
//    }else{
//      AudioNoInterrupts();
//      env1.attack(atk);
//      env3.attack(atk);
//      env1.attack(atk);
//      env4.attack(atk);
//      AudioInterrupts();
//    }
    beat2.set_len(len);
    beat2.set_trig(stamp);
    hrt_led.line(255, 0, clk_delta.last_delta * 0.4);
    tcp_led.line(255, 0, clk_delta.last_delta);
  }else if(beat2.get_trig(stamp)){
    AudioNoInterrupts();
    env1.noteOff();
    env3.noteOff();
    env2.noteOn();
    env4.noteOn();
    AudioInterrupts();
    hrt_led.line(255, 0, clk_delta.last_delta * 0.4);
    bcp_led.line(255, 0, clk_delta.last_delta);
  }
}

int light = 0;

unsigned long ledTimer = 0;
unsigned long i2cTimer = 0;

unsigned long clk_norm_timer = 0;

bool clk_in_flag = false;
unsigned long rn = 0;
int norm_pulse = 0;

void loop() {

  bool clk_in = digitalReadFast(CLK_IN);
  digitalWriteFast(ATK_OUT, clk_in);


  if(rn != millis()){
    rn = millis();
 
    if(rn > clk_norm_timer + analogRead(pot[0]) * 2 + 1){
      clk_norm_timer = rn;
      norm_pulse = 10;
    }
    
    bool pulse = norm_pulse > 0;
    digitalWriteFast(CLK_NORM, pulse);
    if(pulse){ --norm_pulse; }
    
    if(clk_in && !clk_in_flag){
      clk_delta.get_delta(rn);
      clk_delta.set_stamp(rn);
      hg_led.line(255, 0, 500);
      def_led.line(255, 0, 500);
      atk_led.line(255, 0, 500);
      fall_timer.set_timer(clk_delta.last_delta * 0.25);
      foil_led.set(random(255), clk_delta.last_delta);
    }
    clk_in_flag = clk_in;
    heartbeat(rn);
 
    if(fall_timer.check_timer(rn)){
      for(int i = 0; i < 9; ++i){
        if(i == light){
          lfall_led[i].set_broken(255);
          rfall_led[i].set_broken(255);
        }else{
          lfall_led[i].set(random(10), 100);
          rfall_led[i].set(random(10), 100);
        }
      }
      
      data_buf[36] = 0; //update leds register write
      light = ((light + 1) % 9);
      ledTimer = rn;
    }

    float vol = (float(analogRead(A8)) - 5.0) / 1018.0f;
    if(vol < 0){ vol = 0; }
    vol = powf(vol, 4);

    amp1.gain(vol*100);

    float cut = 100.0f + 300.0f * (float(analogRead(pot[1])) / 1023.0f);

    for(int i = 0; i < 3; ++i){
      filt.setLowpass(i, cut, 0.7);
    } 
    
    if(led_refresh.check_timer(rn)){
      data_buf[FOIL] = foil_led.port();
      data_buf[TCP] = tcp_led.port();
      data_buf[BCP] = bcp_led.port();
      data_buf[ATK] = atk_led.port();
      data_buf[DEF] = def_led.port();
      data_buf[HRT] = hrt_led.port();
      data_buf[HG] = hg_led.port();
 
      for(int i = 0; i < 9; ++i){
        data_buf[rfall[i]] = rfall_led[i].port();
        data_buf[lfall[i]] = lfall_led[i].port();
      }
      i2cTimer = rn;
      write_is31_pwm(data_buf);
    }
  }

  clk_in = digitalReadFast(CLK_IN);
  digitalWriteFast(ATK_OUT, clk_in);
 
}
 
Could the problem be caused by this library in your main file? #include "IS31_I2C.h".
Google did not return a result when searching for "IS31_I2C.h", so I can't check further.

Paul
 
Could the problem be caused by this library in your main file? #include "IS31_I2C.h".
Google did not return a result when searching for "IS31_I2C.h", so I can't check further.

Paul
IS31_I2C.h is the first code section. This code section is included in main as IS31_I2C.h
 
To solve this I had to find the default Wire library and modify it as I believe that gets included by the Teensy Audio library.

Commenting out these lines in WireKinetis.cpp

C++:
// #ifdef WIRE_IMPLEMENT_WIRE
// constexpr uintptr_t i2c0_addr = KINETIS_I2C0_ADDRESS;
// TwoWire Wire(i2c0_addr, TwoWire::i2c0_hardware);
// void i2c0_isr(void) { Wire.isr(); }
// #endif
// #ifdef WIRE_IMPLEMENT_WIRE1
// constexpr uintptr_t i2c1_addr = KINETIS_I2C1_ADDRESS;
// TwoWire Wire1(i2c1_addr, TwoWire::i2c1_hardware);
// void i2c1_isr(void) { Wire1.isr(); }
// #endif
// #ifdef WIRE_IMPLEMENT_WIRE2
// constexpr uintptr_t i2c2_addr = KINETIS_I2C2_ADDRESS;
// TwoWire Wire2(i2c2_addr, TwoWire::i2c2_hardware);
// void i2c2_isr(void) { Wire2.isr(); }
// #endif
// #ifdef WIRE_IMPLEMENT_WIRE3
// constexpr uintptr_t i2c3_addr = KINETIS_I2C3_ADDRESS;
// TwoWire Wire3(i2c3_addr, TwoWire::i2c3_hardware);
// void i2c3_isr(void) { Wire3.isr(); }
// #endif

This is obviously far from an ideal solution as the Wire library is buried deep in the Teensy hardware folder but I needed something that would allow my project to compile tonight and this worked.
 
As far as I recall this was an issue during initial development as well. The Audio library called Wire and left no good method for resolving the conflicts this created with the i2c_t3 library. Doesn't matter whether or not any audio objects I was using actually used the Wire library, since Wire just gets instantiated as a global object.

Is there any better solution for resolving this conflict than the workaround I ended up doing?

I realize Teensy 3.2 is deprecated at this point so probably not a high priority but maybe this is something to look at in the audio library as a whole?
 
Back
Top