home_easy.c 7.6 KB

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