bmp085.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "module.h"
  2. #include "lauxlib.h"
  3. #include "platform.h"
  4. #include "c_stdlib.h"
  5. #include "c_string.h"
  6. static const uint32_t bmp085_i2c_id = 0;
  7. static const uint8_t bmp085_i2c_addr = 0x77;
  8. static struct {
  9. int16_t AC1;
  10. int16_t AC2;
  11. int16_t AC3;
  12. uint16_t AC4;
  13. uint16_t AC5;
  14. uint16_t AC6;
  15. int16_t B1;
  16. int16_t B2;
  17. int16_t MB;
  18. int16_t MC;
  19. int16_t MD;
  20. } bmp085_data;
  21. static uint8_t r8u(uint32_t id, uint8_t reg) {
  22. uint8_t ret;
  23. platform_i2c_send_start(id);
  24. platform_i2c_send_address(id, bmp085_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
  25. platform_i2c_send_byte(id, reg);
  26. platform_i2c_send_stop(id);
  27. platform_i2c_send_start(id);
  28. platform_i2c_send_address(id, bmp085_i2c_addr, PLATFORM_I2C_DIRECTION_RECEIVER);
  29. ret = platform_i2c_recv_byte(id, 0);
  30. platform_i2c_send_stop(id);
  31. return ret;
  32. }
  33. static uint16_t r16u(uint32_t id, uint8_t reg) {
  34. uint8_t high = r8u(id, reg);
  35. uint8_t low = r8u(id, reg + 1);
  36. return (high << 8) | low;
  37. }
  38. static int16_t r16(uint32_t id, uint8_t reg) {
  39. return (int16_t) r16u(id, reg);
  40. }
  41. static int bmp085_setup(lua_State* L) {
  42. (void)L;
  43. bmp085_data.AC1 = r16(bmp085_i2c_id, 0xAA);
  44. bmp085_data.AC2 = r16(bmp085_i2c_id, 0xAC);
  45. bmp085_data.AC3 = r16(bmp085_i2c_id, 0xAE);
  46. bmp085_data.AC4 = r16u(bmp085_i2c_id, 0xB0);
  47. bmp085_data.AC5 = r16u(bmp085_i2c_id, 0xB2);
  48. bmp085_data.AC6 = r16u(bmp085_i2c_id, 0xB4);
  49. bmp085_data.B1 = r16(bmp085_i2c_id, 0xB6);
  50. bmp085_data.B2 = r16(bmp085_i2c_id, 0xB8);
  51. bmp085_data.MB = r16(bmp085_i2c_id, 0xBA);
  52. bmp085_data.MC = r16(bmp085_i2c_id, 0xBC);
  53. bmp085_data.MD = r16(bmp085_i2c_id, 0xBE);
  54. return 0;
  55. }
  56. static int bmp085_init(lua_State* L) {
  57. uint32_t sda;
  58. uint32_t scl;
  59. platform_print_deprecation_note("bmp085.init() is replaced by bmp085.setup()", "in the next version");
  60. if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) {
  61. return luaL_error(L, "wrong arg range");
  62. }
  63. sda = luaL_checkinteger(L, 1);
  64. scl = luaL_checkinteger(L, 2);
  65. if (scl == 0 || sda == 0) {
  66. return luaL_error(L, "no i2c for D0");
  67. }
  68. platform_i2c_setup(bmp085_i2c_id, sda, scl, PLATFORM_I2C_SPEED_SLOW);
  69. return bmp085_setup(L);
  70. }
  71. static uint32_t bmp085_temperature_raw_b5(void) {
  72. int16_t t, X1, X2;
  73. platform_i2c_send_start(bmp085_i2c_id);
  74. platform_i2c_send_address(bmp085_i2c_id, bmp085_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
  75. platform_i2c_send_byte(bmp085_i2c_id, 0xF4);
  76. platform_i2c_send_byte(bmp085_i2c_id, 0x2E);
  77. platform_i2c_send_stop(bmp085_i2c_id);
  78. // Wait for device to complete sampling
  79. os_delay_us(4500);
  80. t = r16(bmp085_i2c_id, 0xF6);
  81. X1 = ((t - bmp085_data.AC6) * bmp085_data.AC5) >> 15;
  82. X2 = (bmp085_data.MC << 11)/ (X1 + bmp085_data.MD);
  83. return X1 + X2;
  84. }
  85. static int16_t bmp085_temperature(void) {
  86. return (bmp085_temperature_raw_b5() + 8) >> 4;
  87. }
  88. static int bmp085_lua_temperature(lua_State* L) {
  89. lua_pushinteger(L, bmp085_temperature());
  90. return 1;
  91. }
  92. static int32_t bmp085_pressure_raw(int oss) {
  93. int32_t p;
  94. int32_t p1, p2, p3;
  95. platform_i2c_send_start(bmp085_i2c_id);
  96. platform_i2c_send_address(bmp085_i2c_id, bmp085_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
  97. platform_i2c_send_byte(bmp085_i2c_id, 0xF4);
  98. platform_i2c_send_byte(bmp085_i2c_id, 0x34 + 64 * oss);
  99. platform_i2c_send_stop(bmp085_i2c_id);
  100. // Wait for device to complete sampling
  101. switch (oss) {
  102. case 0: os_delay_us( 4500); break;
  103. case 1: os_delay_us( 7500); break;
  104. case 2: os_delay_us(13500); break;
  105. case 3: os_delay_us(25500); break;
  106. }
  107. p1 = r8u(bmp085_i2c_id, 0xF6);
  108. p2 = r8u(bmp085_i2c_id, 0xF7);
  109. p3 = r8u(bmp085_i2c_id, 0xF8);
  110. p = (p1 << 16) | (p2 << 8) | p3;
  111. p = p >> (8 - oss);
  112. return p;
  113. }
  114. static int bmp085_lua_pressure_raw(lua_State* L) {
  115. uint8_t oss = 0;
  116. int32_t p;
  117. if (lua_isnumber(L, 1)) {
  118. oss = luaL_checkinteger(L, 1);
  119. if (oss > 3) {
  120. oss = 3;
  121. }
  122. }
  123. p = bmp085_pressure_raw(oss);
  124. lua_pushinteger(L, p);
  125. return 1;
  126. }
  127. static int bmp085_lua_pressure(lua_State* L) {
  128. uint8_t oss = 0;
  129. int32_t p;
  130. int32_t X1, X2, X3, B3, B4, B5, B6, B7;
  131. if (lua_isnumber(L, 1)) {
  132. oss = luaL_checkinteger(L, 1);
  133. if (oss > 3) {
  134. oss = 3;
  135. }
  136. }
  137. p = bmp085_pressure_raw(oss);
  138. B5 = bmp085_temperature_raw_b5();
  139. B6 = B5 - 4000;
  140. X1 = ((int32_t)bmp085_data.B2 * ((B6 * B6) >> 12)) >> 11;
  141. X2 = ((int32_t)bmp085_data.AC2 * B6) >> 11;
  142. X3 = X1 + X2;
  143. B3 = ((((int32_t)bmp085_data.AC1 << 2) + X3) * (1 << oss) + 2) >> 2;
  144. X1 = ((int32_t)bmp085_data.AC3 * B6) >> 13;
  145. X2 = ((int32_t)bmp085_data.B1 * ((B6 * B6) >> 12)) >> 16;
  146. X3 = (X1 + X2 + 2) >> 2;
  147. B4 = ((int32_t)bmp085_data.AC4 * (X3 + 32768)) >> 15;
  148. B7 = (p - B3) * (50000 / (1 << oss));
  149. p = (B7 / B4) << 1;
  150. X1 = (p >> 8) * (p >> 8);
  151. X1 = (X1 * 3038) >> 16;
  152. X2 = (-7357 * p) >> 16;
  153. p = p + ((X1 + X2 + 3791) >> 4);
  154. lua_pushinteger(L, p);
  155. return 1;
  156. }
  157. static const LUA_REG_TYPE bmp085_map[] = {
  158. { LSTRKEY( "temperature" ), LFUNCVAL( bmp085_lua_temperature )},
  159. { LSTRKEY( "pressure" ), LFUNCVAL( bmp085_lua_pressure )},
  160. { LSTRKEY( "pressure_raw" ), LFUNCVAL( bmp085_lua_pressure_raw )},
  161. { LSTRKEY( "setup" ), LFUNCVAL( bmp085_setup )},
  162. // init() is deprecated
  163. { LSTRKEY( "init" ), LFUNCVAL( bmp085_init )},
  164. { LNILKEY, LNILVAL}
  165. };
  166. NODEMCU_MODULE(BMP085, "bmp085", bmp085_map, NULL);