home_easy.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <malloc.h>
  4. #include <string.h>
  5. #ifdef __arm__
  6. #include <wiringPi.h>
  7. #else
  8. #define LOW 0
  9. #define HIGH 1
  10. #define INPUT 0
  11. #define OUTPUT 1
  12. int wiringPiSetup(void) {return 0;}
  13. void pinMode (int a, int b) {a=b;}
  14. void delayMicroseconds(unsigned int a) {a=a;}
  15. void digitalWrite(int a, int b) {a=b;}
  16. int digitalRead(int a) {return a;}
  17. #endif
  18. #include "home_easy.h"
  19. #include "buffer.h"
  20. #include "utils.h"
  21. unsigned int timings[5][2] = {
  22. //{310, 310}, // bit 0
  23. //{310, 1340}, // bit 1
  24. {275, 275}, // bit 0
  25. {275, 1300}, // bit 1
  26. {275, 9900}, // start of data
  27. {275, 2675}, // start of frame
  28. {275, 10000}, // end of data
  29. };
  30. unsigned char homeEasyPinOut = 0;
  31. unsigned char homeEasyPinIn = 2;
  32. /**
  33. * Encode bits with HomeEasy encoding (1 => 10, 0 => 01)
  34. *
  35. * @param frame 32-bit frame to encode
  36. *
  37. * @return new buffer
  38. * */
  39. BYTE_BUFFER homeEasyEncode(unsigned long int frame)
  40. {
  41. BYTE_BUFFER result = createByteBuffer();
  42. unsigned int i;
  43. for(i=0; i<4; i++) {
  44. pushWord(&result, encodeByte((frame >> ((3 - i) * 8)) & 0xff));
  45. }
  46. return result;
  47. }
  48. /**
  49. * Decode bits with HomeEasy encoding (1 => 10, 0 => 01)
  50. *
  51. * @param buffer the buffuer to decode
  52. *
  53. * @return new frame
  54. * */
  55. unsigned long int homeEasyDecode(BYTE_BUFFER *buffer)
  56. {
  57. unsigned long int result = 0;
  58. unsigned short int word;
  59. unsigned char *byte = (unsigned char*)&word;
  60. unsigned int i;
  61. for(i=0; i<(buffer->size+1)/2; i++) {
  62. byte[1] = buffer->data[2*i];
  63. byte[0] = (2*i+1 < buffer->size ? buffer->data[2*i+1]:0);
  64. result += (decodeByte(word)) << ((3 - i)* 8);
  65. }
  66. return result;
  67. }
  68. /**
  69. * Decode a byte according to HomeEasy
  70. *
  71. * @param byte the byte to decode
  72. *
  73. * @return the decoded byte
  74. */
  75. unsigned char decodeByte(unsigned short int word)
  76. {
  77. unsigned char decodedChar=0;
  78. int j;
  79. int shift = 7;
  80. for(j=0x8000;j>0; j>>=2) {
  81. decodedChar |= (((word & j) == j) ? 0x01 : 0x00) << shift;
  82. shift -=1;
  83. }
  84. return decodedChar;
  85. }
  86. /**
  87. * Encode a byte according to HomeEasy
  88. *
  89. * @param byte the byte to encode
  90. *
  91. * @return the encoded byte
  92. */
  93. unsigned short int encodeByte(unsigned char byte)
  94. {
  95. unsigned short int encodedChar=0;
  96. int j;
  97. int shift = 14;
  98. for(j=0x80;j>0; j>>=1) {
  99. encodedChar |= (((byte & j) == j) ? 0x02 : 0x01) << shift;
  100. shift -=2;
  101. }
  102. return encodedChar;
  103. }
  104. /**
  105. * Create a complete command according to Chacon protocole
  106. *
  107. * @param id command id (refer to your remote)
  108. * @param section button section ('A' | 'B' | 'C' | 'D' | 'G')
  109. * @param nb button number(1, 2, 3, 4)
  110. * @param on boolean for on/off
  111. *
  112. * @return HomeEasy frame
  113. */
  114. unsigned long int createHomeEasyCommand(unsigned long int id, char section, unsigned char nb, unsigned char on)
  115. {
  116. unsigned long int command = id << 6;
  117. char formatedSection = (section<='Z' ? section : section + 'A' - 'a');
  118. // adding global
  119. command |= (formatedSection == 'G' ? 0x20 : 0);
  120. // adding on/off
  121. command |= (on ? 0x10 : 0);
  122. // adding section
  123. command |= ((formatedSection == 'G' ? 0 : formatedSection - 'A') << 2) & 0x0c;
  124. // adding num
  125. command |= (formatedSection == 'G' ? 0 : nb-1) & 0x03;;
  126. return command;
  127. }
  128. /**
  129. * Send n times a data frame
  130. *
  131. * @param frame the data to send
  132. * @param repeat number of repeatition
  133. */
  134. void sendFrame(BYTE_BUFFER frame, unsigned int repeat)
  135. {
  136. unsigned int i;
  137. // switch to real time
  138. scheduler_realtime();
  139. // send header
  140. sendHomeEasyBit(START_OF_DATA);
  141. sendHomeEasyBit(START_OF_FRAME);
  142. // repeat the command
  143. for(i=0; i<repeat; i++) {
  144. sendHomeEasyBytes(frame);
  145. sendHomeEasyBit(END_OF_FRAME);
  146. }
  147. digitalWrite(homeEasyPinOut, LOW);
  148. // Exit real time mode
  149. scheduler_standard();
  150. }
  151. /**
  152. * Send a complete command according to Chacon protocole
  153. *
  154. * @param id command id (refer to your remote)
  155. * @param section button section ('A' | 'B' | 'C' | 'D' | 'G')
  156. * @param nb button number(1, 2, 3, 4)
  157. * @param on boolean for on/off
  158. * @param repeat number of repeatition
  159. */
  160. void sendHomeEasyCommand(unsigned long int id, char section, unsigned char nb, unsigned char on, unsigned char repeat)
  161. {
  162. unsigned long int command;
  163. BYTE_BUFFER encoded;
  164. // build the command
  165. command = createHomeEasyCommand(id, section, nb, on);
  166. // encode the command
  167. encoded = homeEasyEncode(command);
  168. // send data
  169. sendFrame(encoded, repeat);
  170. // release the memory
  171. destroyByteBuffer(encoded);
  172. }
  173. /**
  174. * retrieve the HomeEasy device ID from a frame
  175. *
  176. * @param buffer the buffer that hold the frame
  177. *
  178. * @return the device id
  179. */
  180. unsigned long int getHomeEasyId(unsigned long int frame)
  181. {
  182. return frame >> 6;
  183. }
  184. /**
  185. * Configure the GPIO output pin
  186. *
  187. * @param pinNumber wiringPi pin number
  188. */
  189. void setHomeEasyTransmittorPin(unsigned char pinNumber)
  190. {
  191. homeEasyPinOut = pinNumber;
  192. }
  193. /**
  194. * read the GPIO output pin
  195. *
  196. * @return wiringPi pin number
  197. */
  198. unsigned char getHomeEasyTransmittorPin()
  199. {
  200. return homeEasyPinOut;
  201. }
  202. /**
  203. * Configure the GPIO input pin
  204. *
  205. * @param pinNumber wiringPi pin number
  206. */
  207. void setHomeEasyReceptorPin(unsigned char pinNumber)
  208. {
  209. homeEasyPinIn = pinNumber;
  210. }
  211. /**
  212. * read the GPIO input pin
  213. *
  214. * @return wiringPi pin number
  215. */
  216. unsigned char getHomeEasyReceptorPin()
  217. {
  218. return homeEasyPinIn;
  219. }
  220. /**
  221. * Init input/output
  222. *
  223. * @return status
  224. */
  225. int initIO()
  226. {
  227. int status;
  228. status = wiringPiSetup();
  229. if (status != -1) {
  230. pinMode(homeEasyPinIn, INPUT);
  231. pinMode(homeEasyPinOut, OUTPUT);
  232. } else {
  233. printf("GPIO setup failed %d\n", status);
  234. }
  235. return status;
  236. }
  237. /**
  238. * Send a bit to the RF transmitter
  239. *
  240. * @param bit the bit to transmit (0 | 1 | TRIGGER0 | TRIGGER1 | END_OF_FRAME)
  241. */
  242. void sendHomeEasyBit(unsigned char bit)
  243. {
  244. digitalWrite(homeEasyPinOut, HIGH);
  245. delayMicroseconds(timings[bit][0]);
  246. digitalWrite(homeEasyPinOut, LOW);
  247. delayMicroseconds(timings[bit][1]);
  248. digitalWrite(homeEasyPinOut, HIGH);
  249. }
  250. /**
  251. * Send a byte to the RF transmitter
  252. *
  253. * @param byte the byte to transmit
  254. */
  255. void sendHomeEasyByte(unsigned char byte)
  256. {
  257. int i;
  258. for(i=0x80;i>0; i>>=1) {
  259. sendHomeEasyBit((byte & i) == i);
  260. }
  261. }
  262. /**
  263. * Send the content of a buffer to the RF transmitter
  264. *
  265. * @param buffer the buffer to transmit
  266. */
  267. void sendHomeEasyBytes(BYTE_BUFFER buffer)
  268. {
  269. unsigned int i;
  270. for(i=0; i<buffer.size; i++) {
  271. sendHomeEasyByte(buffer.data[i]);
  272. }
  273. }
  274. /**
  275. * Calculate the length of the frame
  276. *
  277. * @param data data to scan (each byte represent a bit)
  278. * @param high length of high level
  279. * @param low length of low level
  280. *
  281. * @return total length of the frame
  282. */
  283. unsigned int frameSize(unsigned char* data, unsigned int* high, unsigned int* low)
  284. {
  285. unsigned int i=0;
  286. if (high) *high = 0;
  287. if (data[i] == 1) {
  288. for(i=0; data[i]; i++) ;
  289. if (high) *high = i;
  290. }
  291. for(; !data[i]; i++) ;
  292. if (low) *low = i - *high;
  293. return i;
  294. }
  295. /**
  296. * Reading data from GPIO
  297. *
  298. * @param samples number of samples to read
  299. * @param duration waiting time between samples
  300. *
  301. * @return buffer
  302. */
  303. BYTE_BUFFER readData(unsigned long int samples, unsigned int duration)
  304. {
  305. struct timeval* start;
  306. BYTE_BUFFER result;
  307. unsigned long int i;
  308. result = createByteBuffer();
  309. result.size = samples;
  310. result.data = (char*) realloc(result.data, samples);
  311. scheduler_realtime();
  312. start = showTime(0);
  313. for(i=0; i<samples; i++) {
  314. result.data[i] = digitalRead(homeEasyPinIn);
  315. delayMicroseconds(duration);
  316. }
  317. showTime(start);
  318. scheduler_standard();
  319. return result;
  320. }