]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/safe_numerics/example/example93.cpp
bump version to 15.2.11-pve1
[ceph.git] / ceph / src / boost / libs / safe_numerics / example / example93.cpp
CommitLineData
92f5a8d4
TL
1//////////////////////////////////////////////////////////////////
2// example93.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
10#include <iostream>
11
12// include headers to support safe integers
13#include <boost/safe_numerics/cpp.hpp>
14#include <boost/safe_numerics/exception.hpp>
15#include <boost/safe_numerics/safe_integer.hpp>
16#include <boost/safe_numerics/safe_integer_range.hpp>
17#include <boost/safe_numerics/safe_integer_literal.hpp>
18
19// use same type promotion as used by the pic compiler
20// target compiler XC8 supports:
21using pic16_promotion = boost::safe_numerics::cpp<
22 8, // char 8 bits
23 16, // short 16 bits
24 16, // int 16 bits
25 16, // long 16 bits
26 32 // long long 32 bits
27>;
28
29// ***************************
30// 1. Specify exception policies so we will generate a
31// compile time error whenever an operation MIGHT fail.
32
33// ***************************
34// generate runtime errors if operation could fail
35using exception_policy = boost::safe_numerics::default_exception_policy;
36
37// generate compile time errors if operation could fail
38using trap_policy = boost::safe_numerics::loose_trap_policy;
39
40// ***************************
41// 2. Create a macro named literal an integral value
42// that can be evaluated at compile time.
43#define literal(n) make_safe_literal(n, pic16_promotion, void)
44
45// For min speed of 2 mm / sec (24.8 format)
46// sec / step = sec / 2 mm * 2 mm / rotation * rotation / 200 steps
47#define C0 literal(5000 << 8)
48
49// For max speed of 400 mm / sec
50// sec / step = sec / 400 mm * 2 mm / rotation * rotation / 200 steps
51#define C_MIN literal(25 << 8)
52
53static_assert(
54 C0 < make_safe_literal(0xffffff, pic16_promotion,trap_policy),
55 "Largest step too long"
56);
57static_assert(
58 C_MIN > make_safe_literal(0, pic16_promotion,trap_policy),
59 "Smallest step must be greater than zero"
60);
61
62// ***************************
63// 3. Create special ranged types for the motor program
64// These wiil guarantee that values are in the expected
65// ranges and permit compile time determination of when
66// exceptional conditions might occur.
67
68using pic_register_t = boost::safe_numerics::safe<
69 uint8_t,
70 pic16_promotion,
71 trap_policy // use for compiling and running tests
72>;
73
74// note: the maximum value of step_t would be:
75// 50000 = 500 mm / 2 mm/rotation * 200 steps/rotation.
76// But in one expression the value of number of steps * 4 is
77// used. To prevent introduction of error, permit this
78// type to hold the larger value.
79using step_t = boost::safe_numerics::safe_unsigned_range<
80 0,
81 200000,
82 pic16_promotion,
83 exception_policy
84>;
85
86// position
87using position_t = boost::safe_numerics::safe_unsigned_range<
88 0,
89 50000, // 500 mm / 2 mm/rotation * 200 steps/rotation
90 pic16_promotion,
91 exception_policy
92>;
93
94// next end of step timer value in format 24.8
95// where the .8 is the number of bits in the fractional part.
96using ccpr_t = boost::safe_numerics::safe<
97 uint32_t,
98 pic16_promotion,
99 exception_policy
100>;
101
102// pulse length in format 24.8
103// note: this value is constrainted to be a positive value. But
104// we still need to make it a signed type. We get an arithmetic
105// error when moving to a negative step number.
106using c_t = boost::safe_numerics::safe_unsigned_range<
107 C_MIN,
108 C0,
109 pic16_promotion,
110 exception_policy
111>;
112
113// index into phase table
114// note: The legal values are 0-3. So why must this be a signed
115// type? Turns out that expressions like phase_ix + d
116// will convert both operands to unsigned. This in turn will
117// create an exception. So leave it signed even though the
118// value is greater than zero.
119using phase_ix_t = boost::safe_numerics::safe_signed_range<
120 0,
121 3,
122 pic16_promotion,
123 trap_policy
124>;
125
126// settings for control value output
127using phase_t = boost::safe_numerics::safe<
128 uint16_t,
129 pic16_promotion,
130 trap_policy
131>;
132
133// direction of rotation
134using direction_t = boost::safe_numerics::safe_signed_range<
135 -1,
136 +1,
137 pic16_promotion,
138 trap_policy
139>;
140
141// some number of microseconds
142using microseconds = boost::safe_numerics::safe<
143 uint32_t,
144 pic16_promotion,
145 trap_policy
146>;
147
148// ***************************
149// emulate PIC features on the desktop
150
151// filter out special keyword used only by XC8 compiler
152#define __interrupt
153// filter out XC8 enable/disable global interrupts
154#define ei()
155#define di()
156
157// emulate PIC special registers
158pic_register_t RCON;
159pic_register_t INTCON;
160pic_register_t CCP1IE;
161pic_register_t CCP2IE;
162pic_register_t PORTC;
163pic_register_t TRISC;
164pic_register_t T3CON;
165pic_register_t T1CON;
166
167pic_register_t CCPR2H;
168pic_register_t CCPR2L;
169pic_register_t CCPR1H;
170pic_register_t CCPR1L;
171pic_register_t CCP1CON;
172pic_register_t CCP2CON;
173pic_register_t TMR1H;
174pic_register_t TMR1L;
175
176// ***************************
177// special checked type for bits - values restricted to 0 or 1
178using safe_bit_t = boost::safe_numerics::safe_unsigned_range<
179 0,
180 1,
181 pic16_promotion,
182 trap_policy
183>;
184
185// create type used to map PIC bit names to
186// correct bit in PIC register
187template<typename T, std::int8_t N>
188struct bit {
189 T & m_word;
190 constexpr explicit bit(T & rhs) :
191 m_word(rhs)
192 {}
193 // special functions for assignment of literal
194 constexpr bit & operator=(decltype(literal(1))){
195 m_word |= literal(1 << N);
196 return *this;
197 }
198 constexpr bit & operator=(decltype(literal(0))){
199 m_word &= ~literal(1 << N);
200 return *this;
201 }
202 // operator to convert to 0 or 1
203 constexpr operator safe_bit_t () const {
204 return m_word >> literal(N) & literal(1);
205 }
206};
207
208// define bits for T1CON register
209struct {
210 bit<pic_register_t, 7> RD16{T1CON};
211 bit<pic_register_t, 5> T1CKPS1{T1CON};
212 bit<pic_register_t, 4> T1CKPS0{T1CON};
213 bit<pic_register_t, 3> T1OSCEN{T1CON};
214 bit<pic_register_t, 2> T1SYNC{T1CON};
215 bit<pic_register_t, 1> TMR1CS{T1CON};
216 bit<pic_register_t, 0> TMR1ON{T1CON};
217} T1CONbits;
218
219// define bits for T1CON register
220struct {
221 bit<pic_register_t, 7> GEI{INTCON};
222 bit<pic_register_t, 5> PEIE{INTCON};
223 bit<pic_register_t, 4> TMR0IE{INTCON};
224 bit<pic_register_t, 3> RBIE{INTCON};
225 bit<pic_register_t, 2> TMR0IF{INTCON};
226 bit<pic_register_t, 1> INT0IF{INTCON};
227 bit<pic_register_t, 0> RBIF{INTCON};
228} INTCONbits;
229
230#include "motor3.c"
231
232#include <chrono>
233#include <thread>
234
235// round 24.8 format to microseconds
236microseconds to_microseconds(ccpr_t t){
237 return (t + literal(128)) / literal(256);
238}
239
240using result_t = uint8_t;
241const result_t success = 1;
242const result_t fail = 0;
243
244// move motor to the indicated target position in steps
245result_t test(position_t new_position){
246 try {
247 std::cout << "move motor to " << new_position << '\n';
248 motor_run(new_position);
249 std::cout
250 << "step #" << ' '
251 << "delay(us)(24.8)" << ' '
252 << "delay(us)" << ' '
253 << "CCPR" << ' '
254 << "motor position" << '\n';
255 while(busy()){
256 std::this_thread::sleep_for(std::chrono::microseconds(to_microseconds(c)));
257 c_t last_c = c;
258 ccpr_t last_ccpr = ccpr;
259 isr_motor_step();
260 std::cout << i << ' '
261 << last_c << ' '
262 << to_microseconds(last_c) << ' '
263 << std::hex << last_ccpr << std::dec << ' '
264 << motor_position << '\n';
265 };
266 }
267 catch(const std::exception & e){
268 std::cout << e.what() << '\n';
269 return fail;
270 }
271 return success;
272}
273
274int main(){
275 std::cout << "start test\n";
276 result_t result = success;
277 try {
278 initialize();
279 // move motor to position 1000
280 result &= test(literal(1000));
281 // move to the left before zero position
282 // fails to compile !
283 // result &= ! test(-10);
284 // move motor to position 200
285 result &= test(literal(200));
286 // move motor to position 200 again! Should result in no movement.
287 result &= test(literal(200));
288 // move motor to position 50000.
289 result &= test(literal(50000));
290 // move motor back to position 0.
291 result &= test(literal(0));
292 }
293 catch(...){
294 std::cout << "test interrupted\n";
295 return EXIT_FAILURE;
296 }
297 std::cout << "end test\n";
298 return result == success ? EXIT_SUCCESS : EXIT_FAILURE;
299}