mcp4725.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Driver for Microchip MCP4725 12-bit digital to analog converter.
  3. */
  4. #include "module.h"
  5. #include "lauxlib.h"
  6. #include "platform.h"
  7. #include "osapi.h"
  8. #define MCP4725_I2C_ADDR_BASE (0x60)
  9. #define MCP4725_I2C_ADDR_A0_MASK (0x01) // user configurable
  10. #define MCP4725_I2C_ADDR_A1_MASK (0x02) // hard wired at factory
  11. #define MCP4725_I2C_ADDR_A2_MASK (0x04) // hard wired at factory
  12. #define MCP4725_COMMAND_WRITE_DAC (0x40)
  13. #define MCP4725_COMMAND_WRITE_DAC_EEPROM (0x60)
  14. #define MCP4725_POWER_DOWN_NORMAL (0x00)
  15. #define MCP4725_POWER_DOWN_RES_1K (0x02)
  16. #define MCP4725_POWER_DOWN_RES_100K (0x04)
  17. #define MCP4725_POWER_DOWN_RES_500K (0x06)
  18. static const unsigned mcp4725_i2c_id = 0;
  19. static uint8 get_address(lua_State* L, uint8 i2c_address){
  20. uint8 addr_temp = i2c_address;
  21. uint16 temp_var = 0;
  22. lua_getfield(L, 1, "A2");
  23. if (!lua_isnil(L, -1))
  24. {
  25. if( lua_isnumber(L, -1) )
  26. {
  27. temp_var = lua_tointeger(L, -1);
  28. if(temp_var < 2){
  29. temp_var = MCP4725_I2C_ADDR_A2_MASK & (temp_var << 2);
  30. addr_temp|=temp_var;
  31. }
  32. else
  33. return luaL_argerror( L, 1, "A2: Must be 0 or 1" );
  34. }
  35. else
  36. {
  37. return luaL_argerror( L, 1, "A2: Must be number" );
  38. }
  39. }
  40. lua_pop(L, 1);
  41. lua_getfield(L, 1, "A1");
  42. if (!lua_isnil(L, -1))
  43. {
  44. if( lua_isnumber(L, -1) )
  45. {
  46. temp_var = lua_tointeger(L, -1);
  47. if(temp_var < 2){
  48. temp_var = MCP4725_I2C_ADDR_A1_MASK & (temp_var << 1);
  49. addr_temp|=temp_var;
  50. }
  51. else
  52. return luaL_argerror( L, 1, "A1: Must be 0 or 1" );
  53. }
  54. else
  55. {
  56. return luaL_argerror( L, 1, "A1: Must be number" );
  57. }
  58. }
  59. lua_pop(L, 1);
  60. lua_getfield(L, 1, "A0");
  61. if (!lua_isnil(L, -1))
  62. {
  63. if( lua_isnumber(L, -1) )
  64. {
  65. temp_var = lua_tointeger(L, -1);
  66. if(temp_var<2){
  67. temp_var = MCP4725_I2C_ADDR_A0_MASK & (temp_var);
  68. addr_temp|=temp_var;
  69. }
  70. else
  71. return luaL_argerror( L, 1, "A0: Must be 0 or 1" );
  72. }
  73. else
  74. {
  75. return luaL_argerror( L, 1, "A0: Must be number" );
  76. }
  77. }
  78. lua_pop(L, 1);
  79. return addr_temp;
  80. }
  81. static int mcp4725_write(lua_State* L){
  82. uint8 i2c_address = MCP4725_I2C_ADDR_BASE;
  83. uint16 dac_value = 0;
  84. uint8 cmd_byte = 0;
  85. if(lua_istable(L, 1))
  86. {
  87. i2c_address = get_address(L, i2c_address);
  88. uint16 temp_var=0;
  89. lua_getfield(L, 1, "value");
  90. if (!lua_isnil(L, -1))
  91. {
  92. if( lua_isnumber(L, -1) )
  93. {
  94. temp_var = lua_tointeger(L, -1);
  95. if(temp_var >= 0 && temp_var<=4095){
  96. dac_value = temp_var<<4;
  97. }
  98. else
  99. return luaL_argerror( L, 1, "value: Valid range 0-4095" );
  100. }
  101. else
  102. {
  103. return luaL_argerror( L, 1, "value: Must be number" );
  104. }
  105. }
  106. else
  107. {
  108. return luaL_argerror( L, 1, "value: value is required" );
  109. }
  110. lua_pop(L, 1);
  111. lua_getfield(L, 1, "save");
  112. if (!lua_isnil(L, -1))
  113. {
  114. if( lua_isboolean(L, -1) )
  115. {
  116. if(lua_toboolean(L, -1)){
  117. cmd_byte |= MCP4725_COMMAND_WRITE_DAC_EEPROM;
  118. }
  119. else{
  120. cmd_byte |= MCP4725_COMMAND_WRITE_DAC;
  121. }
  122. }
  123. else
  124. {
  125. return luaL_argerror( L, 1, "save: must be boolean" );
  126. }
  127. }
  128. else
  129. {
  130. cmd_byte |= MCP4725_COMMAND_WRITE_DAC;
  131. }
  132. lua_pop(L, 1);
  133. lua_getfield(L, 1, "pwrdn");
  134. if (!lua_isnil(L, -1))
  135. {
  136. if( lua_isnumber(L, -1) )
  137. {
  138. temp_var = lua_tointeger(L, -1);
  139. if(temp_var >= 0 && temp_var <= 3){
  140. cmd_byte |= temp_var << 1;
  141. }
  142. else{
  143. return luaL_argerror( L, 1, "pwrdn: Valid range 0-3" );
  144. }
  145. }
  146. else
  147. {
  148. return luaL_argerror( L, 1, "pwrdn: Must be number" );
  149. }
  150. }
  151. lua_pop(L, 1);
  152. }
  153. uint8 *dac_value_byte = (uint8*) & dac_value;
  154. platform_i2c_send_start(mcp4725_i2c_id);
  155. platform_i2c_send_address(mcp4725_i2c_id, i2c_address, PLATFORM_I2C_DIRECTION_TRANSMITTER);
  156. platform_i2c_send_byte(mcp4725_i2c_id, cmd_byte);
  157. platform_i2c_send_byte(mcp4725_i2c_id, dac_value_byte[1]);
  158. platform_i2c_send_byte(mcp4725_i2c_id, dac_value_byte[0]);
  159. platform_i2c_send_stop(mcp4725_i2c_id);
  160. return 0;
  161. }
  162. static int mcp4725_read(lua_State* L){
  163. uint8 i2c_address = MCP4725_I2C_ADDR_BASE;
  164. uint8 recieve_buffer[5] = {0};
  165. if(lua_istable(L, 1))
  166. {
  167. i2c_address = get_address(L, i2c_address);
  168. }
  169. platform_i2c_send_start(mcp4725_i2c_id);
  170. platform_i2c_send_address(mcp4725_i2c_id, i2c_address, PLATFORM_I2C_DIRECTION_RECEIVER);
  171. for(int i=0;i<5;i++){
  172. recieve_buffer[i] = platform_i2c_recv_byte(mcp4725_i2c_id, 1);
  173. }
  174. platform_i2c_send_stop(mcp4725_i2c_id);
  175. lua_pushinteger(L, (recieve_buffer[0] & 0x06)>>1);
  176. lua_pushinteger(L, (recieve_buffer[1] << 4) | (recieve_buffer[2] >> 4));
  177. lua_pushinteger(L, (recieve_buffer[3] & 0x60) >> 5);
  178. lua_pushinteger(L, ((recieve_buffer[3] & 0xf) << 8) | recieve_buffer[4]);
  179. lua_pushinteger(L, (recieve_buffer[0] & 0x80) >> 7);
  180. lua_pushinteger(L, (recieve_buffer[0] & 0x40) >> 6);
  181. return 6;
  182. }
  183. LROT_BEGIN(mcp4725, NULL, 0)
  184. LROT_FUNCENTRY( write, mcp4725_write )
  185. LROT_FUNCENTRY( read, mcp4725_read )
  186. LROT_NUMENTRY( PWRDN_NONE, MCP4725_POWER_DOWN_NORMAL )
  187. LROT_NUMENTRY( PWRDN_1K, MCP4725_POWER_DOWN_RES_1K>>1 )
  188. LROT_NUMENTRY( PWRDN_100K, MCP4725_POWER_DOWN_RES_100K>>1 )
  189. LROT_NUMENTRY( PWRDN_500K, MCP4725_POWER_DOWN_RES_500K>>1 )
  190. LROT_END(mcp4725, NULL, 0)
  191. NODEMCU_MODULE(MCP4725, "mcp4725", mcp4725, NULL);