img-ir-nec.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * ImgTec IR Decoder setup for NEC protocol.
  3. *
  4. * Copyright 2010-2014 Imagination Technologies Ltd.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2 of the License, or (at your
  9. * option) any later version.
  10. */
  11. #include "img-ir-hw.h"
  12. #include <linux/bitrev.h>
  13. /* Convert NEC data to a scancode */
  14. static int img_ir_nec_scancode(int len, u64 raw, u64 enabled_protocols,
  15. struct img_ir_scancode_req *request)
  16. {
  17. unsigned int addr, addr_inv, data, data_inv;
  18. /* a repeat code has no data */
  19. if (!len)
  20. return IMG_IR_REPEATCODE;
  21. if (len != 32)
  22. return -EINVAL;
  23. /* raw encoding: ddDDaaAA */
  24. addr = (raw >> 0) & 0xff;
  25. addr_inv = (raw >> 8) & 0xff;
  26. data = (raw >> 16) & 0xff;
  27. data_inv = (raw >> 24) & 0xff;
  28. if ((data_inv ^ data) != 0xff) {
  29. /* 32-bit NEC (used by Apple and TiVo remotes) */
  30. /* scan encoding: as transmitted, MSBit = first received bit */
  31. request->scancode = bitrev8(addr) << 24 |
  32. bitrev8(addr_inv) << 16 |
  33. bitrev8(data) << 8 |
  34. bitrev8(data_inv);
  35. } else if ((addr_inv ^ addr) != 0xff) {
  36. /* Extended NEC */
  37. /* scan encoding: AAaaDD */
  38. request->scancode = addr << 16 |
  39. addr_inv << 8 |
  40. data;
  41. } else {
  42. /* Normal NEC */
  43. /* scan encoding: AADD */
  44. request->scancode = addr << 8 |
  45. data;
  46. }
  47. request->protocol = RC_TYPE_NEC;
  48. return IMG_IR_SCANCODE;
  49. }
  50. /* Convert NEC scancode to NEC data filter */
  51. static int img_ir_nec_filter(const struct rc_scancode_filter *in,
  52. struct img_ir_filter *out, u64 protocols)
  53. {
  54. unsigned int addr, addr_inv, data, data_inv;
  55. unsigned int addr_m, addr_inv_m, data_m, data_inv_m;
  56. data = in->data & 0xff;
  57. data_m = in->mask & 0xff;
  58. if ((in->data | in->mask) & 0xff000000) {
  59. /* 32-bit NEC (used by Apple and TiVo remotes) */
  60. /* scan encoding: as transmitted, MSBit = first received bit */
  61. addr = bitrev8(in->data >> 24);
  62. addr_m = bitrev8(in->mask >> 24);
  63. addr_inv = bitrev8(in->data >> 16);
  64. addr_inv_m = bitrev8(in->mask >> 16);
  65. data = bitrev8(in->data >> 8);
  66. data_m = bitrev8(in->mask >> 8);
  67. data_inv = bitrev8(in->data >> 0);
  68. data_inv_m = bitrev8(in->mask >> 0);
  69. } else if ((in->data | in->mask) & 0x00ff0000) {
  70. /* Extended NEC */
  71. /* scan encoding AAaaDD */
  72. addr = (in->data >> 16) & 0xff;
  73. addr_m = (in->mask >> 16) & 0xff;
  74. addr_inv = (in->data >> 8) & 0xff;
  75. addr_inv_m = (in->mask >> 8) & 0xff;
  76. data_inv = data ^ 0xff;
  77. data_inv_m = data_m;
  78. } else {
  79. /* Normal NEC */
  80. /* scan encoding: AADD */
  81. addr = (in->data >> 8) & 0xff;
  82. addr_m = (in->mask >> 8) & 0xff;
  83. addr_inv = addr ^ 0xff;
  84. addr_inv_m = addr_m;
  85. data_inv = data ^ 0xff;
  86. data_inv_m = data_m;
  87. }
  88. /* raw encoding: ddDDaaAA */
  89. out->data = data_inv << 24 |
  90. data << 16 |
  91. addr_inv << 8 |
  92. addr;
  93. out->mask = data_inv_m << 24 |
  94. data_m << 16 |
  95. addr_inv_m << 8 |
  96. addr_m;
  97. return 0;
  98. }
  99. /*
  100. * NEC decoder
  101. * See also http://www.sbprojects.com/knowledge/ir/nec.php
  102. * http://wiki.altium.com/display/ADOH/NEC+Infrared+Transmission+Protocol
  103. */
  104. struct img_ir_decoder img_ir_nec = {
  105. .type = RC_BIT_NEC,
  106. .control = {
  107. .decoden = 1,
  108. .code_type = IMG_IR_CODETYPE_PULSEDIST,
  109. },
  110. /* main timings */
  111. .unit = 562500, /* 562.5 us */
  112. .timings = {
  113. /* leader symbol */
  114. .ldr = {
  115. .pulse = { 16 /* 9ms */ },
  116. .space = { 8 /* 4.5ms */ },
  117. },
  118. /* 0 symbol */
  119. .s00 = {
  120. .pulse = { 1 /* 562.5 us */ },
  121. .space = { 1 /* 562.5 us */ },
  122. },
  123. /* 1 symbol */
  124. .s01 = {
  125. .pulse = { 1 /* 562.5 us */ },
  126. .space = { 3 /* 1687.5 us */ },
  127. },
  128. /* free time */
  129. .ft = {
  130. .minlen = 32,
  131. .maxlen = 32,
  132. .ft_min = 10, /* 5.625 ms */
  133. },
  134. },
  135. /* repeat codes */
  136. .repeat = 108, /* 108 ms */
  137. .rtimings = {
  138. /* leader symbol */
  139. .ldr = {
  140. .space = { 4 /* 2.25 ms */ },
  141. },
  142. /* free time */
  143. .ft = {
  144. .minlen = 0, /* repeat code has no data */
  145. .maxlen = 0,
  146. },
  147. },
  148. /* scancode logic */
  149. .scancode = img_ir_nec_scancode,
  150. .filter = img_ir_nec_filter,
  151. };