Skip to content
This repository was archived by the owner on Aug 21, 2019. It is now read-only.

Commit aac2c03

Browse files
Arduino_uc32_Basic_Simulator_v0.1
added basic stuff. Created template from which i can start working more seriously. Tasks that i will ahve to do is: - figure out a plan to create a efficient and safe concurent program.
0 parents  commit aac2c03

4 files changed

Lines changed: 1087 additions & 0 deletions

File tree

README.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
In my school we are programming this semester in uC32 arduino, but i can't find that chipkit anywhere near me,
2+
also i couln't find any simulators online, so i decided to make my own simulator,
3+
and of course all in good old console! :D Still work in progres...
4+
5+
# Note that i probably won't be making full simulator, i will only be making the stuff i need for school.
6+
Which is basically only L01-L08, SW1-SW4, BTN1-BTN4.
7+
8+
Controls:
9+
- 1,2,3,4 - SW1, SW2, SW3, SW4 (on/off)
10+
- Q,W,E,R - BTN4, BTN3, BTN2, BTN1 (hold to on, release to off)
11+
- LEDs are ordered in descending order from left to right L08,L07,...,L01

das.h

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
#pragma once
2+
#include "olcConsoleGameEngine.h"
3+
4+
// Danilo's Arduino Simulation namespace
5+
6+
namespace das
7+
{
8+
void Swap(int &x, int &y) {
9+
x ^= y;
10+
y ^= x;
11+
x ^= y;
12+
}
13+
14+
/**
15+
Rounds 'value' to closed interval ['lowerBoundary', 'higherBoundary']
16+
*/
17+
void Clip(int &value, int lowerBoundary, int higherBoundary) {
18+
if (lowerBoundary > higherBoundary) {
19+
Swap(lowerBoundary, higherBoundary);
20+
}
21+
if (value < lowerBoundary) {
22+
value = lowerBoundary;
23+
}
24+
else if (value > higherBoundary) {
25+
value = higherBoundary;
26+
}
27+
}
28+
29+
const int RUN_SKETCH_ON_BOOT(0), ENTER_BOOTLOADER_ON_BOOT(1);
30+
31+
const int LOW(0);
32+
const int HIGH(5); // approx 5 volts
33+
34+
// Feel free to add more pins if you like, for my needs L01-L08, SW1-SW4 and BTN1-BTN4 are enough
35+
const int MAX_UC32_BASIC_IO_PIN(37);
36+
const int NUM_SW(4);
37+
const int NUM_LED(8);
38+
const int NUM_BTN(4);
39+
40+
enum PIN
41+
{
42+
L01 = 26, L02, L03, L04, L05, L06, L07, L08,
43+
SW1 = 2, SW2 = 7, SW3 = 8, SW4 = 35,
44+
BTN1 = 4, BTN2 = 34, BTN3 = 36, BTN4 = 37
45+
};
46+
47+
enum PIN_MODE {
48+
INPUT = 0, OUTPUT, INPUT_PULLUP
49+
};
50+
51+
/**
52+
Simulation of Arduino uC32 - Basic IO Shield, used for educational purposes.
53+
54+
@note1: This is an abstract class with abstract methods 'void setup()' and 'void loop()'
55+
you MUST implement these. Also you need to call method Start() which is protected
56+
and inherited from olcConsoleGameEngine.h to start the simulation.
57+
58+
@note2: New Console window is created in ArduinoSimulation_uC32 constructor
59+
with default parameters that can potentionally cause exception depending on your
60+
settings. To change these, class that ihnerits ArduinoSimulation_uC32 will have
61+
to call its constructor with different parameters.
62+
63+
@author Danilo Novakoviæ
64+
@version 0.1 4/25/2018
65+
*/
66+
class ArduinoSimulation_uC32 : protected olcConsoleGameEngine
67+
{
68+
protected:
69+
// You MUST implement these!!!
70+
virtual void setup() = 0;
71+
virtual void loop() = 0;
72+
private:
73+
struct sRectangleObject
74+
{
75+
short width, height;
76+
sRectangleObject(short width = 1, short height = 2) {
77+
set(width, height);
78+
}
79+
void set(short width, short height) {
80+
this->width = width;
81+
this->height = height;
82+
}
83+
};
84+
85+
// fields
86+
bool m_bPins[MAX_UC32_BASIC_IO_PIN + 1];
87+
PIN_MODE m_PinModes[MAX_UC32_BASIC_IO_PIN + 1];
88+
sRectangleObject m_swModel, m_btnModel, m_ledModel;
89+
private:
90+
/**
91+
@note: Set 'm_bLearningMode' to off if you don't wish to be thrown unecessary exceptions
92+
or/and possible warnings aimed to serve as reminder to not forget to, for example, set
93+
pinModes to on/off. (Even though simulation will work withouth doing it)
94+
*/
95+
bool m_bLearningMode;
96+
public:
97+
ArduinoSimulation_uC32(int width = 80, int height = 60, int fontw = 6, int fonth = 6) {
98+
m_sAppName = L"ArduinoSimulation_uC32 by Danilo Novakovic";
99+
try {
100+
ConstructConsole(width, height, fontw, fonth);
101+
}
102+
catch (...) {
103+
printf_s("\nError: Unable to construct console window with width=%d, height=%d, fotnw=%d, fonth=%d\n",
104+
width, height, fontw, fonth);
105+
exit(EXIT_FAILURE);
106+
}
107+
m_bLearningMode = true;
108+
}
109+
~ArduinoSimulation_uC32() {}
110+
111+
private:
112+
// Inherited via olcConsoleGameEngine
113+
virtual bool OnUserCreate() override
114+
{
115+
m_swModel.set(5, 15);
116+
m_btnModel.set(5, 5);
117+
m_ledModel.set(4, 8);
118+
119+
executeSoftReset(RUN_SKETCH_ON_BOOT);
120+
setup();
121+
return true;
122+
}
123+
virtual bool OnUserUpdate(float fElapsedTime) override
124+
{
125+
// HANDLE INPUT
126+
if (m_keys[VK_ESCAPE].bReleased == true) {
127+
return false;
128+
}
129+
130+
for (int i = 1; i <= NUM_SW; ++i) {
131+
// keyboard nums 1-4 are reserved for SW flips (on-off)
132+
if (m_keys[i + '0'].bReleased == true) {
133+
int index = swIndex(NUM_SW - i + 1);
134+
m_bPins[index] = !m_bPins[index];
135+
}
136+
}
137+
138+
for (int i = 0; i < NUM_BTN; ++i) {
139+
// keyboard chars Q,W,E,R are reserved for BTN flips (on-off)
140+
if (m_keys["QWER"[i]].bHeld || m_keys["qwer"[i]].bHeld) {
141+
m_bPins[btnIndex(NUM_BTN - i)] = true;
142+
}
143+
else {
144+
m_bPins[btnIndex(NUM_BTN - i)] = false;
145+
}
146+
}
147+
148+
// USER FUNCTION
149+
loop();
150+
151+
// UPDATE SCREEN
152+
DrawChipKIT();
153+
154+
return true;
155+
}
156+
157+
/**
158+
Helper function that allows me to iterate through sw pins in a loop
159+
by returning their actual value. (SW1 == swIndex(1))
160+
@example: swIndex(1) will return value 2 (check enum das::PIN)
161+
*/
162+
int swIndex(int i) {
163+
das::Clip(i, 1, NUM_SW);
164+
switch (i) {
165+
case 1:
166+
return (int)SW1;
167+
case 2:
168+
return (int)SW2;
169+
case 3:
170+
return (int)SW3;
171+
case 4:
172+
return (int)SW4;
173+
default:
174+
return -1; // not found
175+
}
176+
}
177+
/**
178+
Helper function that allows me to iterate through btn pins in a loop
179+
by returning their actual value. (BTN1 == btnIndex(1))
180+
@example: btnIndex(1) will return value 4 (check enum das::PIN)
181+
*/
182+
int btnIndex(int i) {
183+
das::Clip(i, 1, NUM_BTN);
184+
switch (i) {
185+
case 1:
186+
return (int)BTN1;
187+
case 2:
188+
return (int)BTN2;
189+
case 3:
190+
return (int)BTN3;
191+
case 4:
192+
return (int)BTN4;
193+
default:
194+
return -1; // not found
195+
}
196+
}
197+
198+
/**
199+
Updates simulated chipkit (pins) on the console screen.
200+
*/
201+
void DrawChipKIT()
202+
{
203+
// Draw SW's
204+
int y = 2, x = 1, i;
205+
static const int SPACE_BETWEEN_PINS(1);
206+
COLOUR colour;
207+
208+
for (i = 1, x = 1; x < ScreenWidth() && i <= NUM_SW; ++i)
209+
{
210+
colour = m_bPins[swIndex(i)] == true ? FG_GREEN : FG_RED;
211+
Fill(x, y, x + m_swModel.width, y + m_swModel.height, PIXEL_SOLID, colour);
212+
x += m_swModel.width + SPACE_BETWEEN_PINS;
213+
}
214+
y += m_swModel.height + SPACE_BETWEEN_PINS * 3;
215+
216+
// Draw BTNs
217+
for (i = 0, x = 1; x < ScreenWidth() && i < NUM_BTN; ++i)
218+
{
219+
PIXEL_TYPE type = m_bPins[btnIndex(NUM_BTN - i)] == true ? PIXEL_SOLID : PIXEL_QUARTER;
220+
Fill(x, y, x + m_btnModel.width, y + m_btnModel.height, type, FG_GREY);
221+
x += m_btnModel.width + SPACE_BETWEEN_PINS;
222+
}
223+
224+
// Draw LEDs
225+
for (i = 0, x += m_btnModel.width; x < ScreenWidth() && i < NUM_LED; ++i)
226+
{
227+
colour = m_bPins[(int)PIN::L08 - i] == true ? FG_GREEN : FG_RED;
228+
Fill(x, y, x + m_ledModel.width, y + m_ledModel.height, PIXEL_SOLID, colour);
229+
x += m_ledModel.width + SPACE_BETWEEN_PINS;
230+
}
231+
232+
}
233+
public:
234+
/**
235+
Resets arduino chipset with specific options
236+
@params supported : RUN_SKETCH_ON_BOOT - resets chipset
237+
note: ENTER_BOOTLOADER_ON_BOOT is not yet implemented
238+
*/
239+
void executeSoftReset(uint32_t options) {
240+
if (options == RUN_SKETCH_ON_BOOT) {
241+
for (int i = 0; i < MAX_UC32_BASIC_IO_PIN; ++i) {
242+
m_bPins[i] = false;
243+
}
244+
}
245+
else if (options == ENTER_BOOTLOADER_ON_BOOT) {
246+
// ...
247+
}
248+
}
249+
250+
/**
251+
Sets pin to certain mode (INPUT, OUTPUT, INPUT_PULLUP)
252+
@note: INPUT_PULLUP support is not yet implemented.
253+
It doesn't do anything in this current state of simulation class.
254+
*/
255+
void pinMode(PIN pin, PIN_MODE mode) {
256+
m_PinModes[(int)pin] = mode;
257+
}
258+
259+
/**
260+
Sets given 'pin' to 'value' (LOW, HIGH)
261+
@note: 'pin' given in params must be previously set to OUTPUT before
262+
calling this method. If it wasn't set on OUTPUT mode method will throw exception.
263+
(exception won't be thrown if m_bLearningMode is set to off)
264+
*/
265+
void digitalWrite(PIN pin, int value)
266+
{
267+
if (m_bLearningMode && m_PinModes[(int)pin] != PIN_MODE::OUTPUT)
268+
{
269+
exit(Error(L"error: you called digital write on pin that had no OUTPUT mode set!"));
270+
}
271+
m_bPins[(int)pin] = value > 0;
272+
}
273+
274+
/**
275+
Reads the state of pin. (ON/OFF)
276+
*/
277+
int digitalRead(PIN pin) {
278+
return m_bPins[(int)pin] == true ? LOW : HIGH;
279+
}
280+
void delay(unsigned int ms)
281+
{
282+
// I need to optimize this to work a bit better
283+
DrawChipKIT();
284+
thread t([this](){ this->UpdateScreen(); });
285+
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
286+
t.join();
287+
}
288+
289+
};
290+
291+
292+
293+
}

main.cpp

3.04 KB
Binary file not shown.

0 commit comments

Comments
 (0)