-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
05b0d9e
commit ae42b5e
Showing
33 changed files
with
3,913 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.idea | ||
.pio | ||
cmake-build-teensy40 | ||
CMakeListsPrivate.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Continuous Integration (CI) is the practice, in software | ||
# engineering, of merging all developer working copies with a shared mainline | ||
# several times a day < https://docs.platformio.org/page/ci/index.html > | ||
# | ||
# Documentation: | ||
# | ||
# * Travis CI Embedded Builds with PlatformIO | ||
# < https://docs.travis-ci.com/user/integration/platformio/ > | ||
# | ||
# * PlatformIO integration with Travis CI | ||
# < https://docs.platformio.org/page/ci/travis.html > | ||
# | ||
# * User Guide for `platformio ci` command | ||
# < https://docs.platformio.org/page/userguide/cmd_ci.html > | ||
# | ||
# | ||
# Please choose one of the following templates (proposed below) and uncomment | ||
# it (remove "# " before each line) or use own configuration according to the | ||
# Travis CI documentation (see above). | ||
# | ||
|
||
|
||
# | ||
# Template #1: General project. Test it using existing `platformio.ini`. | ||
# | ||
|
||
# language: python | ||
# python: | ||
# - "2.7" | ||
# | ||
# sudo: false | ||
# cache: | ||
# directories: | ||
# - "~/.platformio" | ||
# | ||
# install: | ||
# - pip install -U platformio | ||
# - platformio update | ||
# | ||
# script: | ||
# - platformio run | ||
|
||
|
||
# | ||
# Template #2: The project is intended to be used as a library with examples. | ||
# | ||
|
||
# language: python | ||
# python: | ||
# - "2.7" | ||
# | ||
# sudo: false | ||
# cache: | ||
# directories: | ||
# - "~/.platformio" | ||
# | ||
# env: | ||
# - PLATFORMIO_CI_SRC=path/to/test/file.c | ||
# - PLATFORMIO_CI_SRC=examples/file.ino | ||
# - PLATFORMIO_CI_SRC=path/to/test/directory | ||
# | ||
# install: | ||
# - pip install -U platformio | ||
# - platformio update | ||
# | ||
# script: | ||
# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# !!! WARNING !!! AUTO-GENERATED FILE, PLEASE DO NOT MODIFY IT AND USE | ||
# https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags | ||
# | ||
# If you need to override existing CMake configuration or add extra, | ||
# please create `CMakeListsUser.txt` in the root of project. | ||
# The `CMakeListsUser.txt` will not be overwritten by PlatformIO. | ||
|
||
cmake_minimum_required(VERSION 3.2) | ||
project(teensy4_i2c) | ||
|
||
include(CMakeListsPrivate.txt) | ||
|
||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeListsUser.txt) | ||
include(CMakeListsUser.txt) | ||
endif() | ||
|
||
add_custom_target( | ||
PLATFORMIO_BUILD ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion run "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_BUILD_VERBOSE ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion run --verbose "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_UPLOAD ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion run --target upload "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_CLEAN ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion run --target clean "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_MONITOR ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion device monitor "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_TEST ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion test "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_PROGRAM ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion run --target program "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_UPLOADFS ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion run --target uploadfs "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>" | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_UPDATE_ALL ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion update | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_REBUILD_PROJECT_INDEX ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion init --ide clion | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_custom_target( | ||
PLATFORMIO_DEVICE_LIST ALL | ||
COMMAND ${PLATFORMIO_CMD} -f -c clion device list | ||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||
) | ||
|
||
add_executable(${PROJECT_NAME} ${SRC_LIST}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Make tests visible to CLion. | ||
# Use CLion's "Mark directory as" option to mark the "test" directory as a source folder. | ||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/test/test_register_i2c) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,90 @@ | ||
# teensy4_i2c | ||
An I2C library for the Teensy 4. Provides slave and master mode. | ||
#teensy4_i2c | ||
An I2C library for the [Teensy 4](https://www.pjrc.com/store/teensy40.html) | ||
microcontroller. | ||
|
||
The Teensy 4.0 uses the [NXP i.MXRT 1062](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/i.mx-rt-series/i.mx-rt1060-crossover-processor-with-arm-cortex-m7-core:i.MX-RT1060) | ||
microcontroller with n ARM Corex-M7 core. | ||
|
||
This library is intended to be used as a drop in replacement for the | ||
Wire library in [Teensyduino](https://www.pjrc.com/teensy/td_download.html). | ||
The primary reason for writing it was to add support for Slave mode. | ||
|
||
The driver implementations IMX_RT1060_I2CMaster and IMX_RT1060_I2CSlave have | ||
no dependencies on Arduino itself and relatively few dependencies on the | ||
Teensy code. This means that is should be possible to use the drivers with | ||
other tool sets without having to change too much. | ||
|
||
##Usage | ||
### Use I2C Register Wrappers | ||
I2CDevice and I2CRegisterSlave classes make it very simple to follow | ||
the standard I2C pattern of reading or writing to "registers". | ||
I recommend that you use this interface if it's suitable. | ||
|
||
1. Download the code and put it in your include path. | ||
1. #include "i2c_device.h" if you have a master and wish | ||
to read from a slave device. | ||
1. #include "i2c_register_slave.h" if you want to implement | ||
a slave device to be read by a master. | ||
1. See the examples in the examples/simple directory | ||
|
||
### Use the Driver Directly | ||
The driver interfaces are defined in i2c_driver.h. These provide | ||
everything you need to use I2C without the limitations of the Wire | ||
library. The key classes are I2CMaster and I2CSlave. | ||
|
||
1. Download the code and put it in your include path. | ||
1. #include "imx_rt1060_i2c_driver.h" | ||
1. See the examples in the examples/raw directory | ||
|
||
###Replacing Wire.h | ||
Follow these instructions if you have already written code to | ||
use Wire.h and don't want to change it. I don't recommend using | ||
the Wire API unless you have to. See below for alternatives. | ||
1. Download the code and put it in your include path. | ||
1. Change all #includes from Wire.h to i2c_driver_wire.h. | ||
1. If any of your dependencies use Wire.h you'll have to | ||
modify them to use i2c_driver_wire.h instead. | ||
1. See the examples in the examples/wire directory | ||
|
||
##Features | ||
* Supports all features that are required by the I2C specification | ||
for master, multi-master and slave devices. | ||
* Drop in replacement for the Wire library | ||
* Master Mode | ||
* Slave Mode | ||
* Standard Mode (100 kbps) | ||
* Fast Mode (400 kbps) | ||
* Fast Mode Plus (1 Mbps) | ||
* Multi-master support | ||
* Clock stretching in Slave Mode | ||
* Non-blocking API for Master Mode and Slave Mode | ||
* Comprehensive error handling | ||
|
||
## Not Tested | ||
I haven't been able to test some features because of hardware and time | ||
restrictions. These features *should* work but don't be surprised if | ||
they don't. Please contact me if you encounter any problems. | ||
* Multi-master configurations | ||
* Noisy environments | ||
* Cortex i.MX RT1050 | ||
|
||
## Not Implemented | ||
The following features are supported by the NXP i.MXRT 1062 processor but | ||
I haven't implemented them in this driver. | ||
Please contact me if you need any of these features. | ||
* Alternative pins for port 1 | ||
* Direct Memory Access (DMA) | ||
* High Speed Mode (3.4 Mbps) | ||
* Ultra Fast Mode (5 Mbps) | ||
* Multiple addresses for a single slave | ||
* 10 bit slave addresses | ||
* Glitch filter (for slave mode) | ||
* SMBus Alert | ||
* General Call | ||
* 4 pin I2C in Master mode | ||
* Master reading more than 256 bytes in a single transfer | ||
|
||
## Version History | ||
| Version | Release Date | Comment | | ||
| ------- |-------------------| ----------------| | ||
| v0.9.0 | 7th November 2019 | Initial Version | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// Copyright © 2019 Richard Gemmell | ||
// Released under the MIT License. See license.txt. (https://opensource.org/licenses/MIT) | ||
|
||
// This example WILL NOT work unless you have an INA260 | ||
// current sensor connected to pins 16 and 17. | ||
// | ||
// Demonstrates use of the raw I2C driver. | ||
// Creates an I2C master and reads a device with it. | ||
// | ||
// This is an advanced example. Use the "simple" examples | ||
// instead if you want to follow the typical usage pattern | ||
// for I2C. | ||
|
||
#include <Arduino.h> | ||
#include <i2c_driver.h> | ||
#include "imx_rt1060/imx_rt1060_i2c_driver.h" | ||
|
||
// Blink the LED to make sure the Teensy hasn't hung | ||
IntervalTimer blink_timer; | ||
volatile bool led_high = false; | ||
void blink_isr(); | ||
|
||
// The slave is an INA 260 current sensor | ||
const uint16_t slave_address = 0x40; | ||
const uint8_t manufacturer_id_register = 0xFE; | ||
const uint8_t die_id_register = 0xFF; | ||
I2CMaster& master = Master1; | ||
|
||
// Create a buffer to receive data from the slave. | ||
uint8_t rx_buffer[2] = {}; | ||
|
||
void finish(); | ||
bool ok(const char* message); | ||
uint16_t get_int_from_buffer(); | ||
|
||
void setup() { | ||
// Turn the LED on | ||
pinMode(LED_BUILTIN, OUTPUT); | ||
digitalWrite(LED_BUILTIN, true); | ||
|
||
// Create a timer to blink the LED | ||
blink_timer.begin(blink_isr, 500000); | ||
|
||
// Initialise the master | ||
master.begin(100 * 1000U); | ||
|
||
// Enable the serial port for debugging | ||
Serial.begin(9600); | ||
Serial.println("Started"); | ||
} | ||
|
||
void loop() { | ||
Serial.println(""); | ||
// Request the Manufacturer ID | ||
master.write_async(slave_address, (uint8_t*)&manufacturer_id_register, sizeof(manufacturer_id_register), false); | ||
finish(); | ||
if(ok("Failed to send manufacture id register value")) { | ||
master.read_async(slave_address, rx_buffer, sizeof(rx_buffer), true); | ||
finish(); | ||
if (ok("Failed to read manufacture ID.")) { | ||
uint16_t manufacturerID = get_int_from_buffer(); | ||
const uint16_t expected = 0x5449; | ||
if (manufacturerID == expected) { | ||
Serial.println("Got correct Manufacturer ID."); | ||
} else { | ||
Serial.printf("Manufacturer ID is 0x%X. Expected 0x%X.\n", manufacturerID, expected); | ||
} | ||
} | ||
} | ||
|
||
// Request the Die ID | ||
master.write_async(slave_address, (uint8_t*)&die_id_register, sizeof(die_id_register), false); | ||
finish(); | ||
if(ok("Failed to send die id register value")) { | ||
master.read_async(slave_address, rx_buffer, sizeof(rx_buffer), true); | ||
finish(); | ||
if (ok("Failed to read die ID.")) { | ||
uint16_t dieId = get_int_from_buffer(); | ||
const uint16_t expected = 0x2270; | ||
if (dieId == expected) { | ||
Serial.println("Got correct Die ID."); | ||
} else { | ||
Serial.printf("Die ID is 0x%X. Expected 0x%X.\n", dieId, expected); | ||
} | ||
} | ||
} | ||
|
||
delay(1000); | ||
} | ||
|
||
uint16_t get_int_from_buffer() { | ||
uint16_t result = ((uint16_t)rx_buffer[0] << 8U) + ((uint16_t)rx_buffer[1]); | ||
return result; | ||
} | ||
|
||
bool ok(const char* message) { | ||
if (master.has_error()) { | ||
Serial.print(message); | ||
Serial.print(" Error: "); | ||
Serial.println((int)master.error()); | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
void finish() { | ||
elapsedMillis timeout; | ||
while (timeout < 200) { | ||
if (master.finished()){ | ||
return; | ||
} | ||
} | ||
Serial.println("Master: ERROR timed out waiting for transfer to finish."); | ||
} | ||
|
||
void blink_isr() { | ||
led_high = !led_high; | ||
digitalWrite(LED_BUILTIN, led_high); | ||
} |
Oops, something went wrong.