timer_a.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. MSP430 Emulator
  3. Copyright (C) 2020 Rudolf Geosits (rgeosits@live.esu.edu)
  4. "MSP430 Emulator" is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. "MSP430 Emulator" is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "timer_a.h"
  16. void handle_timer_a (Emulator *emu)
  17. {
  18. Cpu *cpu = emu->cpu;
  19. Timer_a *timer = cpu->timer_a;
  20. uint16_t TA0CTL = *timer->TA0CTL;
  21. // --------------------------------------------------------------
  22. // Handle Timer_A0 Control Register
  23. uint8_t TASSEL0 = (TA0CTL >> 8) & 0x03;
  24. uint8_t ID0 = (TA0CTL >> 6) & 0x03;
  25. uint8_t MC0 = (TA0CTL >> 4) & 0x03;
  26. uint8_t TA0CLR = (TA0CTL >> 2) & 0x01;
  27. uint8_t TA0IE = (TA0CTL >> 1) & 0x01;
  28. uint8_t TA0IFG = TA0CTL & 0x01;
  29. switch (TASSEL0) {
  30. case 0b00: {timer->source_0 = TACLK; break;}
  31. case 0b01: {timer->source_0 = ACLK; break;}
  32. case 0b10: {timer->source_0 = SMCLK; break;}
  33. case 0b11: {timer->source_0 = INCLK; break;}
  34. default: break;
  35. }
  36. switch (ID0) {
  37. case 0b00: {timer->idiv_0 = 1; break;}
  38. case 0b01: {timer->idiv_0 = 2; break;}
  39. case 0b10: {timer->idiv_0 = 4; break;}
  40. case 0b11: {timer->idiv_0 = 8; break;}
  41. default: break;
  42. }
  43. switch (MC0) {
  44. case 0b00: {timer->mode_0 = STOP_MODE; break;}
  45. case 0b01: {timer->mode_0 = UP_MODE; break;}
  46. case 0b10: {timer->mode_0 = CONTINOUS_MODE; break;}
  47. case 0b11: {timer->mode_0 = UP_DOWN_MODE; break;}
  48. default: break;
  49. }
  50. /* Timer_A clear; setting this bit resets TAR, the clock divider,
  51. and the count direction. The TACLR bit is automatically
  52. reset and is always read as zero. */
  53. if (TA0CLR) {
  54. *timer->TA0R = 0;
  55. *timer->TA0CTL &= 0xFF0B; // 0b00001011
  56. }
  57. // --------------------------------------------------------------
  58. // --------------------------------------------------------------
  59. // Handle Timer_A0 Capture/Compare Control Register
  60. uint16_t TA0CCTL1 = *timer->TA0CCTL1;
  61. uint8_t OUTMOD1 = (TA0CCTL1 >> 5) & 0x07;
  62. uint8_t CAP = (TA0CCTL1 >> 8) & 0x01;
  63. switch (OUTMOD1) {
  64. case 0b000: {break;}
  65. case 0b001: {break;}
  66. case 0b010: {break;}
  67. case 0b011: {break;}
  68. case 0b100: {break;}
  69. case 0b101: {break;}
  70. case 0b110: {break;}
  71. case 0b111: {break;}
  72. default: break;
  73. }
  74. // CAP field (Capture or compare mode?)
  75. timer->capture_mode_0 = CAP;
  76. timer->compare_mode_0 = !CAP;
  77. // --------------------------------------------------------------
  78. static double last_period = 0;
  79. static double last_pulse_width = 0;
  80. // Figure Out Frequency in up mode
  81. if (timer->compare_mode_0) {
  82. if (timer->mode_0 == UP_MODE) {
  83. uint16_t period_ct = *timer->TA0CCR0 + 1;
  84. uint64_t frequency = emu->cpu->bcm->mclk_freq;
  85. double period = (1.0/frequency) * period_ct;// In seconds
  86. double pulse_width = (1.0/frequency) * (*timer->TA0CCR1);
  87. double duty_cycle = pulse_width / period;
  88. /*
  89. printf("period: %lf\npulse_width: %lf\nduty: %lf%%\n",
  90. period, pulse_width, duty_cycle);
  91. */
  92. if (last_period != period || last_pulse_width != pulse_width) {
  93. if (period >= 0.015 && period <= 0.025) { // 0.020 is sweet spot 50 Hz
  94. //printf("period: %lf, last_period: %lf\n", period, last_period);
  95. //printf("pw: %lf, last_pw: %lf\n", pulse_width, last_pulse_width);
  96. if (pulse_width < 0.0009) {
  97. // Send Control for 0 degrees
  98. //print_console(emu, "0 degrres\n");
  99. uint8_t byte = 0;
  100. send_control(emu, SERVO_MOTOR, (void *)&byte, 1);
  101. }
  102. else if (pulse_width < 0.0012) {
  103. // Send Control for 30 Degrees
  104. //print_console(emu, "30 degrres\n");
  105. uint8_t byte = 30;
  106. send_control(emu, SERVO_MOTOR, (void *)&byte, 1);
  107. }
  108. else if (pulse_width < 0.0015) {
  109. // Send Control for 60 degrees
  110. uint8_t byte = 60;
  111. send_control(emu, SERVO_MOTOR, (void *)&byte, 1);
  112. }
  113. else if (pulse_width < 0.0018) {
  114. // Send Control for 90 degrees
  115. //print_console(emu, "90 degrres\n");
  116. uint8_t byte = 90;
  117. send_control(emu, SERVO_MOTOR, (void *)&byte, 1);
  118. }
  119. else if (pulse_width < 0.0021) {
  120. // Send Control for 120 degrees
  121. uint8_t byte = 120;
  122. send_control(emu, SERVO_MOTOR, (void *)&byte, 1);
  123. }
  124. else if (pulse_width >= 0.0021) {
  125. // Send Control for 150 degrees
  126. uint8_t byte = 150;
  127. send_control(emu, SERVO_MOTOR, (void *)&byte, 1);
  128. }
  129. }
  130. }
  131. if (OUTMOD1 == 0b111) { // RESET/SET
  132. uint16_t pulse_width = *timer->TA0CCR1;
  133. }
  134. last_period = period;
  135. last_pulse_width = pulse_width;
  136. }
  137. }
  138. if (!timer->timer_0_running && MC0 != 0) {
  139. //print_console(emu, "START TIMER\n");
  140. timer->timer_0_running = true;
  141. //pthread_t pp;
  142. //if(pthread_create(&pp, NULL, timer_A0_thread , (void*)emu)){
  143. //printf("ErrorcreatingDCOthread\n");
  144. //exit(1);
  145. //}
  146. }
  147. }
  148. void *timer_A0_thread (void *data)
  149. {
  150. Emulator *emu = (Emulator *) data;
  151. Timer_a *timer = emu->cpu->timer_a;
  152. uint64_t counter;
  153. bool high = false;
  154. while (true) {
  155. high = true;
  156. counter = 0;
  157. while (true) {
  158. if ( counter == (*timer->TA0CCR1) ) {
  159. high = false;
  160. }
  161. else if ( counter == (*timer->TA0CCR0 + 1) ) {
  162. break;
  163. }
  164. mclk_wait_cycles(emu, 1);
  165. counter++;
  166. high ? printf("-") : printf("_");
  167. fflush(stdout);
  168. }
  169. }
  170. return NULL;
  171. }
  172. void setup_timer_a (Emulator *emu)
  173. {
  174. Cpu *cpu = emu->cpu;
  175. Timer_a *timer = cpu->timer_a;
  176. // Configure Timer_A0 Registers
  177. const uint16_t TA0CTL_VLOC = 0x160;
  178. const uint16_t TA0R_VLOC = 0x170;
  179. const uint16_t TA0CCTL0_VLOC = 0x162;
  180. const uint16_t TA0CCR0_VLOC = 0x172;
  181. const uint16_t TA0CCTL1_VLOC = 0x164;
  182. const uint16_t TA0CCR1_VLOC = 0x174;
  183. const uint16_t TA0CCTL2_VLOC = 0x166;
  184. const uint16_t TA0CCR2_VLOC = 0x176;
  185. const uint16_t TA0IV_VLOC = 0x12E;
  186. *(timer->TA0CTL = (uint16_t *) get_addr_ptr(TA0CTL_VLOC)) = 0;
  187. *(timer->TA0R = (uint16_t *) get_addr_ptr(TA0R_VLOC)) = 0;
  188. *(timer->TA0CCTL0 = (uint16_t *) get_addr_ptr(TA0CCTL0_VLOC)) = 0;
  189. *(timer->TA0CCR0 = (uint16_t *) get_addr_ptr(TA0CCR0_VLOC)) = 0;
  190. *(timer->TA0CCTL1 = (uint16_t *) get_addr_ptr(TA0CCTL1_VLOC)) = 0;
  191. *(timer->TA0CCR1 = (uint16_t *) get_addr_ptr(TA0CCR1_VLOC)) = 0;
  192. *(timer->TA0CCTL2 = (uint16_t *) get_addr_ptr(TA0CCTL2_VLOC)) = 0;
  193. *(timer->TA0CCR2 = (uint16_t *) get_addr_ptr(TA0CCR2_VLOC)) = 0;
  194. *(timer->TA0IV = (uint16_t *) get_addr_ptr(TA0IV_VLOC)) = 0;
  195. // Configure Timer_A1 Registers
  196. const uint16_t TA1CTL_VLOC = 0x180;
  197. const uint16_t TA1R_VLOC = 0x190;
  198. const uint16_t TA1CCTL0_VLOC = 0x182;
  199. const uint16_t TA1CCR0_VLOC = 0x192;
  200. const uint16_t TA1CCTL1_VLOC = 0x184;
  201. const uint16_t TA1CCR1_VLOC = 0x194;
  202. const uint16_t TA1CCTL2_VLOC = 0x186;
  203. const uint16_t TA1CCR2_VLOC = 0x196;
  204. const uint16_t TA1IV_VLOC = 0x11E;
  205. *(timer->TA1CTL = (uint16_t *) get_addr_ptr(TA1CTL_VLOC)) = 0;
  206. *(timer->TA1R = (uint16_t *) get_addr_ptr(TA1R_VLOC)) = 0;
  207. *(timer->TA1CCTL0 = (uint16_t *) get_addr_ptr(TA1CCTL0_VLOC)) = 0;
  208. *(timer->TA1CCR0 = (uint16_t *) get_addr_ptr(TA1CCR0_VLOC)) = 0;
  209. *(timer->TA1CCTL1 = (uint16_t *) get_addr_ptr(TA1CCTL1_VLOC)) = 0;
  210. *(timer->TA1CCR1 = (uint16_t *) get_addr_ptr(TA1CCR1_VLOC)) = 0;
  211. *(timer->TA1CCTL2 = (uint16_t *) get_addr_ptr(TA1CCTL2_VLOC)) = 0;
  212. *(timer->TA1CCR2 = (uint16_t *) get_addr_ptr(TA1CCR2_VLOC)) = 0;
  213. *(timer->TA1IV = (uint16_t *) get_addr_ptr(TA1IV_VLOC)) = 0;
  214. // Configure other
  215. timer->source_0 = 0b10;
  216. timer->timer_0_running = false;
  217. timer->source_1 = 0b10;
  218. timer->timer_1_running = false;
  219. }
  220. /* POWER UP CLEAR (PUC)
  221. *
  222. * A PUC is always generated when a POR is generated, but a POR is not
  223. * generated by a PUC. The following events trigger a PUC:
  224. *
  225. * A POR signal
  226. * Watchdog timer expiration when in watchdog mode only
  227. * Watchdog timer security key violation
  228. * A Flash memory security key violation
  229. * A CPU instruct fetch from the peripheral address range 0h to 01FFh
  230. void power_up_clear () {
  231. *P1OUT = *P1DIR = *P1IFG = *P1IE = *P1SEL = *P1SEL2 = *P1REN = 0;
  232. }
  233. */