A low cost DIY sound pressure level sensor for enabling environmental noise awareness. https://lukasschwarz.org/noise-sensor
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. I2C_DMAC is a non-blocking I2C library that uses a SERCOM in
  3. conjunction with the Direct Memory Access Controller (DMAC).
  4. Copyright (C) Martin Lindupp 2018
  5. V1.0.0 -- Initial release
  6. V1.1.0 -- Add Arduino MKR and SAMD51 support, plus multiple I2C instances
  7. V1.1.1 -- Replaced pinPeripheral() function with port register manipulation
  8. V1.1.2 -- Allow other classes to simultaneously use remaining DMAC channels
  9. V1.1.3 -- Fixed issue with consecutive calls to writeByte() overwriting data
  10. V1.1.4 -- Allow the DMAC to resume normal operation after an early NACK is received
  11. V1.1.5 -- Activate internal pull-up resistors and increase driver strength
  12. V1.1.6 -- Add SERCOM ALT (alternative) peripheral switch for the Metro M4
  13. V1.1.7 -- Arduino IDE library manager release
  14. V1.1.8 -- Code optimisation
  15. V1.1.9 -- Use default arguments for begin() member function
  16. V1.1.10 -- Remove I2C instance on writeBusy flag in ReadByte() and ReadBytes() functions
  17. V1.1.11 -- Arduino IDE library manager release
  18. The MIT License (MIT)
  19. Permission is hereby granted, free of charge, to any person obtaining a copy
  20. of this software and associated documentation files (the "Software"), to deal
  21. in the Software without restriction, including without limitation the rights
  22. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  23. copies of the Software, and to permit persons to whom the Software is
  24. furnished to do so, subject to the following conditions:
  25. The above copyright notice and this permission notice shall be included in all
  26. copies or substantial portions of the Software.
  27. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  28. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  30. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  31. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  32. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  33. SOFTWARE.
  34. */
  35. #ifndef _I2C_DMAC_h
  36. #define _I2C_DMAC_h
  37. #include <Arduino.h>
  38. #include "DMAC.h"
  39. enum { REG_ADDR_8BIT = 1, REG_ADDR_16BIT }; // Register address mode definitions, 8-bit address or 16-bit address
  40. class I2C_DMAC {
  41. public:
  42. I2C_DMAC(SERCOM* s, uint8_t pinSDA, uint8_t pinSCL); // Class constructor to initialise, SERCOM class, pins and member variables
  43. void begin(uint32_t baudrate = 100000, // Begin with 100kHz default clock rate and 8-bit register address mode
  44. uint8_t regAddrMode = REG_ADDR_8BIT,
  45. EPioType ulPeripheral = PIO_SERCOM);
  46. void end(); // Tear down and tidy up resources
  47. void setClock(uint32_t baudrate); // Set the I2C bus clock speed to the specified baud rate
  48. void setWriteChannel(uint8_t channel); // Set the DMAC write channel number (0 - 11), default 0
  49. void setReadChannel(uint8_t channel); // Set the DMAC read channel number (0 - 11), default 1
  50. void setPriority(uint8_t priority); // Set the priority level for both read and write DMAC channels (0 - 3), default 0
  51. void setRegAddrMode(uint8_t regAddrMode); // Set the register address mode REG_ADDR_8BIT or REG_ADDR_16BIT
  52. void initWriteBytes(uint8_t devAddress, uint8_t* data, uint8_t count); // Initialise DMAC to send data, (no register address)
  53. void initWriteBytes(uint8_t devAddress, uint16_t regAddress, uint8_t* data, uint8_t count); // Initialise DMAC to send register address + data
  54. void initWriteByte(uint8_t devAddress, uint16_t regAddress, uint8_t data); // Initialise DMAC to send register address + 1 data byte
  55. void initWriteRegAddr(uint8_t devAddress, uint16_t regAddress); // Initialise DMAC to send register address, (no data)
  56. void initReadBytes(uint8_t devAddress, uint8_t* data, uint8_t count); // Initialise DMAC to receive data
  57. void initReadByte(uint8_t devAddress); // Initialise DMAC to receive 1 data byte
  58. uint8_t getData(); // Retrieve the received data byte
  59. void write(); // Transmit on I2C bus
  60. void read(); // Receive on I2C bus
  61. void writeBytes(uint8_t devAddress, uint16_t regAddress, uint8_t* data, uint8_t count); // Transmit data to the I2C device's register address
  62. void writeByte(uint8_t devAddress, uint16_t regAddress, uint8_t data); // Transmit 1 data byte to the I2C device's register address
  63. void writeRegAddr(uint8_t devAddress, uint16_t regAddress); // Write the register address to the I2C device
  64. void readBytes(uint8_t devAddress, uint8_t* data, uint8_t count); // Receive data from the I2C device
  65. void readByte(uint8_t devAddress); // Receive 1 data byte from the I2C device
  66. void readBytes(uint8_t devAddress, uint16_t regAddress, uint8_t* data, uint8_t count); // Receive data from the I2C device's register address
  67. void readByte(uint8_t devAddress, uint16_t regAddress); // Receive a byte from the I2C device's register address
  68. void attachWriteCallback(voidFuncPtr callback); // Attach a DMAC write callback function
  69. void attachReadCallback(voidFuncPtr callback); // Attach a DMAC read callback function
  70. void attachDmacErrorCallback(voidFuncPtr callback); // Attach a DMAC error callback function
  71. void attachSercomErrorCallback(voidFuncPtr callback); // Attach a SERCOM error callback function
  72. void detachWriteCallback(); // Detach the DMAC write callback function
  73. void detachReadCallback(); // Detach the DMAC read callback function
  74. void detachDmacErrorCallback(); // Detach the DAMC error callback function
  75. void detachSercomErrorCallback(); // Detach the SERCOM error callback function
  76. static void DMAC_IrqHandler(); // DMAC interrupt handler function
  77. void SERCOM_IrqHandler(); // SERCOM interrupt handler function
  78. volatile boolean writeBusy; // Write busy flag - indicates write transfer in progress
  79. volatile boolean readBusy; // Read busy flag - indicates read transfer in progress
  80. static volatile I2C_DMAC* i2cDmacPtrs[SERCOM_INST_NUM]; // Array of pointer to each instance (object) of this class
  81. static volatile uint8_t instanceCounter; // Number of instances (objects) of this class
  82. protected:
  83. // Generic initialise write DMAC transfer function
  84. void initWriteBytes(uint8_t devAddress, uint16_t regAddress, uint8_t* data, uint8_t count, uint8_t readAddrLength);
  85. private:
  86. enum { WRITE, READ }; // I2C read and write bits definitions, WRITE: 0, READ: 1
  87. dmacdescriptor linked_descriptor __attribute__ ((aligned (16))); // DMAC linked descriptor
  88. Sercom* sercom; // Pointer to the selected SERCOMx peripheral
  89. uint8_t pinSDA; // The selected SDA pin
  90. uint8_t pinSCL; // The selected SCL pin
  91. uint8_t devAddress; // The I2C device address
  92. uint8_t regAddress[2]; // The I2C device's register address sent MSB first, LSB last
  93. uint8_t data; // Used for single byte data transfer
  94. uint8_t writeCount; // The number of data bytes to transmit
  95. uint8_t readCount; // The number of data bytes to receive
  96. uint8_t regAddrLength; // The length of the register address, 0: data only, 1: 8-bit, 2: 16-bit
  97. uint8_t regAddrMode; // The current register address mode: REG_ADDR_8BIT or REG_ADDR_16BIT
  98. uint8_t dmacPriority; // The DMAC read and write priority level
  99. uint8_t dmacWriteTrigger; // The DMAC write peripheral trigger source
  100. uint8_t dmacReadTrigger; // The DMAC read peripheral trigger source
  101. uint8_t genericClockId; // The generic clock ID used to select the sercom peripheral to be clocked
  102. IRQn_Type nvicId; // The Nested Vector Interrupt (NVIC) interrupt type for the SERCOMx peripheral
  103. typedef void (*voidFuncPtr)(void); // Alias for function pointer declarations
  104. volatile voidFuncPtr writeCallback; // Write callback function pointer
  105. volatile voidFuncPtr readCallback; // Read callback function pointer
  106. volatile voidFuncPtr errorDmacCallback; // DMAC error callback function pointer
  107. volatile voidFuncPtr errorSercomCallback; // SERCOM error callback function pointer
  108. volatile uint8_t dmacWriteChannel; // DMAC write channel number (0 to 11), default 0
  109. volatile uint8_t dmacReadChannel; // DMAC read channel number (0 to 11), default 1
  110. };
  111. #if WIRE_INTERFACES_COUNT > 0
  112. extern I2C_DMAC I2C; // Indicate that the I2C object is externally instantiated
  113. #endif
  114. #if WIRE_INTERFACES_COUNT > 1
  115. extern I2C_DMAC I2C1; // Indicate that the I2C1 object is externally instantiated
  116. #endif
  117. #if WIRE_INTERFACES_COUNT > 2
  118. extern I2C_DMAC I2C2; // Indicate that the I2C2 object is externally instantiated
  119. #endif
  120. #if WIRE_INTERFACES_COUNT > 3
  121. extern I2C_DMAC I2C3; // Indicate that the I2C3 object is externally instantiated
  122. #endif
  123. #if WIRE_INTERFACES_COUNT > 4
  124. extern I2C_DMAC I2C4; // Indicate that the I2C4 object is externally instantiated
  125. #endif
  126. #if WIRE_INTERFACES_COUNT > 5
  127. extern I2C_DMAC I2C5; // Indicate that the I2C5 object is externally instantiated
  128. #endif
  129. #endif