Skip to content

Commit

Permalink
Lingering Wire synchronisation with DxCore
Browse files Browse the repository at this point in the history
  • Loading branch information
MX682X committed Apr 16, 2024
1 parent 390410d commit 876f12b
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 355 deletions.
16 changes: 15 additions & 1 deletion megaavr/libraries/Wire/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,18 @@ uint8_t checkPinLevels();
```
This function returns the level of the master TWI pins, depending on the used TWI module and port multiplexer settings. Bit 0 represents SDA line and bit 1 represents SCL line. This is useful on initialisation, where you want to make sure that all devices have their pins ready in open-drain mode. A value of 0x03 indicates that both lines have a HIGH level and the bus is ready.

#### `uint8_t masterTransmit()`
```c++
uint8_t masterTransmit(auto *length, uint8_t *buffer, uint8_t addr, uint8_t sendStop);
```
This functions allows to transmit a buffer of data without having to copy the data to the internal buffer of the library. This allows transmission lengths as long as the RAM size without having to define the TWI_BUFFER_SIZE in the platform.txt. The return value is the same as endTransmission(). length will be overwritten with the actual amount of written bytes.
#### `uint8_t masterReceive()`
```c++
uint8_t masterReceive(auto *length, uint8_t *buffer, uint8_t addr, uint8_t sendStop);
```
This functions allows to receive a buffer of data without having to copy the data from the internal buffer of the library. This allows transmission lengths as long as the RAM size without having to define the TWI_BUFFER_SIZE in the platform.txt. The return value is the same as endTransmission(). length will be overwritten with the actual amount of received bytes.

### Additional New Methods not available on all parts
These new methods are available exclusively for parts with certain specialized hardware; Most full-size parts support enableDualMode (but tinyAVR does not), while only the DA and DB-series parts have the second TWI interface that swapModule requires.
#### `void swapModule()`
Expand Down Expand Up @@ -323,6 +335,8 @@ When the second or third argument was used, `Wire.getIncomingAddress()` should b

If (and only if) the Master and Slave option is selected in the Tools -> Wire mode, the Wire interface can be enabled for both master and slave. Even when Dual Mode is used, the correct option must still be selected to enable acting as both master and slave.

The Arduino library defines the array lengths as `BUFFER_LENGTH`, however, this define name might create conflicts, as the name is quite arbitrary. The newest library version uses the name `TWI_BUFFER_LENGTH` instead. However, it is still backwards compatible, as the `BUFFER_LENGTH` is still applied, but a compiler warning is generated to notify about the change.

#### `void setClock()`
```c++
void setClock(uint32_t);
Expand Down Expand Up @@ -419,7 +433,7 @@ The implementation isn't identical, but the behaviour is unchanged, or is differ
#### Write Sequence
1. Master generates start condition.
2. Master clocks out the slave address with out read-bit set..
2. Master clocks out the slave address without read-bit set..
3. Slave detects and ACKs.
4. Master clocks out 1 or more data bytes as slave ACKs them.
5. Master generates a Stop Condition.
Expand Down

This file was deleted.

55 changes: 55 additions & 0 deletions megaavr/libraries/Wire/examples/master_read/master_read.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* Wire Master Read
* by MX682X
*
* Demonstrates use of the New Wire library
* Reads data from an I2C/TWI slave device
* Refer to the "Wire Slave Write" example for use with this
*
* This example takes the input from Serial. If the serial input is 'm' or 'M',
* this code requests 4 bytes from the slave with the address 0x54.
* When using together with the complementary example, the slave sends it's millis() value.
* This value is then sent to the serial monitor
*
* To use this, you need to connect the SCL and SDA pins of this device to the
* SCL and SDA pins of a second device running the Wire Slave Write example.
*
* Pullup resistors must be connected between both data lines and Vcc.
* See the Wire library README.md for more information.
*/

#define MySerial Serial

#include <Wire.h>

int8_t rxLen = 0;
int8_t len = 0;

void setup() {
Wire.begin(); // initialize master
MySerial.begin(115200);
}

void loop() {
if (MySerial.available() > 0) { // as soon as the first byte is received on Serial
char c = MySerial.read(); // read the data from serial.
if (c == 'm' || c == 'M') {
sendDataWire(); // send the data over I2C
}
len = 0; // since the data was sent, the position is 0 again
}
}

void sendDataWire() {
uint32_t ms;
if (4 == Wire.requestFrom(0x54, 4, 0x01)) { // request from slave
while (Wire.available()) {
ms = (uint32_t)Wire.read(); // read out 32-bit wide data
ms |= (uint32_t)Wire.read() << 8;
ms |= (uint32_t)Wire.read() << 16;
ms |= (uint32_t)Wire.read() << 24;
MySerial.println(ms); // print the milliseconds from Slave
}
} else {
MySerial.println("Wire.requestFrom() timed out!");
}
}
64 changes: 64 additions & 0 deletions megaavr/libraries/Wire/examples/master_write/master_write.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* Wire Master Write
* by MX682X
*
* Demonstrates use of the New Wire library
* Writes data to an I2C/TWI slave device
* Refer to the "Wire Slave Read" example for use with this
*
* Enter any data using serial monitor or other console followed by either or
* both of the line ending characters, and it will be sent to the slave, which
* should print it out on it's serial port.
*
* To use this, you need to connect the SCL and SDA pins of this device to the
* SCL and SDA pins of a second device running the Wire Slave Read example.
*
* Pullup resistors must be connected between both data lines and Vcc.
* See the Wire library README.md for more information.
*/

#include <Wire.h>

char input[32];
int8_t len = 0;

#define MySerial Serial // The serial port connected to the to the computer.

void setup() {
Wire.begin(); // initialize master
// MySerial.swap(1); // Remember to swap serial pins if you need to do that with your connections.
MySerial.begin(115200); // Use 115200 baud - this is the 2020's, and these are modern AVRs.
}

void loop() {
if (MySerial.available() > 0) { // as soon as the first byte is received on Serial
readFromSerial(); // read the data from the Serial interface
if (len > 0) { // after the while-loop, if there was useful data,
sendDataWire(); // send the data over I2C
}
len = 0; // since the data was sent, the position is 0 again
}
}

void readFromSerial() {
while (true) { // in an endless while-loop
while (MySerial.available() == 0);// means we've taken all the bytes in, and are still waiting for a cr/lf.
char c = MySerial.read(); // read the next char, now that there's one available.
if (c == '\n' || c == '\r') { // until a new line or carriage return is found
break; // if so, break the endless while-loop
} // otherwise
input[len] = c; // save the char
len++; // increment the position
if (len > 30) { // if there was too much data
break; // break the while-loop to avoid buffer overflow
}
}
}

void sendDataWire() {
Wire.beginTransmission(0x54); // prepare transmission to slave with address 0x54
for (uint8_t i = 0; i < len; i++) {
Wire.write(input[i]); // Write the received data to the bus buffer
}
Wire.write("\r\n"); // add new line and carriage return for the Serial monitor
Wire.endTransmission(); // finish transmission
}

This file was deleted.

40 changes: 40 additions & 0 deletions megaavr/libraries/Wire/examples/slave_read/slave_read.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* Wire Slave Read
* by MX682X
*
* Demonstrates use of the Wire library
* Receives data as an I2C/TWI slave device
* Refer to the "Wire Master Write" example for use with this
*
* This example prints everything that is received on the I2C bus to the
* serial monitor.
*
* To use this, you need to connect the SCL and SDA pins of this device to the
* SCL and SDA pins of a second device running the Master Write example.
*
* Pullup resistors must be connected between both data lines and Vcc.
* See the Wire library README.md for more information.
*/

#include <Wire.h>

#define MySerial Serial

void setup() {
Wire.begin(0x54); // join i2c bus with address 0x54
Wire.onReceive(receiveDataWire); // give the Wire library the name of the function
// that will be called on a master write event
MySerial.begin(115200);
}

void loop() {
delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveDataWire(int16_t numBytes) { // the Wire library tells us how many bytes
for (uint8_t i = 0; i < numBytes; i++) { // were received so we can for loop for that
char c = Wire.read(); // amount and read the received data
MySerial.write(c); // to print it to the Serial Monitor
}
}
Loading

0 comments on commit 876f12b

Please sign in to comment.