Repository navigation
Expand file tree
/
Copy pathSerialOut.cpp
More file actions
147 lines (121 loc) · 4.03 KB
/
Copy pathSerialOut.cpp
File metadata and controls
147 lines (121 loc) · 4.03 KB
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
/*==============================================================================
* SerialOut.cpp -- Serial output device proof of concept.
*============================================================================*/
// Note: Compile with MS VC
#include <stdio.h>
#include <stdarg.h>
#include <thread>
#include "SerialBuf.h"
// versioning
#define PROGRAM_NAME "SerialOut"
#define PROGRAM_VERSION "v0.1"
#define PROGRAM_INFO PROGRAM_NAME " " PROGRAM_VERSION
union uData {
bool b;
char c;
unsigned char uc;
short s;
unsigned short us;
int i;
unsigned int ui;
float f;
double d;
long long int i64;
unsigned long long int ui64;
char *str;
unsigned char *bytes;
};
// #undef pin names lest they collide with names in any header file(s) you might
// include.
#undef CLK
#undef CS
#undef DSO
#undef VCC
#undef TEST
// int DllMain() must exist and return 1 for a process to load the .DLL
// See https://docs.microsoft.com/en-us/windows/win32/dlls/dllmain for more
// information.
int __stdcall DllMain(void *module, unsigned int reason, void *reserved) {
return 1;
}
#define msleep(msecs) \
std::this_thread::sleep_for(std::chrono::milliseconds(msecs))
void msg(int lineNbr, const char *fmt, ...) {
msleep(30);
fflush(stdout);
fprintf(stdout, PROGRAM_INFO " (@%d) ", lineNbr);
va_list args = {0};
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
msleep(30);
}
#define HIGH true
#define LOW false
#define EDGE_FALLING false
#define EDGE_RISING true
struct InstData {
bool lastClk = LOW;
bool lastEn = HIGH;
bool lastDSO = LOW;
int testCtr = 0;
SerialOutBuffer8 sBuf;
};
unsigned int testData[] = {
0x88, 0x11, 0x55, 0xaa, 0xde, 0xad, 0xbe, 0xef, 0x00};
extern "C" __declspec(dllexport) void serialout(
InstData **opaque, double t, uData *data) {
double CLK = data[0].d; // input
double CS = data[1].d; // input
double VCC = data[2].d; // input
double TEST = data[3].d; // input
double &DSO = data[4].d; // output
InstData *inst = *opaque;
if (!*opaque) {
*opaque = inst = new InstData();
if (!inst) { // terminate with prejudice
msg(__LINE__, "Unable to allocate memory. Terminating simulation.\n");
std::terminate();
}
}
/*------------------------------------------------------------------------------
* Process:
* (1) Wait for CS to go low.
* (2) If already low and goes high, stop output.
* (3) Latch test voltage on first enable (this is our test data).
* (4) Write one bit on each falling clock edge.
* (5) When buffer is empty, output low.
*----------------------------------------------------------------------------*/
const bool enableState = LOW; // active low
const bool clockOutEdge = EDGE_FALLING; // clock data out on falling edge
double vRef = VCC / 2;
bool enState = (CS > vRef);
bool enabled = enState == enableState;
bool clkState = CLK > vRef;
DSO = inst->lastDSO * VCC;
if (!enabled) {
inst->lastEn = enabled;
inst->lastClk = clkState;
inst->lastDSO = LOW;
inst->sBuf.serialEnd(); // end if active
return;
}
if (enabled != inst->lastEn) {
inst->lastEn = enabled;
// latch test data -- we'll use the testData defined above
inst->sBuf.serialStart(testData[inst->testCtr]);
if (inst->testCtr < sizeof(testData) / sizeof(testData[0])) inst->testCtr++;
}
// clock data out on configured edge of clock
if (clkState == inst->lastClk) { return; }
inst->lastClk = clkState;
if (clkState != clockOutEdge) { return; }
// send the data
inst->lastDSO = inst->sBuf.serialOut();
DSO = inst->lastDSO * VCC;
}
extern "C" __declspec(dllexport) void Destroy(struct InstData *inst) {
// free(inst);
delete inst;
}