example92.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. //////////////////////////////////////////////////////////////////
  2. // example92.cpp
  3. //
  4. // Copyright (c) 2015 Robert Ramey
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. #include <iostream>
  10. // ***************************
  11. // 1. include headers to support safe integers
  12. #include <boost/safe_numerics/cpp.hpp>
  13. #include <boost/safe_numerics/exception.hpp>
  14. #include <boost/safe_numerics/safe_integer.hpp>
  15. // ***************************
  16. // 2. specify a promotion policy to support proper emulation of
  17. // PIC types on the desktop
  18. using pic16_promotion = boost::safe_numerics::cpp<
  19. 8, // char 8 bits
  20. 16, // short 16 bits
  21. 16, // int 16 bits
  22. 16, // long 16 bits
  23. 32 // long long 32 bits
  24. >;
  25. // 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
  26. #define C0 (50000 << 8)
  27. #define C_MIN (2500 << 8)
  28. static_assert(C0 < 0xffffff, "Largest step too long");
  29. static_assert(C_MIN > 0, "Smallest step must be greater than zero");
  30. static_assert(C_MIN < C0, "Smallest step must be smaller than largest step");
  31. // ***************************
  32. // 3. define PIC integer type names to be safe integer types of he same size.
  33. template <typename T> // T is char, int, etc data type
  34. using safe_t = boost::safe_numerics::safe<
  35. T,
  36. pic16_promotion
  37. >;
  38. // alias original program's integer types to corresponding PIC safe types
  39. // In conjunction with the promotion policy above, this will permit us to
  40. // guarantee that the resulting program will be free of arithmetic errors
  41. // introduced by C expression syntax and type promotion with no runtime penalty
  42. typedef safe_t<int8_t> int8;
  43. typedef safe_t<int16_t> int16;
  44. typedef safe_t<int32_t> int32;
  45. typedef safe_t<uint8_t> uint8;
  46. typedef safe_t<uint16_t> uint16;
  47. typedef safe_t<uint32_t> uint32;
  48. // ***************************
  49. // 4. emulate PIC features on the desktop
  50. // filter out special keyword used only by XC8 compiler
  51. #define __interrupt
  52. // filter out XC8 enable/disable global interrupts
  53. #define ei()
  54. #define di()
  55. // emulate PIC special registers
  56. uint8 RCON;
  57. uint8 INTCON;
  58. uint8 CCP1IE;
  59. uint8 CCP2IE;
  60. uint8 PORTC;
  61. uint8 TRISC;
  62. uint8 T3CON;
  63. uint8 T1CON;
  64. uint8 CCPR2H;
  65. uint8 CCPR2L;
  66. uint8 CCPR1H;
  67. uint8 CCPR1L;
  68. uint8 CCP1CON;
  69. uint8 CCP2CON;
  70. uint8 TMR1H;
  71. uint8 TMR1L;
  72. // create type used to map PIC bit names to
  73. // correct bit in PIC register
  74. template<typename T, std::int8_t N>
  75. struct bit {
  76. T & m_word;
  77. constexpr explicit bit(T & rhs) :
  78. m_word(rhs)
  79. {}
  80. constexpr bit & operator=(int b){
  81. if(b != 0)
  82. m_word |= (1 << N);
  83. else
  84. m_word &= ~(1 << N);
  85. return *this;
  86. }
  87. constexpr operator int () const {
  88. return m_word >> N & 1;
  89. }
  90. };
  91. // define bits for T1CON register
  92. struct {
  93. bit<uint8, 7> RD16{T1CON};
  94. bit<uint8, 5> T1CKPS1{T1CON};
  95. bit<uint8, 4> T1CKPS0{T1CON};
  96. bit<uint8, 3> T1OSCEN{T1CON};
  97. bit<uint8, 2> T1SYNC{T1CON};
  98. bit<uint8, 1> TMR1CS{T1CON};
  99. bit<uint8, 0> TMR1ON{T1CON};
  100. } T1CONbits;
  101. // define bits for T1CON register
  102. struct {
  103. bit<uint8, 7> GEI{INTCON};
  104. bit<uint8, 5> PEIE{INTCON};
  105. bit<uint8, 4> TMR0IE{INTCON};
  106. bit<uint8, 3> RBIE{INTCON};
  107. bit<uint8, 2> TMR0IF{INTCON};
  108. bit<uint8, 1> INT0IF{INTCON};
  109. bit<uint8, 0> RBIF{INTCON};
  110. } INTCONbits;
  111. // ***************************
  112. // 5. include the environment independent code we want to test
  113. #include "motor2.c"
  114. #include <chrono>
  115. #include <thread>
  116. // round 24.8 format to microseconds
  117. int32 to_microseconds(uint32 t){
  118. return (t + 128) / 256;
  119. }
  120. using result_t = uint8_t;
  121. const result_t success = 1;
  122. const result_t fail = 0;
  123. // move motor to the indicated target position in steps
  124. result_t test(int32 m){
  125. try {
  126. std::cout << "move motor to " << m << '\n';
  127. motor_run(m);
  128. std::cout
  129. << "step #" << ' '
  130. << "delay(us)(24.8)" << ' '
  131. << "delay(us)" << ' '
  132. << "CCPR" << ' '
  133. << "motor position" << '\n';
  134. do{
  135. std::this_thread::sleep_for(std::chrono::microseconds(to_microseconds(c)));
  136. uint32 last_c = c;
  137. uint32 last_ccpr = ccpr;
  138. isr_motor_step();
  139. std::cout
  140. << step_no << ' '
  141. << last_c << ' '
  142. << to_microseconds(last_c) << ' '
  143. << std::hex << last_ccpr << std::dec << ' '
  144. << motor_pos << '\n';
  145. }while(run_flg);
  146. }
  147. catch(const std::exception & e){
  148. std::cout << e.what() << '\n';
  149. return fail;
  150. }
  151. return success;
  152. }
  153. int main(){
  154. std::cout << "start test\n";
  155. result_t result = success;
  156. try{
  157. initialize();
  158. // move motor to position 1000
  159. result &= test(1000);
  160. // move motor to position 200
  161. result &= test(200);
  162. // move motor to position 200 again! Should result in no movement.
  163. result &= test(200);
  164. // move back to position 0
  165. result &= test(0);
  166. // ***************************
  167. // 6. error detected here! data types can't handle enough
  168. // steps to move the carriage from end to end! Suppress this
  169. // test for now.
  170. // move motor to position 50000.
  171. // result &= test(50000);
  172. // move motor back to position 0.
  173. result &= test(0);
  174. }
  175. catch(const std::exception & e){
  176. std::cout << e.what() << '\n';
  177. return 1;
  178. }
  179. catch(...){
  180. std::cout << "test interrupted\n";
  181. return EXIT_FAILURE;
  182. }
  183. std::cout << "end test\n";
  184. return result == success ? EXIT_SUCCESS : EXIT_FAILURE;
  185. }