PICSimLab - Programmable IC Simulator Laboratory 0.9.2
PICSimLab - API
Loading...
Searching...
No Matches

Introduction

This is the documentation to explain the use of picsimlab internal classes.

The main objective of this domentation is to enable the expansion of the simulator with the creation of new boards (board) and parts (part).

Part example

output_step.h

/* ########################################################################
PICSimLab - Programmable IC Simulator Laboratory
########################################################################
Copyright (c) : 2010-2024 Luis Claudio Gambôa Lopes <lcgamboa@yahoo.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
For e-mail suggestions : lcgamboa@yahoo.com
######################################################################## */
#ifndef PART_STEP_H
#define PART_STEP_H
#include "../lib/part.h"
#define PART_STEP_Name "Step Motor"
class cpart_step : public part {
public:
std::string GetAboutInfo(void) override { return "L.C. Gamboa \n <lcgamboa@yahoo.com>"; };
cpart_step(const unsigned x, const unsigned y, const char* name, const char* type, board* pboard_, const int id_);
~cpart_step(void);
void DrawOutput(const unsigned int index) override;
void PreProcess(void) override;
void Process(void) override;
void PostProcess(void) override;
void ConfigurePropertiesWindow(void) override;
void ReadPropertiesWindow(void) override;
std::string WritePreferences(void) override;
void ReadPreferences(std::string value) override;
unsigned short GetInputId(char* name) override;
unsigned short GetOutputId(char* name) override;
private:
void RegisterRemoteControl(void) override;
unsigned char input_pins[4];
unsigned char output_pins[1];
float steps;
float angle;
int input[2];
int turns;
};
#endif /* PART_STEP */
Board class.
Definition board.h:111
step motor part class
Definition output_step.h:38
std::string GetAboutInfo(void) override
Return the about information of part.
Definition output_step.h:40
void PreProcess(void) override
Called every start of CPU process.
Definition output_step.cc:148
std::string WritePreferences(void) override
Called to save part preferences in configuration file.
Definition output_step.cc:388
unsigned char input_pins[4]
pulse input pind
Definition output_step.h:67
void ReadPropertiesWindow(void) override
Called when properties window close.
Definition output_step.cc:414
void DrawOutput(const unsigned int index) override
Called to draw every output.
Definition output_step.cc:71
unsigned short GetInputId(char *name) override
return the input ids numbers of names used in input map
Definition output_step.cc:355
void ConfigurePropertiesWindow(void) override
Called to configure the properties window.
Definition output_step.cc:406
void Process(void) override
Called every CPU step.
Definition output_step.cc:171
unsigned char output_pins[1]
pulse output pin
Definition output_step.h:68
void RegisterRemoteControl(void) override
Register remote control variables.
Definition output_step.cc:402
~cpart_step(void)
destructor called once on part destruction
Definition output_step.cc:65
unsigned short GetOutputId(char *name) override
return the output ids numbers of names used in output map
Definition output_step.cc:360
void ReadPreferences(std::string value) override
Called whe configuration file load preferences.
Definition output_step.cc:397
void PostProcess(void) override
Called every end of CPU process.
Definition output_step.cc:338
PART class.
Definition part.h:49

output_step.cc

/* ########################################################################
PICSimLab - Programmable IC Simulator Laboratory
########################################################################
Copyright (c) : 2010-2024 Luis Claudio Gambôa Lopes <lcgamboa@yahoo.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
For e-mail suggestions : lcgamboa@yahoo.com
######################################################################## */
#define _USE_MATH_DEFINES
#include "output_step.h"
#include "../lib/oscilloscope.h"
#include "../lib/picsimlab.h"
#include "../lib/spareparts.h"
#include "math.h"
/* outputs */
enum { O_P1, O_P2, O_P3, O_P4, O_P5, O_L1, O_L2, O_L3, O_L4, O_ROT, O_STEPS };
static PCWProp pcwprop[6] = {{PCW_COMBO, "Pin 1"}, {PCW_COMBO, "Pin 2"}, {PCW_COMBO, "Pin 3"},
{PCW_COMBO, "Pin 4"}, {PCW_COMBO, "Home"}, {PCW_END, ""}};
cpart_step::cpart_step(const unsigned x, const unsigned y, const char* name, const char* type, board* pboard_,
const int id_)
: part(x, y, name, type, pboard_, id_) {
angle = 0;
steps = 0;
input_pins[0] = 0;
input_pins[1] = 0;
input_pins[2] = 0;
input_pins[3] = 0;
output_pins[0] = 0;
input[0] = 0;
input[1] = 0;
turns = 0;
SetPCWProperties(pcwprop);
PinCount = 4;
Pins = input_pins;
}
SpareParts.SetPartOnDraw(id);
SpareParts.CanvasCmd({CC_FREEBITMAP, .FreeBitmap{BitmapId}});
SpareParts.CanvasCmd({CC_DESTROY});
}
void cpart_step::DrawOutput(const unsigned int i) {
float x2, y2;
const picpin* ppins = SpareParts.GetPinsValues();
switch (output[i].id) {
case O_P1:
case O_P2:
case O_P3:
case O_P4:
SpareParts.CanvasCmd({CC_SETCOLOR, .SetColor{49, 61, 99}});
SpareParts.CanvasCmd({CC_RECTANGLE, .Rectangle{1, output[i].x1, output[i].y1, output[i].x2 - output[i].x1,
output[i].y2 - output[i].y1}});
SpareParts.CanvasCmd({CC_SETFGCOLOR, .SetFgColor{255, 255, 255}});
if (input_pins[output[i].id - O_P1] == 0)
SpareParts.CanvasCmd({CC_ROTATEDTEXT, .RotatedText{"NC", output[i].x1, output[i].y1, 0}});
else
SpareParts.CanvasCmd(
{CC_ROTATEDTEXT, .RotatedText{SpareParts.GetPinName(input_pins[output[i].id - O_P1]).c_str(),
output[i].x1, output[i].y1, 0}});
break;
case O_P5:
SpareParts.CanvasCmd({CC_SETCOLOR, .SetColor{49, 61, 99}});
SpareParts.CanvasCmd({CC_RECTANGLE, .Rectangle{1, output[i].x1, output[i].y1, output[i].x2 - output[i].x1,
output[i].y2 - output[i].y1}});
SpareParts.CanvasCmd({CC_SETFGCOLOR, .SetFgColor{255, 255, 255}});
if (output_pins[output[i].id - O_P5] == 0)
SpareParts.CanvasCmd({CC_ROTATEDTEXT, .RotatedText{"NC", output[i].x1, output[i].y1, 0}});
else
SpareParts.CanvasCmd(
{CC_ROTATEDTEXT, .RotatedText{SpareParts.GetPinName(output_pins[output[i].id - O_P5]).c_str(),
output[i].x1, output[i].y1, 0}});
break;
case O_STEPS: {
SpareParts.CanvasCmd({CC_SETCOLOR, .SetColor{49, 61, 99}});
SpareParts.CanvasCmd({CC_RECTANGLE, .Rectangle{1, output[i].x1, output[i].y1, output[i].x2 - output[i].x1,
output[i].y2 - output[i].y1}});
SpareParts.CanvasCmd({CC_SETFGCOLOR, .SetFgColor{255, 255, 255}});
char text[100];
snprintf(text, 100, "S=%5.1f", steps);
SpareParts.CanvasCmd({CC_ROTATEDTEXT, .RotatedText{text, output[i].x1, output[i].y1, 0}});
snprintf(text, 100, "T=%3i", turns);
SpareParts.CanvasCmd({CC_ROTATEDTEXT, .RotatedText{text, output[i].x1, output[i].y1 + 12, 0}});
} break;
case O_ROT:
SpareParts.CanvasCmd({CC_SETCOLOR, .SetColor{77, 77, 77}});
SpareParts.CanvasCmd({CC_CIRCLE, .Circle{1, output[i].x1, output[i].y1, output[i].r + 10}});
SpareParts.CanvasCmd({CC_SETFGCOLOR, .SetFgColor{0, 0, 0}});
SpareParts.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{250, 250, 250}});
SpareParts.CanvasCmd({CC_CIRCLE, .Circle{1, output[i].x1, output[i].y1, output[i].r}});
SpareParts.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{55, 55, 55}});
SpareParts.CanvasCmd({CC_CIRCLE, .Circle{1, output[i].x1, output[i].y1, output[i].r / 3}});
SpareParts.CanvasCmd({CC_SETLINEWIDTH, .SetLineWidth{8}});
x2 = output[i].x1 + (output[i].r - 2) * sin(angle);
y2 = output[i].y1 + (output[i].r - 2) * cos(angle);
SpareParts.CanvasCmd({CC_LINE, .Line{output[i].x1, output[i].y1, x2, y2}});
SpareParts.CanvasCmd({CC_SETLINEWIDTH, .SetLineWidth{6}});
SpareParts.CanvasCmd({CC_SETFGCOLOR, .SetFgColor{77, 77, 77}});
SpareParts.CanvasCmd({CC_LINE, .Line{output[i].x1, output[i].y1, x2, y2}});
SpareParts.CanvasCmd({CC_SETLINEWIDTH, .SetLineWidth{1}});
break;
case O_L1:
case O_L2:
case O_L3:
case O_L4:
SpareParts.CanvasCmd({CC_SETFGCOLOR, .SetFgColor{0, 0, 0}});
if (input_pins[output[i].id - O_L1] > 0) {
SpareParts.CanvasCmd(
{CC_SETBGCOLOR,
.SetBgColor{(unsigned int)ppins[input_pins[output[i].id - O_L1] - 1].oavalue, 0, 0}});
} else {
SpareParts.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{55, 0, 0}});
}
DrawLED(SpareParts.CanvasCmd, &output[i]);
break;
}
}
if (output_pins[0] > 0) {
if ((steps == 0) && (turns == 0)) {
SpareParts.SetPin(output_pins[0], 0);
} else {
SpareParts.SetPin(output_pins[0], 1);
}
}
}
#define STEP (1.8 * M_PI / 180.0)
#define HSTEP (STEP / 2.0)
#define NSTEP 200 // 360/1.8
#define S1 1
#define S12 3
#define S2 2
#define S23 6
#define S3 4
#define S34 12
#define S4 8
#define S41 9
void cpart_step::Process(void) {
const picpin* ppins = SpareParts.GetPinsValues();
if ((input_pins[0] > 0) && (input_pins[1] > 0) && (input_pins[2] > 0) && (input_pins[3] > 0)) {
input[1] = input[0];
input[0] = (ppins[input_pins[0] - 1].value << 3) | (ppins[input_pins[1] - 1].value << 2) |
(ppins[input_pins[2] - 1].value << 1) | ppins[input_pins[3] - 1].value;
if (input[0] ^ input[1]) {
switch (input[0]) {
case S1:
switch (input[1]) {
case S4: // foward full step
steps += 1;
break;
case S2: // backward full step
steps -= 1;
break;
case S41: // foward half step
steps += 0.5;
break;
case S12: // backward half step
steps -= 0.5;
break;
}
break;
case S2:
switch (input[1]) {
case S1: // foward full step
steps += 1;
break;
case S3: // backward full step
steps -= 1;
break;
case S12: // foward half step
steps += 0.5;
break;
case S23: // backward half step
steps -= 0.5;
break;
}
break;
case S3:
switch (input[1]) {
case S2: // foward full step
steps += 1;
break;
case S4: // backward full step
steps -= 1;
break;
case S23: // foward half step
steps += 0.5;
break;
case S34: // backward half step
steps -= 0.5;
break;
}
break;
case S4:
switch (input[1]) {
case S3: // foward full step
steps += 1;
break;
case S1: // backward full step
steps -= 1;
break;
case S34: // foward half step
steps += 0.5;
break;
case S41: // backward half step
steps -= 0.5;
break;
}
break;
case S12:
switch (input[1]) {
case S41: // foward full step double phase
steps += 1;
break;
case S23: // backward full step double phase
steps -= 1;
break;
case S1: // foward half step
steps += 0.5;
break;
case S2: // backward half step
steps -= 0.5;
break;
}
break;
case S23:
switch (input[1]) {
case S12: // foward full step double phase
steps += 1;
break;
case S34: // backward full step double phase
steps -= 1;
break;
case S2: // foward half step
steps += 0.5;
break;
case S3: // backward half step
steps -= 0.5;
break;
}
break;
case S34:
switch (input[1]) {
case S23: // foward full step double phase
steps += 1;
break;
case S41: // backward full step double phase
steps -= 1;
break;
case S3: // foward half step
steps += 0.5;
break;
case S4: // backward half step
steps -= 0.5;
break;
}
break;
case S41:
switch (input[1]) {
case S34: // foward full step double phase
steps += 1;
break;
case S12: // backward full step double phase
steps -= 1;
break;
case S4: // foward half step
steps += 0.5;
break;
case S1: // backward half step
steps -= 0.5;
break;
}
break;
default: // invalid
input[0] = input[1];
return;
break;
}
if (steps >= NSTEP) {
steps -= NSTEP;
turns++;
}
if (steps < 0) {
steps += NSTEP;
turns--;
}
angle = STEP * steps;
if (output_pins[0] > 0) {
if ((steps == 0) && (turns == 0)) {
SpareParts.SetPin(output_pins[0], 0);
} else {
SpareParts.SetPin(output_pins[0], 1);
}
}
}
}
}
const picpin* ppins = SpareParts.GetPinsValues();
for (int i = 0; i < 4; i++) {
if (input_pins[i] && (output_ids[O_L1 + i]->value != ppins[input_pins[i] - 1].oavalue)) {
output_ids[O_L1 + i]->value = ppins[input_pins[i] - 1].oavalue;
output_ids[O_L1 + i]->update = 1;
}
}
if (output_ids[O_ROT]->value_f != angle) {
output_ids[O_ROT]->value_f = angle;
output_ids[O_ROT]->update = 1;
output_ids[O_STEPS]->update = 1;
}
}
unsigned short cpart_step::GetInputId(char* name) {
printf("Error input '%s' don't have a valid id! \n", name);
return INVALID_ID;
}
unsigned short cpart_step::GetOutputId(char* name) {
if (strcmp(name, "PN_1") == 0)
return O_P1;
if (strcmp(name, "PN_2") == 0)
return O_P2;
if (strcmp(name, "PN_3") == 0)
return O_P3;
if (strcmp(name, "PN_4") == 0)
return O_P4;
if (strcmp(name, "PN_5") == 0)
return O_P5;
if (strcmp(name, "LD_1") == 0)
return O_L1;
if (strcmp(name, "LD_2") == 0)
return O_L2;
if (strcmp(name, "LD_3") == 0)
return O_L3;
if (strcmp(name, "LD_4") == 0)
return O_L4;
if (strcmp(name, "DG_ROT") == 0)
return O_ROT;
if (strcmp(name, "DI_STEPS") == 0)
return O_STEPS;
printf("Error output '%s' don't have a valid id! \n", name);
return INVALID_ID;
}
std::string cpart_step::WritePreferences(void) {
char prefs[256];
sprintf(prefs, "%hhu,%hhu,%hhu,%hhu,%hhu", input_pins[0], input_pins[1], input_pins[2], input_pins[3],
return prefs;
}
void cpart_step::ReadPreferences(std::string value) {
sscanf(value.c_str(), "%hhu,%hhu,%hhu,%hhu,%hhu", &input_pins[0], &input_pins[1], &input_pins[2], &input_pins[3],
}
output_ids[O_ROT]->status = (void*)&angle;
}
SetPCWComboWithPinNames("combo1", input_pins[0]);
SetPCWComboWithPinNames("combo2", input_pins[1]);
SetPCWComboWithPinNames("combo3", input_pins[2]);
SetPCWComboWithPinNames("combo4", input_pins[3]);
SetPCWComboWithPinNames("combo5", output_pins[0]);
}
input_pins[0] = GetPWCComboSelectedPin("combo1");
input_pins[1] = GetPWCComboSelectedPin("combo2");
input_pins[2] = GetPWCComboSelectedPin("combo3");
input_pins[3] = GetPWCComboSelectedPin("combo4");
output_pins[0] = GetPWCComboSelectedPin("combo5");
}
part_init(PART_STEP_Name, cpart_step, "Output");
std::string GetPinName(unsigned char pin)
Return the name of one pin.
Definition spareparts.cc:145
cpart_step(const unsigned x, const unsigned y, const char *name, const char *type, board *pboard_, const int id_)
constructor called once on part creation
Definition output_step.cc:40
output_t output[MAX_IDS]
output map elements
Definition part.h:373
output_t * output_ids[MAX_IDS]
output map elements by id order
Definition part.h:374
int BitmapId
Internal Bitmap.
Definition part.h:381
Definition part.h:39
float r
radius
Definition board.h:75
float x2
x2 position
Definition board.h:70
unsigned char value
updated value
Definition board.h:81
float y2
y2 position
Definition board.h:72
float y1
y1 position
Definition board.h:71
void * status
rcontrol status
Definition board.h:78
float x1
x1 position
Definition board.h:69
float value_f
updated value float
Definition board.h:83
unsigned char update
need draw update
Definition board.h:79

Board example

board_x.h

/* ########################################################################
PICSimLab - Programmable IC Simulator Laboratory
########################################################################
Copyright (c) : 2015-2024 Luis Claudio Gambôa Lopes <lcgamboa@yahoo.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
For e-mail suggestions : lcgamboa@yahoo.com
######################################################################## */
#ifndef BOARD_x_H
#define BOARD_x_H
#include "../devices/swbounce.h"
#include "bsim_picsim.h"
#define BOARD_x_Name "X"
// new board class must be derived from board class defined in board.h
class cboard_x : public bsim_picsim {
private:
unsigned char p_BT1; // first board push button in RD0
unsigned char p_BT2; // second board switch in RD1
// value of potentiometer
unsigned char pot1;
// flag to control if potentiometer is active
unsigned char active;
// Register controls for remote interface called once on board creation
void RegisterRemoteControl(void) override;
SWBounce_t bounce;
public:
// Constructor called once on board creation
cboard_x(void);
// Destructor called once on board destruction
~cboard_x(void);
// Return the board name
std::string GetName(void) override { return BOARD_x_Name; };
// Return the about info of board
std::string GetAboutInfo(void) override { return "L.C. Gamboa \n <lcgamboa@yahoo.com>"; };
// Called ever 100ms to draw board
void Draw(void) override;
void Run_CPU(void) override;
// Return a list of board supported microcontrollers
std::string GetSupportedDevices(void) override { return "PIC16F877A,PIC18F4550,PIC18F4620,"; };
// Reset board status
void Reset(void) override;
// Event on the board
void EvMouseButtonPress(unsigned int button, unsigned int x, unsigned int y, unsigned int state) override;
// Event on the board
void EvMouseButtonRelease(unsigned int button, unsigned int x, unsigned int y, unsigned int state) override;
// Event on the board
void EvMouseMove(unsigned int button, unsigned int x, unsigned int y, unsigned int state) override;
// Event on the board
void EvKeyPress(unsigned int key, unsigned int mask) override;
// Event on the board
void EvKeyRelease(unsigned int key, unsigned int mask) override;
// Called ever 1s to refresh status
void RefreshStatus(void) override;
// Called to save board preferences in configuration file
void WritePreferences(void) override;
// Called whe configuration file load preferences
void ReadPreferences(char* name, char* value) override;
// return the input ids numbers of names used in input map
unsigned short GetInputId(char* name) override;
// return the output ids numbers of names used in output map
unsigned short GetOutputId(char* name) override;
};
#endif /* BOARD_x_H */
Definition bsim_picsim.h:34
Definition board_x.h:35
void RefreshStatus(void) override
Called ever 1s to refresh status.
Definition board_x.cc:183
std::string GetSupportedDevices(void) override
Return a list of supported microcontrollers.
Definition board_x.h:63
void EvMouseButtonPress(unsigned int button, unsigned int x, unsigned int y, unsigned int state) override
Event on the board.
Definition board_x.cc:263
std::string GetName(void) override
Get board name registered in PICSimLab.
Definition board_x.h:56
void WritePreferences(void) override
Called to save board preferences in configuration file.
Definition board_x.cc:199
void Draw(void) override
Called ever 100ms to draw board.
Definition board_x.cc:384
void Run_CPU(void) override
Paralle thread called ever 100ms to run cpu code.
Definition board_x.cc:513
void ReadPreferences(char *name, char *value) override
Called whe configuration file load preferences.
Definition board_x.cc:212
void Reset(void) override
Reset board status.
Definition board_x.cc:133
unsigned short GetInputId(char *name) override
return the input ids numbers of names used in input map
Definition board_x.cc:61
void EvMouseMove(unsigned int button, unsigned int x, unsigned int y, unsigned int state) override
Event on the board.
Definition board_x.cc:323
void EvMouseButtonRelease(unsigned int button, unsigned int x, unsigned int y, unsigned int state) override
Event on the board.
Definition board_x.cc:346
void EvKeyPress(unsigned int key, unsigned int mask) override
Event on the board.
Definition board_x.cc:237
unsigned short GetOutputId(char *name) override
return the output ids numbers of names used in output map
Definition board_x.cc:81
void RegisterRemoteControl(void) override
Register remote control variables.
Definition board_x.cc:163
void EvKeyRelease(unsigned int key, unsigned int mask) override
Event on the board.
Definition board_x.cc:253
std::string GetAboutInfo(void) override
Return the about information of part.
Definition board_x.h:58
Definition swbounce.h:29

board_x.cc

/* ########################################################################
PICSimLab - Programmable IC Simulator Laboratory
########################################################################
Copyright (c) : 2015-2024 Luis Claudio Gambôa Lopes <lcgamboa@yahoo.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
For e-mail suggestions : lcgamboa@yahoo.com
######################################################################## */
// include files
#include "board_x.h"
#include <math.h>
#include "../lib/oscilloscope.h"
#include "../lib/picsimlab.h"
#include "../lib/spareparts.h"
/* ids of inputs of input map*/
enum {
I_POT1, // potentiometer
I_ICSP, // ICSP connector
I_PWR, // Power button
I_RST, // Reset button
I_BD0, // RD0 push button
I_SD1 // RD1 switch
};
/* ids of outputs of output map*/
enum {
O_POT1, // potentiometer
O_RST, // Reset button
O_SD1, // switch position (On/Off)
O_LD0, // LED on RD0 push button
O_LD1, // LED on RD1 switch
O_LPWR, // Power LED
O_RB0, // LED on RB0 output
O_RB1, // LED on RB1 output
O_BD0, // RD1 switch
O_CPU // CPU name
};
enum { PWM0 = 1, PWM1 };
// return the input ids numbers of names used in input map
unsigned short cboard_x::GetInputId(char* name) {
if (strcmp(name, "PG_ICSP") == 0)
return I_ICSP;
if (strcmp(name, "SW_PWR") == 0)
return I_PWR;
if (strcmp(name, "PB_RST") == 0)
return I_RST;
if (strcmp(name, "PB_D0") == 0)
return I_BD0;
if (strcmp(name, "SW_D1") == 0)
return I_SD1;
if (strcmp(name, "PO_1") == 0)
return I_POT1;
printf("Error input '%s' don't have a valid id! \n", name);
return INVALID_ID;
}
// return the output ids numbers of names used in output map
unsigned short cboard_x::GetOutputId(char* name) {
if (strcmp(name, "SW_D1") == 0)
return O_SD1;
if (strcmp(name, "LD_LD0") == 0)
return O_LD0;
if (strcmp(name, "LD_LD1") == 0)
return O_LD1;
if (strcmp(name, "LD_LPWR") == 0)
return O_LPWR;
if (strcmp(name, "LD_RB1") == 0)
return O_RB1;
if (strcmp(name, "LD_RB0") == 0)
return O_RB0;
if (strcmp(name, "PB_D0") == 0)
return O_BD0;
if (strcmp(name, "PO_1") == 0)
return O_POT1;
if (strcmp(name, "PB_RST") == 0)
return O_RST;
if (strcmp(name, "IC_CPU") == 0)
return O_CPU;
printf("Error output '%s' don't have a valid id! \n", name);
return INVALID_ID;
}
// Constructor called once on board creation
cboard_x::cboard_x(void) {
Proc = "PIC18F4550"; // default microcontroller if none defined in preferences
ReadMaps(); // Read input and output board maps
pot1 = 100;
active = 0;
PICSimLab.UpdateGUI(PWM0, GT_GAUGE, GA_ADD, (void*)"*RB0");
PICSimLab.UpdateGUI(PWM1, GT_GAUGE, GA_ADD, (void*)"*RB1");
SWBounce_init(&bounce, 2);
}
// Destructor called once on board destruction
cboard_x::~cboard_x(void) {
PICSimLab.UpdateGUI(PWM0, GT_GAUGE, GA_DEL, NULL);
PICSimLab.UpdateGUI(PWM1, GT_GAUGE, GA_DEL, NULL);
SWBounce_end(&bounce);
}
// Reset board status
void cboard_x::Reset(void) {
pic_reset(&pic, 1);
p_BT1 = 1; // set push button in default state (high)
// write button state to pic pin 19 (RD0)
pic_set_pin(&pic, 19, p_BT1);
// write switch state to pic pin 20 (RD1)
pic_set_pin(&pic, 20, p_BT2);
// verify serial port state and refresh status bar
if (pic.serial[0].serialfd != INVALID_SERIAL)
PICSimLab.UpdateStatus(
PS_SERIAL,
"Serial: " + std::string(SERIALDEVICE) + ":" + std::to_string(pic.serial[0].serialbaud) + "(" +
FloatStrFormat("%4.1f", fabs((100.0 * pic.serial[0].serialexbaud - 100.0 * pic.serial[0].serialbaud) /
pic.serial[0].serialexbaud)) +
"%)");
else
PICSimLab.UpdateStatus(PS_SERIAL, "Serial: " + std::string(SERIALDEVICE) + " (ERROR)");
if (use_spare)
SpareParts.Reset();
}
// Register variables to be controled by remote control
// register inputa
input_ids[I_BD0]->status = &p_BT1;
input_ids[I_SD1]->status = &p_BT2;
input_ids[I_POT1]->status = &pot1;
// register output to be updated on input change
input_ids[I_BD0]->update = &output_ids[O_BD0]->update;
input_ids[I_SD1]->update = &output_ids[O_SD1]->update;
input_ids[I_POT1]->update = &output_ids[O_POT1]->update;
// register outputa
output_ids[O_RB0]->status = &pic.pins[32].oavalue;
output_ids[O_RB1]->status = &pic.pins[33].oavalue;
output_ids[O_LD0]->status = &pic.pins[18].oavalue;
output_ids[O_LD1]->status = &pic.pins[19].oavalue;
}
// Called ever 1s to refresh status
// verify serial port state and refresh status bar
if (pic.serial[0].serialfd != INVALID_SERIAL)
PICSimLab.UpdateStatus(
PS_SERIAL,
"Serial: " + std::string(SERIALDEVICE) + ":" + std::to_string(pic.serial[0].serialbaud) + "(" +
FloatStrFormat("%4.1f", fabs((100.0 * pic.serial[0].serialexbaud - 100.0 * pic.serial[0].serialbaud) /
pic.serial[0].serialexbaud)) +
"%)");
else
PICSimLab.UpdateStatus(PS_SERIAL, "Serial: " + std::string(SERIALDEVICE) + " (ERROR)");
}
// Called to save board preferences in configuration file
// write selected microcontroller of board_x to preferences
PICSimLab.SavePrefs("X_proc", Proc);
// write switch state of board_x to preferences
PICSimLab.SavePrefs("X_bt2", std::to_string(p_BT2));
// write microcontroller clock to preferences
PICSimLab.SavePrefs("X_clock", FloatStrFormat("%2.1f", PICSimLab.GetClock()));
// write potentiometer position to preferences
PICSimLab.SavePrefs("X_pot1", std::to_string(pot1));
}
// Called whe configuration file load preferences
void cboard_x::ReadPreferences(char* name, char* value) {
// read switch state of board_x of preferences
if (!strcmp(name, "X_bt2")) {
if (value[0] == '0')
p_BT2 = 0;
else
p_BT2 = 1;
}
// read microcontroller of preferences
if (!strcmp(name, "X_proc")) {
Proc = value;
}
// read microcontroller clock
if (!strcmp(name, "X_clock")) {
PICSimLab.SetClock(atof(value));
}
// read potentiometer position
if (!strcmp(name, "X_pot1")) {
pot1 = atoi(value);
}
}
// Event on the board
void cboard_x::EvKeyPress(unsigned int key, unsigned int mask) {
// if keyboard key 1 is pressed then activate button (state=0)
if (key == '1') {
p_BT1 = 0;
output_ids[O_BD0]->update = 1;
}
// if keyboard key 2 is pressed then toggle switch state
if (key == '2') {
p_BT2 ^= 1;
output_ids[O_SD1]->update = 1;
}
}
// Event on the board
void cboard_x::EvKeyRelease(unsigned int key, unsigned int mask) {
// if keyboard key 1 is pressed then deactivate button (state=1)
if (key == '1') {
p_BT1 = 1;
output_ids[O_BD0]->update = 1;
}
}
// Event on the board
void cboard_x::EvMouseButtonPress(unsigned int button, unsigned int x, unsigned int y, unsigned int state) {
int i;
// search for the input area which owner the event
for (i = 0; i < inputc; i++) {
if (((input[i].x1 <= x) && (input[i].x2 >= x)) && ((input[i].y1 <= y) && (input[i].y2 >= y))) {
switch (input[i].id) {
// if event is over I_ISCP area then load hex file
case I_ICSP:
PICSimLab.OpenLoadHexFileDialog();
;
break;
// if event is over I_PWR area then toggle board on/off
case I_PWR:
if (PICSimLab.GetMcuPwr()) // if on turn off
{
PICSimLab.SetMcuPwr(0);
Reset();
p_BT1 = 1;
} else // if off turn on
{
PICSimLab.SetMcuPwr(1);
Reset();
}
output_ids[O_LPWR]->update = 1;
break;
// if event is over I_RST area then turn off and reset
case I_RST:
if (PICSimLab.GetMcuPwr() && pic_reset(&pic, -1)) // if powered
{
PICSimLab.SetMcuPwr(0);
PICSimLab.SetMcuRst(1);
}
p_RST = 0;
output_ids[O_RST]->update = 1;
break;
// if event is over I_D0 area then activate button (state=0)
case I_BD0:
p_BT1 = 0;
output_ids[O_BD0]->update = 1;
break;
// if event is over I_D1 area then toggle switch state
case I_SD1:
p_BT2 ^= 1;
output_ids[O_SD1]->update = 1;
break;
case I_POT1: {
active = 1;
pot1 = (x - input[i].x1) * 2.77;
if (pot1 > 199)
pot1 = 199;
output_ids[O_POT1]->update = 1;
} break;
}
}
}
}
// Event on the board
void cboard_x::EvMouseMove(unsigned int button, unsigned int x, unsigned int y, unsigned int state) {
int i;
for (i = 0; i < inputc; i++) {
switch (input[i].id) {
case I_POT1:
if (((input[i].x1 <= x) && (input[i].x2 >= x)) && ((input[i].y1 <= y) && (input[i].y2 >= y))) {
if (active) {
pot1 = (x - input[i].x1) * 2.77;
if (pot1 > 199)
pot1 = 199;
output_ids[O_POT1]->update = 1;
}
} else {
active = 0;
}
break;
}
}
}
// Event on the board
void cboard_x::EvMouseButtonRelease(unsigned int button, unsigned int x, unsigned int y, unsigned int state) {
int i;
// search for the input area which owner the event
for (i = 0; i < inputc; i++) {
if (((input[i].x1 <= x) && (input[i].x2 >= x)) && ((input[i].y1 <= y) && (input[i].y2 >= y))) {
switch (input[i].id) {
// if event is over I_RST area then turn on
case I_RST:
if (PICSimLab.GetMcuRst()) // if powered
{
PICSimLab.SetMcuPwr(1);
PICSimLab.SetMcuRst(0);
if (pic_reset(&pic, -1)) {
Reset();
}
}
p_RST = 1;
output_ids[O_RST]->update = 1;
break;
// if event is over I_D0 area then deactivate button (state=1)
case I_BD0:
p_BT1 = 1;
output_ids[O_BD0]->update = 1;
break;
case I_POT1: {
active = 0;
output_ids[O_POT1]->update = 1;
} break;
}
}
}
}
// Called ever 100ms to draw board
// This is the critical code for simulator running speed
void cboard_x::Draw(void) {
int update = 0; // verifiy if updated is needed
int i;
// board_x draw
for (i = 0; i < outputc; i++) // run over all outputs
{
if (output[i].update) // only if need update
{
output[i].update = 0;
if (!update) {
PICSimLab.CanvasCmd({CC_INIT, .Init{Scale, Scale, 0}});
PICSimLab.CanvasCmd({CC_SETFONTWEIGHT, .SetFontWeight{CC_FONTWEIGHT_BOLD}});
}
update++; // set to update buffer
if (!output[i].r) // if output shape is a rectangle
{
if (output[i].id == O_SD1) // if output is switch
{
// draw a background white rectangle
PICSimLab.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{255, 255, 255}});
PICSimLab.CanvasCmd(
{CC_RECTANGLE, .Rectangle{1, output[i].x1, output[i].y1, output[i].x2 - output[i].x1,
output[i].y2 - output[i].y1}});
if (!p_BT2) // draw switch off
{
// draw a grey rectangle
PICSimLab.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{70, 70, 70}});
PICSimLab.CanvasCmd(
{CC_RECTANGLE,
.Rectangle{1, output[i].x1, output[i].y1 + ((int)((output[i].y2 - output[i].y1) * 0.35)),
output[i].x2 - output[i].x1, ((output[i].y2 - output[i].y1) * 0.65f)}});
} else // draw switch on
{
// draw a grey rectangle
PICSimLab.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{70, 70, 70}});
PICSimLab.CanvasCmd(
{CC_RECTANGLE, .Rectangle{1, output[i].x1, output[i].y1, output[i].x2 - output[i].x1,
((output[i].y2 - output[i].y1) * 0.65f)}});
}
} else if (output[i].id == O_BD0) {
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{102, 102, 102}});
PICSimLab.CanvasCmd({CC_CIRCLE, .Circle{1, output[i].cx, output[i].cy, 10}});
if (p_BT1) {
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{15, 15, 15}});
} else {
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{55, 55, 55}});
}
PICSimLab.CanvasCmd({CC_CIRCLE, .Circle{1, output[i].cx, output[i].cy, 8}});
} else if (output[i].id == O_RST) {
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{102, 102, 102}});
PICSimLab.CanvasCmd({CC_CIRCLE, .Circle{1, output[i].cx, output[i].cy, 10}});
if (p_RST) {
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{15, 15, 15}});
} else {
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{55, 55, 55}});
}
PICSimLab.CanvasCmd({CC_CIRCLE, .Circle{1, output[i].cx, output[i].cy, 8}});
} else if (output[i].id == O_POT1) {
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{0, 50, 215}});
PICSimLab.CanvasCmd(
{CC_RECTANGLE, .Rectangle{1, output[i].x1, output[i].y1, output[i].x2 - output[i].x1,
output[i].y2 - output[i].y1}});
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{250, 250, 250}});
PICSimLab.CanvasCmd(
{CC_RECTANGLE, .Rectangle{1, output[i].x1 + pot1 / 2.77f, output[i].y1 + 2, 10, 15}});
} else if (output[i].id == O_CPU) {
PICSimLab.CanvasCmd({CC_SETFONTSIZE, .SetFontSize{10}});
float x, y;
int w, h;
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{26, 26, 26}});
PICSimLab.CanvasCmd(
{CC_RECTANGLE, .Rectangle{1, output[i].x1, output[i].y1, output[i].x2 - output[i].x1,
output[i].y2 - output[i].y1}});
PICSimLab.CanvasCmd({CC_SETCOLOR, .SetColor{230, 230, 230}});
w = output[i].x2 - output[i].x1;
h = output[i].y2 - output[i].y2;
x = output[i].x1 + (w / 2) + 7;
y = output[i].y1 + (h / 2) + (Proc.length());
PICSimLab.CanvasCmd({CC_ROTATEDTEXT, .RotatedText{Proc.c_str(), x, y, 270}});
}
} else // if output shape is a circle
{
PICSimLab.CanvasCmd({CC_SETFGCOLOR, .SetFgColor{0, 0, 0}}); // black
switch (output[i].id) // search for color of output
{
case O_LD0: // White using pin 19 mean value (RD0)
PICSimLab.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{(unsigned int)pic.pins[18].oavalue,
(unsigned int)pic.pins[18].oavalue,
(unsigned int)pic.pins[18].oavalue}});
break;
case O_LD1: // Yelllow using pin 20 mean value (RD1)
PICSimLab.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{(unsigned int)pic.pins[19].oavalue,
(unsigned int)pic.pins[19].oavalue, 0}});
break;
case O_LPWR: // Blue using mcupwr value
PICSimLab.CanvasCmd(
{CC_SETBGCOLOR, .SetBgColor{0, 0, (unsigned int)(200 * PICSimLab.GetMcuPwr() + 55)}});
break;
case O_RB0: // Green using pin 33 mean value (RB0)
PICSimLab.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{0, (unsigned int)pic.pins[32].oavalue, 0}});
break;
case O_RB1: // Red using pin 34 mean value (RB1)
PICSimLab.CanvasCmd({CC_SETBGCOLOR, .SetBgColor{(unsigned int)pic.pins[33].oavalue, 0, 0}});
break;
}
DrawLED(PICSimLab.CanvasCmd, &output[i]);
}
}
}
// end draw
if (update) {
PICSimLab.CanvasCmd({CC_END});
}
int value = (pic.pins[33].oavalue - 55) / 2; // RB0 mean value
PICSimLab.UpdateGUI(PWM0, GT_GAUGE, GA_SET, (void*)&value);
value = (pic.pins[32].oavalue - 55) / 2; // RB1 mean value
PICSimLab.UpdateGUI(PWM1, GT_GAUGE, GA_SET, (void*)&value);
}
void cboard_x::Run_CPU(void) {
int i;
int j;
unsigned char pi;
const picpin* pins;
unsigned int alm[40];
int bret;
const int JUMPSTEPS = PICSimLab.GetJUMPSTEPS(); // number of steps skipped
const long int NSTEP = PICSimLab.GetNSTEP(); // number of steps in 100ms
const float RNSTEP = 200.0 * pic.PINCOUNT / NSTEP;
// reset pins mean value
memset(alm, 0, 40 * sizeof(unsigned int));
// read pic.pins to a local
// variable to speed up
pins = pic.pins;
// Spare parts window pre
// process
if (use_spare)
SpareParts.PreProcess();
SWBounce_prepare(&bounce, PICSimLab.GetBoard()->MGetInstClockFreq());
unsigned char p_BT1_ = p_BT1;
unsigned char p_BT2_ = p_BT2;
if ((pins[19 - 1].dir == PD_IN) && (pins[19 - 1].value != p_BT1_)) {
SWBounce_bounce(&bounce, 0);
}
if ((pins[20 - 1].dir == PD_IN) && (pins[20 - 1].value != p_BT2_)) {
SWBounce_bounce(&bounce, 1);
}
j = JUMPSTEPS; // step counter
pi = 0;
if (PICSimLab.GetMcuPwr()) // if
// powered
for (i = 0; i < NSTEP; i++) // repeat for
// number of
// steps in 100ms
{
if (j >= JUMPSTEPS) // if
// number
// of
// step
// is
// bigger
// than
// steps
// to
// skip
{
pic_set_pin(&pic, pic.mclr, p_RST);
if (!bounce.do_bounce) {
pic_set_pin(&pic, 19,
p_BT1_); // Set
// pin
// 19
// (RD0)
// with
// button
// state
pic_set_pin(&pic, 20,
p_BT2_); // Set
// pin
// 20
// (RD1)
// with
// switch
// state
}
}
if (bounce.do_bounce) {
bret = SWBounce_process(&bounce);
if (bret) {
if (bounce.bounce[0]) {
if (bret == 1) {
pic_set_pin(&pic, 19, !pins[19 - 1].value);
} else {
pic_set_pin(&pic, 19, p_BT1_);
}
}
if (bounce.bounce[1]) {
if (bret == 1) {
pic_set_pin(&pic, 20, !pins[20 - 1].value);
} else {
pic_set_pin(&pic, 20, p_BT2_);
}
}
}
}
// verify if a
// breakpoint is reached
// if not run one
// instruction
if (!mplabxd_testbp())
pic_step(&pic);
ioupdated = pic.ioupdated;
// Oscilloscope window
// process
Oscilloscope.SetSample();
// Spare parts window
// process
if (use_spare)
SpareParts.Process();
// increment mean value
// counter if pin is
// high
alm[pi] += pins[pi].value;
pi++;
if (pi == pic.PINCOUNT)
pi = 0;
if (j >= JUMPSTEPS) // if
// number
// of
// step
// is
// bigger
// than
// steps
// to
// skip
{
// set analog pin 2
// (AN0) with value
// from scroll
pic_set_apin(&pic, 2, (5.0 * pot1 / 199));
j = -1; // reset
// counter
}
j++; // counter
// increment
pic.ioupdated = 0;
}
// calculate mean value
for (pi = 0; pi < pic.PINCOUNT; pi++) {
pic.pins[pi].oavalue = (int)((alm[pi] * RNSTEP) + 55);
}
// Spare parts window pre post
// process
if (use_spare)
SpareParts.PostProcess();
// verifiy if LEDS need update
if (output_ids[O_LD0]->value != pic.pins[18].oavalue) {
output_ids[O_LD0]->value = pic.pins[18].oavalue;
output_ids[O_LD0]->update = 1;
}
if (output_ids[O_LD1]->value != pic.pins[19].oavalue) {
output_ids[O_LD1]->value = pic.pins[19].oavalue;
output_ids[O_LD1]->update = 1;
}
if (output_ids[O_RB0]->value != pic.pins[32].oavalue) {
output_ids[O_RB0]->value = pic.pins[32].oavalue;
output_ids[O_RB0]->update = 1;
}
if (output_ids[O_RB1]->value != pic.pins[33].oavalue) {
output_ids[O_RB1]->value = pic.pins[33].oavalue;
output_ids[O_RB1]->update = 1;
}
}
// Register the board in PICSimLab
board_init(BOARD_x_Name, cboard_x);
void SetSample(void)
Sample and update oscilloscope data aquisition.
Definition oscilloscope.cc:63
void SetMcuRst(int pr)
Set mcu rst flag (inform simulator about mcu reset state)
Definition picsimlab.h:121
int GetMcuRst(void)
Retunr if microcontroller reset pin is enabled.
Definition picsimlab.h:101
void SetMcuPwr(int pp)
Set the power status of microcontroller ON/OFF.
Definition picsimlab.h:108
int GetMcuPwr(void)
Return actual power status of microcontroller ON/OFF.
Definition picsimlab.h:96
int GetJUMPSTEPS(void)
Get the number of steps to be skipped in board update.
Definition picsimlab.h:83
board * GetBoard(void)
Return a pointer to board object.
Definition picsimlab.h:89
void SavePrefs(std::string name, std::string value)
Save the preferences.
Definition picsimlab.cc:251
void Process(void)
Execute the process code of spare parts N times (where N is the number of steps in 100ms)
Definition spareparts.cc:545
void PostProcess(void)
Execute the post process code of spare parts one time per 100ms.
Definition spareparts.cc:565
void PreProcess(void)
Execute the pre process code of spare parts one time per 100ms.
Definition spareparts.cc:520
output_t output[MAX_IDS]
output map elements
Definition board.h:659
input_t * input_ids[MAX_IDS]
input map elements by id order
Definition board.h:658
int use_oscope
use oscilloscope window
Definition board.h:663
virtual float MGetInstClockFreq(void)=0
board microcontroller get cpu internal clock (in PIC frequency/4)
void InstCounterInc(void)
Increment the Intructions Counter.
Definition board.cc:398
int outputc
output map elements counter
Definition board.h:662
output_t * output_ids[MAX_IDS]
output map elements by id order
Definition board.h:660
unsigned char p_RST
board /RESET pin state
Definition board.h:665
input_t input[MAX_IDS]
input map elements
Definition board.h:657
int use_spare
use spare parts window
Definition board.h:664
int inputc
input map elements counter
Definition board.h:661
void ReadMaps(void)
Read maps.
Definition board.cc:61
std::string Proc
Name of processor in use.
Definition board.h:655
unsigned char * update
output need draw update
Definition board.h:56
float x1
x1 position
Definition board.h:47
void * status
rcontrol status
Definition board.h:55
float cx
center x position
Definition board.h:73
float cy
center y position
Definition board.h:74