PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
4.9KB

  1. // -------------------------------------------------------------------------------------------
  2. // I2C Advanced Slave
  3. // -------------------------------------------------------------------------------------------
  4. //
  5. // This creates an I2C slave device with simple read/write commands and a small
  6. // addressable memory. Note that this communication adds a protocol layer on top of
  7. // normal I2C read/write procedures. As such, it is meant to pair with the advanced_master
  8. // sketch. The read/write commands are described below.
  9. //
  10. // For basic I2C communication only, refer to basic_master and basic_slave example sketches.
  11. //
  12. // This example code is in the public domain.
  13. //
  14. // -------------------------------------------------------------------------------------------
  15. // WRITE - The I2C Master can write to the device by transmitting the WRITE command,
  16. // a memory address to store to, and a sequence of data to store.
  17. // The command sequence is:
  18. //
  19. // START|I2CADDR+W|WRITE|MEMADDR|DATA0|DATA1|DATA2|...|STOP
  20. //
  21. // where START = I2C START sequence
  22. // I2CADDR+W = I2C Slave address + I2C write flag
  23. // WRITE = WRITE command
  24. // MEMADDR = memory address to store data to
  25. // DATAx = data byte to store, multiple bytes are stored to increasing address
  26. // STOP = I2C STOP sequence
  27. // -------------------------------------------------------------------------------------------
  28. // READ - The I2C Master can read data from the device by transmitting the READ command,
  29. // a memory address to read from, and then issuing a STOP/START or Repeated-START,
  30. // followed by reading the data. The command sequence is:
  31. //
  32. // START|I2CADDR+W|READ|MEMADDR|REPSTART|I2CADDR+R|DATA0|DATA1|DATA2|...|STOP
  33. //
  34. // where START = I2C START sequence
  35. // I2CADDR+W = I2C Slave address + I2C write flag
  36. // READ = READ command
  37. // MEMADDR = memory address to read data from
  38. // REPSTART = I2C Repeated-START sequence (or STOP/START if single Master)
  39. // I2CADDR+R = I2C Slave address + I2C read flag
  40. // DATAx = data byte read by Master, multiple bytes are read from increasing address
  41. // STOP = I2C STOP sequence
  42. // -------------------------------------------------------------------------------------------
  43. // SETRATE - The I2C Master can adjust the Slave configured I2C rate with this command
  44. // The command sequence is:
  45. //
  46. // START|I2CADDR+W|SETRATE|RATE0|RATE1|RATE2|RATE3|STOP
  47. //
  48. // where START = I2C START sequence
  49. // I2CADDR+W = I2C Slave address + I2C write flag
  50. // SETRATE = SETRATE command
  51. // RATE0-3 = I2C frequency (uint32_t) LSB-to-MSB format
  52. // -------------------------------------------------------------------------------------------
  53. #include <i2c_t3.h>
  54. // Command definitions
  55. #define WRITE 0x10
  56. #define READ 0x20
  57. #define SETRATE 0x30
  58. // Function prototypes
  59. void receiveEvent(size_t count);
  60. void requestEvent(void);
  61. // Memory
  62. #define MEM_LEN 256
  63. uint8_t mem[MEM_LEN];
  64. volatile uint8_t cmd;
  65. volatile size_t addr;
  66. volatile uint32_t rate;
  67. //
  68. // Setup
  69. //
  70. void setup()
  71. {
  72. pinMode(LED_BUILTIN,OUTPUT); // LED
  73. // Setup for Slave mode, address 0x44, pins 18/19, external pullups, 400kHz
  74. Wire.begin(I2C_SLAVE, 0x44, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
  75. // init vars
  76. cmd = 0;
  77. addr = 0;
  78. memset(mem, 0, sizeof(mem));
  79. rate = 400000;
  80. // register events
  81. Wire.onReceive(receiveEvent);
  82. Wire.onRequest(requestEvent);
  83. Serial.begin(115200);
  84. }
  85. void loop()
  86. {
  87. digitalWrite(LED_BUILTIN,HIGH); // double pulse LED while waiting for I2C requests
  88. delay(10); // if the LED stops the slave is probably stuck in an ISR
  89. digitalWrite(LED_BUILTIN,LOW);
  90. delay(100);
  91. digitalWrite(LED_BUILTIN,HIGH);
  92. delay(10);
  93. digitalWrite(LED_BUILTIN,LOW);
  94. delay(880);
  95. }
  96. //
  97. // handle Rx Event (incoming I2C request/data)
  98. //
  99. void receiveEvent(size_t count)
  100. {
  101. if(count)
  102. {
  103. // grab command
  104. cmd = Wire.readByte();
  105. switch(cmd)
  106. {
  107. case WRITE:
  108. addr = Wire.readByte(); // grab addr
  109. Wire.read(&mem[addr], count-2); // copy Rx data to databuf
  110. break;
  111. case READ:
  112. addr = Wire.readByte(); // grab addr
  113. break;
  114. case SETRATE:
  115. if(Wire.available() >= 4)
  116. {
  117. rate = Wire.readByte(); // grab rate
  118. rate |= Wire.readByte() << 8;
  119. rate |= Wire.readByte() << 16;
  120. rate |= Wire.readByte() << 24;
  121. Wire.setClock(rate); // set rate
  122. }
  123. break;
  124. }
  125. }
  126. }
  127. //
  128. // handle Tx Event (outgoing I2C data)
  129. //
  130. void requestEvent(void)
  131. {
  132. switch(cmd)
  133. {
  134. case READ:
  135. Wire.write(&mem[addr], MEM_LEN-addr); // fill Tx buffer (from addr location to end of mem)
  136. break;
  137. }
  138. }