The SeeSaw operates as an I2C secondary device using standard I2C protocol. It uses the SDA and SCL pins to communicate with the host system.
The I2C bus on the SAMD09 is 3.3V logic level, but all boards other than the SAMD09 breakout have level shifting so you can use 3 or 5V logic. Boards with Attiny chips are 3 or 5V safe so you can use either for power and logic
Only 7-bit addressing is supported.
I2C pullup resistors are included in our SeeSaw boards but if you are DIY'ing, be sure to add your own! 2.2K - 10K is a good range.
Setting the Device Address
Standard 7-bit addressing is used. The seesaw's default I2C address is initially configured in the compiled firmware (e.g for theSeeSaw breakouts we use 0x49) but other boards will have a different base address. Check the board documentation for the default base I2C address, or you can plug it in and scan the I2C bus to find it.
This address can be modified using the address select pins, there can be multiple address pins. If address select pin 0 (A0) is tied to ground on boot, the I2C address is incremented by 1. If address select pin 1 (A1) is pulled low, the I2C address is incremented by 2. If both address select pins are pulled low, the I2C address is incremented by 3. Thus you can, with the same hardware, have up to 4 devices
On both the SAMD09 and Attiny817 breakouts, the default A0 pin is 16, default A1 pin is 17. On boards where the chips are embedded, there may be as many as 4 address pins, they'll be labeled with jumpers
The base I2C address can also be modified by writing a new address to EEPROM. See the EEPROM section for more information.
I2C Transactions
We recommend using 100KHz I2C, but speeds of up to 400KHz are supported. You may want to decrease the SDA/SCL pullups to 2.2K from 10K in that case.
Writing Data
A seesaw write command consists of the standard I2C write header (with the R/W bit set to 0), followed by 2 register bytes followed by zero or more data bytes.
The first register byte is the module base register address. Each module (GPIO, ADC, DAC, etc.) has it's own unique 8 bit base identifier.
The second register byte is the module function register address. This byte specifies the desired register within the module to be written.
Thus we have up to 254 modules available (0x00 is reserved) and 255 functions per module - plenty to allow all sorts of different capabilities!
In code, this may look like this (using the Arduino wire I2C object):
void Adafruit_seesaw::write(uint8_t moduleBase, uint8_t moduleFunction, uint8_t *buf, uint8_t num) { Wire.beginTransmission((uint8_t)_i2caddr); Wire.write((uint8_t)moduleBase); //module base register address Wire.write((uint8_t)moduleFunction); //module function register address Wire.write((uint8_t *)buf, num); //data bytes Wire.endTransmission(); }
Base Register Summary
The following table summarizes the module base registers addresses. Further details about the function registers associated for each base register are covered in later sections.
Base Register Address |
Module |
0x00 |
Status |
0x01 |
GPIO |
0x02 - 0x07 |
SERCOM |
0x08 |
PWM |
0x09 |
ADC |
0x0A |
DAC |
0x0B |
Interrupt |
0x0C |
DAP |
0x0D |
EEPROM |
0x0E |
NeoPixel |
0x0F |
Touch |
0x10 |
Keypad |
0x11 |
Encoder |
Reading Data
A register read is accomplished by first sending the standard I2C write header, followed by the two register bytes corresponding to the data to be read. Allow a short delay, and then send a standard I2C read header (with the R/W bit set to 1) to read the data.
The length of the required delay depends on the data that is to be read. These delays are discussed in the sections specific to each module.
In code, this may look like this (using the Arduino wire I2C object):
void Adafruit_seesaw::read(uint8_t moduleBase, uint8_t moduleFunction, uint8_t *buf, uint8_t num, uint16_t delay) { Wire.beginTransmission((uint8_t)_i2caddr); Wire.write((uint8_t)moduleBase); //module base register address Wire.write((uint8_t)moduleFunction); //module function register address Wire.endTransmission(); delayMicroseconds(delay); Wire.requestFrom((uint8_t)_i2caddr, num); for(int i=0; i<num; i++){ buf[i] = Wire.read(); } }
Page last edited March 08, 2024
Text editor powered by tinymce.