You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

пре 10 година
пре 9 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 9 година
пре 9 година
пре 9 година
пре 9 година
пре 9 година
пре 9 година
пре 10 година
пре 9 година
пре 9 година
пре 9 година
пре 9 година
пре 9 година
пре 9 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include <avr/pgmspace.h>
  4. #include "led.h"
  5. #include "softpwm_led.h"
  6. #include "debug.h"
  7. #define SOFTPWM_LED_FREQ 64
  8. #define SOFTPWM_LED_TIMER_TOP F_CPU / (256 * SOFTPWM_LED_FREQ)
  9. static uint8_t softpwm_led_state = 0;
  10. static uint8_t softpwm_led_ocr[LED_COUNT] = {0};
  11. static uint8_t softpwm_led_ocr_buff[LED_COUNT] = {0};
  12. #ifdef FADING_LED_ENABLE
  13. static void fading_led_proc(void);
  14. #else
  15. #define fading_led_proc()
  16. #endif
  17. #ifdef BREATHING_LED_ENABLE
  18. static void breathing_led_proc(void);
  19. #else
  20. #define fading_led_proc()
  21. #endif
  22. void softpwm_init(void)
  23. {
  24. #ifdef SOFTPWM_LED_TIMER3
  25. /* Timer3 setup */
  26. /* CTC mode */
  27. TCCR3B |= (1<<WGM32);
  28. /* Clock selelct: clk/8 */
  29. TCCR3B |= (1<<CS30);
  30. /* Set TOP value */
  31. uint8_t sreg = SREG;
  32. cli();
  33. OCR3AH = (SOFTPWM_LED_TIMER_TOP >> 8) & 0xff;
  34. OCR3AL = SOFTPWM_LED_TIMER_TOP & 0xff;
  35. SREG = sreg;
  36. #else
  37. /* Timer1 setup */
  38. /* CTC mode */
  39. TCCR1B |= (1<<WGM12);
  40. /* Clock selelct: clk/8 */
  41. TCCR1B |= (1<<CS10);
  42. /* Set TOP value */
  43. uint8_t sreg = SREG;
  44. cli();
  45. OCR1AH = (SOFTPWM_LED_TIMER_TOP >> 8) & 0xff;
  46. OCR1AL = SOFTPWM_LED_TIMER_TOP & 0xff;
  47. SREG = sreg;
  48. #endif
  49. softpwm_led_init();
  50. }
  51. void softpwm_led_enable(void)
  52. {
  53. /* Enable Compare Match Interrupt */
  54. #ifdef SOFTPWM_LED_TIMER3
  55. TIMSK3 |= (1<<OCIE3A);
  56. //dprintf("softpwm led on: %u\n", TIMSK3 & (1<<OCIE3A));
  57. #else
  58. TIMSK1 |= (1<<OCIE1A);
  59. //dprintf("softpwm led on: %u\n", TIMSK1 & (1<<OCIE1A));
  60. #endif
  61. softpwm_led_state = 1;
  62. #ifdef LEDMAP_ENABLE
  63. softpwm_led_state_change(softpwm_led_state);
  64. #endif
  65. }
  66. void softpwm_led_disable(void)
  67. {
  68. /* Disable Compare Match Interrupt */
  69. #ifdef SOFTPWM_LED_TIMER3
  70. TIMSK3 &= ~(1<<OCIE3A);
  71. //dprintf("softpwm led off: %u\n", TIMSK3 & (1<<OCIE3A));
  72. #else
  73. TIMSK1 &= ~(1<<OCIE1A);
  74. //dprintf("softpwm led off: %u\n", TIMSK1 & (1<<OCIE1A));
  75. #endif
  76. softpwm_led_state = 0;
  77. for (uint8_t i = 0; i < LED_COUNT; i++) {
  78. softpwm_led_off(i);
  79. }
  80. #ifdef LEDMAP_ENABLE
  81. softpwm_led_state_change(softpwm_led_state);
  82. #endif
  83. }
  84. void softpwm_led_toggle(void)
  85. {
  86. if (softpwm_led_state) {
  87. softpwm_led_disable();
  88. }
  89. else {
  90. softpwm_led_enable();
  91. }
  92. }
  93. void softpwm_led_set(uint8_t index, uint8_t val)
  94. {
  95. softpwm_led_ocr_buff[index] = val;
  96. }
  97. void softpwm_led_set_all(uint8_t val)
  98. {
  99. for (uint8_t i = 0; i < LED_COUNT; i++) {
  100. softpwm_led_ocr_buff[i] = val;
  101. }
  102. }
  103. void softpwm_led_increase(uint8_t index, uint8_t offset)
  104. {
  105. if (softpwm_led_ocr_buff[index] > 0xFF - offset) {
  106. softpwm_led_ocr_buff[index] = 0xFF;
  107. }
  108. else {
  109. softpwm_led_ocr_buff[index] += offset;
  110. }
  111. }
  112. void softpwm_led_increase_all(uint8_t offset)
  113. {
  114. for (uint8_t i = 0; i < LED_COUNT; i++) {
  115. softpwm_led_increase(i, offset);
  116. }
  117. }
  118. void softpwm_led_decrease(uint8_t index, uint8_t offset)
  119. {
  120. if (softpwm_led_ocr_buff[index] < offset) {
  121. softpwm_led_ocr_buff[index] = 0;
  122. }
  123. else {
  124. softpwm_led_ocr_buff[index] -= offset;
  125. }
  126. }
  127. void softpwm_led_decrease_all(uint8_t offset)
  128. {
  129. for (uint8_t i = 0; i < LED_COUNT; i++) {
  130. softpwm_led_decrease(i, offset);
  131. }
  132. }
  133. inline uint8_t softpwm_led_get_state(void)
  134. {
  135. return softpwm_led_state;
  136. }
  137. #ifdef FADING_LED_ENABLE
  138. static led_pack_t fading_led_state = 0;
  139. static led_pack_t fading_led_direction = 0;
  140. static uint8_t fading_led_duration = 0;
  141. static uint8_t fading_led_delay[LED_COUNT] = {0};
  142. void fading_led_enable(uint8_t index)
  143. {
  144. LED_BIT_SET(fading_led_state, index);
  145. }
  146. void fading_led_enable_all(void)
  147. {
  148. for (uint8_t i = 0; i < LED_COUNT; i++) {
  149. LED_BIT_SET(fading_led_state, i);
  150. }
  151. }
  152. void fading_led_disable(uint8_t index)
  153. {
  154. LED_BIT_CLEAR(fading_led_state, index);
  155. }
  156. void fading_led_disable_all(void)
  157. {
  158. fading_led_state = 0;
  159. }
  160. void fading_led_toggle(uint8_t index)
  161. {
  162. LED_BIT_XOR(fading_led_state, index);
  163. }
  164. void fading_led_toggle_all(void)
  165. {
  166. for (uint8_t i = 0; i < LED_COUNT; i++) {
  167. LED_BIT_XOR(fading_led_state, i);
  168. }
  169. }
  170. void fading_led_set_direction(uint8_t index, uint8_t dir)
  171. {
  172. if (dir) {
  173. LED_BIT_SET(fading_led_direction, index);
  174. }
  175. else {
  176. LED_BIT_CLEAR(fading_led_direction, index);
  177. }
  178. }
  179. void fading_led_set_direction_all(uint8_t dir)
  180. {
  181. for (uint8_t i = 0; i < LED_COUNT; i++) {
  182. fading_led_set_direction(i, dir);
  183. }
  184. }
  185. void fading_led_set_duration(uint8_t dur)
  186. {
  187. fading_led_duration = dur;
  188. }
  189. void fading_led_set_delay(uint8_t index, uint8_t delay)
  190. {
  191. fading_led_delay[index] = delay;
  192. }
  193. void fading_led_set_delay_all(uint8_t delay)
  194. {
  195. for (uint8_t i = 0; i < LED_COUNT; i++) {
  196. fading_led_delay[i] = delay;
  197. }
  198. }
  199. #endif
  200. #ifdef BREATHING_LED_ENABLE
  201. /* Breathing LED brighness(PWM On period) table
  202. *
  203. * http://www.wolframalpha.com/input/?i=Table%5Bfloor%28%28exp%28sin%28x%2F256*2*pi%2B3%2F2*pi%29%29-1%2Fe%29*%28256%2F%28e-1%2Fe%29%29%29%2C+%7Bx%2C0%2C255%2C1%7D%5D
  204. * Table[floor((exp(sin(x/256*2*pi+3/2*pi))-1/e)*(256/(e-1/e))), {x,0,255,1}]
  205. * (0..255).each {|x| print ((exp(sin(x/256.0*2*PI+3.0/2*PI))-1/E)*(256/(E-1/E))).to_i, ', ' }
  206. */
  207. static const uint8_t breathing_table[128] PROGMEM = {
  208. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 29, 30, 32, 34, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 56, 58, 61, 63, 66, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98, 102, 105, 108, 112, 116, 119, 123, 126, 130, 134, 138, 142, 145, 149, 153, 157, 161, 165, 169, 173, 176, 180, 184, 188, 192, 195, 199, 203, 206, 210, 213, 216, 219, 223, 226, 228, 231, 234, 236, 239, 241, 243, 245, 247, 248, 250, 251, 252, 253, 254, 255, 255, 255
  209. };
  210. static led_pack_t breathing_led_state = 0;
  211. static led_pack_t breathing_led_once = 0;
  212. static uint8_t breathing_led_duration = 0;
  213. static uint8_t breathing_led_index[LED_COUNT] = {0};
  214. static led_pack_t breathing_led_direction = 0;
  215. void breathing_led_enable(uint8_t index)
  216. {
  217. LED_BIT_SET(breathing_led_state, index);
  218. }
  219. void breathing_led_enable_once(uint8_t index)
  220. {
  221. LED_BIT_SET(breathing_led_state, index);
  222. LED_BIT_SET(breathing_led_once, index);
  223. }
  224. void breathing_led_enable_all(void)
  225. {
  226. for (uint8_t i = 0; i < LED_COUNT; i++) {
  227. LED_BIT_SET(breathing_led_state, i);
  228. }
  229. }
  230. void breathing_led_disable(uint8_t index)
  231. {
  232. LED_BIT_CLEAR(breathing_led_state, index);
  233. }
  234. void breathing_led_disable_all(void)
  235. {
  236. breathing_led_state = 0;
  237. }
  238. void breathing_led_toggle(uint8_t index)
  239. {
  240. LED_BIT_XOR(breathing_led_state, index);
  241. }
  242. void breathing_led_toggle_all(void)
  243. {
  244. for (uint8_t i = 0; i < LED_COUNT; i++) {
  245. LED_BIT_XOR(breathing_led_state, i);
  246. }
  247. }
  248. void breathing_led_set_duration(uint8_t dur)
  249. {
  250. breathing_led_duration = dur;
  251. }
  252. void breathing_led_set_index(uint8_t index, uint8_t value)
  253. {
  254. if (value & 0x80) {
  255. LED_BIT_SET(breathing_led_direction, index);
  256. }
  257. else {
  258. LED_BIT_CLEAR(breathing_led_direction, index);
  259. }
  260. breathing_led_index[index] = value & 0x7F;
  261. }
  262. void breathing_led_set_index_all(uint8_t value)
  263. {
  264. for (uint8_t i = 0; i < LED_COUNT; i++) {
  265. breathing_led_set_index(i, value);
  266. }
  267. }
  268. #endif
  269. #ifdef SOFTPWM_LED_TIMER3
  270. ISR(TIMER3_COMPA_vect)
  271. #else
  272. ISR(TIMER1_COMPA_vect)
  273. #endif
  274. {
  275. static uint8_t pwm = 0;
  276. pwm++;
  277. for (uint8_t i = 0; i < LED_COUNT; i++) {
  278. // LED on
  279. if (pwm == 0) {
  280. if (softpwm_led_ocr[i]) softpwm_led_on(i);
  281. softpwm_led_ocr[i] = softpwm_led_ocr_buff[i];
  282. }
  283. // LED off
  284. if (pwm == softpwm_led_ocr[i]) {
  285. softpwm_led_off(i);
  286. }
  287. }
  288. #if defined(FADING_LED_ENABLE) || defined(BREATHING_LED_ENABLE) || defined(CUSTOM_LED_ENABLE)
  289. static uint8_t counter = 0;
  290. if (++counter >= SOFTPWM_LED_FREQ) {
  291. counter = 0;
  292. #ifdef FADING_LED_ENABLE
  293. fading_led_proc();
  294. #endif
  295. #ifdef BREATHING_LED_ENABLE
  296. breathing_led_proc();
  297. #endif
  298. #if CUSTOM_LED_ENABLE
  299. softpwm_led_custom();
  300. #endif
  301. }
  302. #endif
  303. }
  304. #ifdef FADING_LED_ENABLE
  305. void fading_led_proc(void)
  306. {
  307. static uint8_t step = 0;
  308. if (fading_led_state) {
  309. if (++step > fading_led_duration) {
  310. step = 0;
  311. for (uint8_t i = 0; i < LED_COUNT; i++) {
  312. if (fading_led_state & LED_BIT(i)) {
  313. if (fading_led_delay[i]) {
  314. fading_led_delay[i]--;
  315. }
  316. else {
  317. if (fading_led_direction & LED_BIT(i)) {
  318. softpwm_led_decrease(i, 1);
  319. }
  320. else {
  321. softpwm_led_increase(i, 1);
  322. }
  323. }
  324. }
  325. }
  326. #ifdef CUSTOM_LED_ENABLE
  327. fading_led_custom(softpwm_led_ocr);
  328. #endif
  329. }
  330. }
  331. }
  332. #endif
  333. #ifdef BREATHING_LED_ENABLE
  334. void breathing_led_proc(void)
  335. {
  336. static uint8_t step = 0;
  337. if (breathing_led_state) {
  338. if (++step > breathing_led_duration) {
  339. step = 0;
  340. for (uint8_t i = 0; i < LED_COUNT; i++) {
  341. if (breathing_led_state & LED_BIT(i)) {
  342. softpwm_led_ocr_buff[i] = pgm_read_byte(&breathing_table[breathing_led_index[i]]);
  343. if (breathing_led_direction & LED_BIT(i)) {
  344. if (breathing_led_index[i] == 0) {
  345. LED_BIT_CLEAR(breathing_led_direction, i);
  346. if (breathing_led_once & LED_BIT(i)) {
  347. LED_BIT_CLEAR(breathing_led_state, i);
  348. LED_BIT_CLEAR(breathing_led_once, i);
  349. }
  350. }
  351. else {
  352. breathing_led_index[i]--;
  353. }
  354. }
  355. else {
  356. if (breathing_led_index[i] == 127) {
  357. LED_BIT_SET(breathing_led_direction, i);
  358. }
  359. else {
  360. breathing_led_index[i]++;
  361. }
  362. }
  363. }
  364. }
  365. #ifdef CUSTOM_LED_ENABLE
  366. breathing_led_custom(softpwm_led_ocr);
  367. #endif
  368. }
  369. }
  370. }
  371. #endif