File: example92.cpp

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (207 lines) | stat: -rw-r--r-- 5,697 bytes parent folder | download | duplicates (14)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
//////////////////////////////////////////////////////////////////
// example92.cpp
//
// Copyright (c) 2015 Robert Ramey
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#include <iostream>

// *************************** 
// 1. include headers to support safe integers
#include <boost/safe_numerics/cpp.hpp>
#include <boost/safe_numerics/exception.hpp>
#include <boost/safe_numerics/safe_integer.hpp>

// *************************** 
// 2. specify a promotion policy to support proper emulation of 
// PIC types on the desktop
using pic16_promotion = boost::safe_numerics::cpp<
    8,  // char      8 bits
    16, // short     16 bits
    16, // int       16 bits
    16, // long      16 bits
    32  // long long 32 bits
>;

// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
#define C0    (50000 << 8)
#define C_MIN  (2500 << 8)

static_assert(C0 < 0xffffff, "Largest step too long");
static_assert(C_MIN > 0, "Smallest step must be greater than zero");
static_assert(C_MIN < C0, "Smallest step must be smaller than largest step");

// *************************** 
// 3. define PIC integer type names to be safe integer types of he same size.

template <typename T> // T is char, int, etc data type
using safe_t = boost::safe_numerics::safe<
    T,
    pic16_promotion
>;

// alias original program's integer types to corresponding PIC safe types
// In conjunction with the promotion policy above, this will permit us to 
// guarantee that the resulting program will be free of arithmetic errors 
// introduced by C expression syntax and type promotion with no runtime penalty

typedef safe_t<int8_t> int8;
typedef safe_t<int16_t> int16;
typedef safe_t<int32_t> int32;
typedef safe_t<uint8_t> uint8;
typedef safe_t<uint16_t> uint16;
typedef safe_t<uint32_t> uint32;

// *************************** 
// 4. emulate PIC features on the desktop

// filter out special keyword used only by XC8 compiler
#define __interrupt
// filter out XC8 enable/disable global interrupts
#define ei()
#define di()

// emulate PIC special registers
uint8 RCON;
uint8 INTCON;
uint8 CCP1IE;
uint8 CCP2IE;
uint8 PORTC;
uint8 TRISC;
uint8 T3CON;
uint8 T1CON;

uint8 CCPR2H;
uint8 CCPR2L;
uint8 CCPR1H;
uint8 CCPR1L;
uint8 CCP1CON;
uint8 CCP2CON;
uint8 TMR1H;
uint8 TMR1L;

// create type used to map PIC bit names to
// correct bit in PIC register
template<typename T, std::int8_t N>
struct bit {
    T & m_word;
    constexpr explicit bit(T & rhs) :
        m_word(rhs)
    {}
    constexpr bit & operator=(int b){
        if(b != 0)
            m_word |= (1 << N);
        else
            m_word &= ~(1 << N);
        return *this;
    }
    constexpr operator int () const {
        return m_word >> N & 1;
    }
};

// define bits for T1CON register
struct  {
    bit<uint8, 7> RD16{T1CON};
    bit<uint8, 5> T1CKPS1{T1CON};
    bit<uint8, 4> T1CKPS0{T1CON};
    bit<uint8, 3> T1OSCEN{T1CON};
    bit<uint8, 2> T1SYNC{T1CON};
    bit<uint8, 1> TMR1CS{T1CON};
    bit<uint8, 0> TMR1ON{T1CON};
} T1CONbits;

// define bits for T1CON register
struct  {
    bit<uint8, 7> GEI{INTCON};
    bit<uint8, 5> PEIE{INTCON};
    bit<uint8, 4> TMR0IE{INTCON};
    bit<uint8, 3> RBIE{INTCON};
    bit<uint8, 2> TMR0IF{INTCON};
    bit<uint8, 1> INT0IF{INTCON};
    bit<uint8, 0> RBIF{INTCON};
} INTCONbits;

// ***************************
// 5. include the environment independent code we want to test
#include "motor2.c"

#include <chrono>
#include <thread>

// round 24.8 format to microseconds
int32 to_microseconds(uint32 t){
    return (t + 128) / 256;
}

using result_t = uint8_t;
const result_t success = 1;
const result_t fail = 0;

// move motor to the indicated target position in steps
result_t test(int32 m){
    try {
        std::cout << "move motor to " << m << '\n';
        motor_run(m);
        std::cout
        << "step #" << ' '
        << "delay(us)(24.8)" << ' '
        << "delay(us)" << ' '
        << "CCPR" << ' '
        << "motor position" << '\n';
        do{
            std::this_thread::sleep_for(std::chrono::microseconds(to_microseconds(c)));
            uint32 last_c = c;
            uint32 last_ccpr = ccpr;
            isr_motor_step();
            std::cout
            << step_no << ' '
            << last_c << ' '
            << to_microseconds(last_c) << ' '
            << std::hex << last_ccpr << std::dec << ' '
            << motor_pos << '\n';
        }while(run_flg);
    }
    catch(const std::exception & e){
        std::cout << e.what() << '\n';
        return fail;
    }
    return success;
}

int main(){
    std::cout << "start test\n";
    result_t result = success;
    try{
        initialize();
        // move motor to position 1000
        result &= test(1000);
        // move motor to position 200
        result &= test(200);
        // move motor to position 200 again! Should result in no movement.
        result &= test(200);
        // move back to position 0
        result &= test(0);
        // ***************************
        // 6. error detected here!  data types can't handle enough
        // steps to move the carriage from end to end! Suppress this
        // test for now.
        // move motor to position 50000.
//        result &= test(50000);
        // move motor back to position 0.
        result &= test(0);
    }
    catch(const std::exception & e){
        std::cout << e.what() << '\n';
        return 1;
    }
    catch(...){
        std::cout << "test interrupted\n";
        return EXIT_FAILURE;
    }
    std::cout << "end test\n";
    return result == success ? EXIT_SUCCESS : EXIT_FAILURE;
}