# Porting ## Upgrading Circuits.I2C 1.0 projects to 2.0 Circuits.I2C 2.0 supports alternative I2C hardware and the ability to mock or emulate devices via backends. The Linux i2c-dev backend is the default and this matches Circuits.I2C 1.0. Most projects won't need any changes other than to update the dependency in `mix.exs`. If upgrading a library, The following dependency specification is recommended to allow both `circuits_i2c` versions: ```elixir {:circuits_i2c, "~> 2.0 or ~> 1.0"} ``` The following potentially breaking changes were made: 1. `Circuits.I2C.open/1` no longer accepts Erlang strings. 2. The `stub` implementation has been renamed to `i2c_dev_test`. If using the stub implementation for testing, you may have to update your tests since there were minor changes. ## Upgrading Elixir/ALE projects to Circuits.I2C The `Circuits.I2C` package is the next version of Elixir/ALE's I2C support. If you're currently using Elixir/ALE, you're encouraged to switch. Here are some benefits: 1. Supported by both the maintainer of Elixir/ALE and a couple others. They'd prefer to support `Circuits.I2C` issues. 2. Much faster than Elixir/ALE. 3. Simplified API `Circuits.I2C` uses Erlang's NIF interface. NIFs have the downside of being able to crash the Erlang VM. Experience with Elixir/ALE has given many of us confidence that this won't be a problem. ### Code modifications `Circuits.I2C` is not a `GenServer`, so if you've added `ElixirALE.I2C` to a supervision tree, you'll have to take it out and manually call `Circuits.I2C.open` to obtain a reference. A common pattern is to create a `GenServer` that is descriptive of what the I2C device does and have it be responsible for all I2C calls. The remain modifications should mostly be mechanical: 1. Rename references to `ElixirALE.I2C` to `Circuits.I2C` and `elixir_ale` to `circuits_i2c` 2. Change calls to `ElixirALE.I2C.start_link/2` to `Circuits.I2C.open/1`. You'll need to remove the I2C address from the call to open. While you're at it, review the arguments to open to not include any `GenServer` options. 3. Add the I2C device's bus address to all of the `read`, `write`, and `write_read` calls. We recommend making a short helper function that has the I2C address. 4. The `read` and `write_read` functions now return `{:ok, result}` tuples on success so add code to handle that. Alternately, call `read!` or `write_read!` and they will raise an exception if there's an error. 5. Look for calls to `I2C.read_device`, `I2C.write_device` and `I2C.write_read_device` and remove the `_device` part. 6. Consider adding a call to `Circuits.I2C.close/1` if there's an obvious place to release the I2C. This is not strictly necessary since the garbage collector will free unreferenced I2C references. 7. If you manually implemented I2C bus retry logic, consider specifying the `:retries` option to have `Circuits.I2C` retry for you. 8. Change calls to `ElixirALE.I2C.device_names/0` to `Circuits.I2C.bus_names/0`. If you find that you have to make any other changes, please let us know via an issue or PR so that other users can benefit.