mirror of
https://github.com/thiagoralves/OpenPLC_Editor.git
synced 2025-05-09 00:21:53 +08:00
Brought changes from Beremiz up until commit 24768ad on branch python3. Added live monitoring support from OpenPLC master branch
This commit is contained in:
parent
35d7d079ec
commit
baf70966a4
BIN
editor/.DS_Store
vendored
BIN
editor/.DS_Store
vendored
Binary file not shown.
76
editor/.github/workflows/run_tests_in_docker.yml
vendored
Normal file
76
editor/.github/workflows/run_tests_in_docker.yml
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
name: CI Automated testing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ python3 ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: beremiz
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: beremiz/matiec
|
||||
ref: e5be6a1f036d21cd7b5ee75ef352783a7cfcc1a7
|
||||
path: matiec
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: open62541/open62541
|
||||
ref: v1.3.6
|
||||
path: open62541
|
||||
submodules: recursive
|
||||
|
||||
- name: Restore cached docker image
|
||||
id: cache-docker-restore
|
||||
uses: actions/cache/restore@v3
|
||||
env:
|
||||
cache-name: cache-docker
|
||||
with:
|
||||
path: /tmp/latest.tar
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('beremiz/tests/tools/Docker', 'beremiz/requirements.txt') }}
|
||||
|
||||
- if: ${{ steps.cache-docker-restore.outputs.cache-hit == false }}
|
||||
name: Create docker image
|
||||
run: |
|
||||
cd beremiz/tests/tools/Docker
|
||||
./build_docker_image.sh
|
||||
docker image save --output="/tmp/latest.tar" beremiz_sikuli
|
||||
|
||||
- if: ${{ steps.cache-docker-restore.outputs.cache-hit == false }}
|
||||
name: Save docker image in cache
|
||||
id: cache-docker-save
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: /tmp/latest.tar
|
||||
key: ${{ steps.cache-docker-restore.outputs.cache-primary-key }}
|
||||
|
||||
- if: ${{ steps.cache-docker-restore.outputs.cache-hit != false }}
|
||||
name: Re-use docker image
|
||||
run: |
|
||||
docker image load --input="/tmp/latest.tar"
|
||||
|
||||
- name: Create docker container
|
||||
run: |
|
||||
cd beremiz/tests/tools/Docker
|
||||
./create_docker_container.sh ${{ github.workspace }}/test
|
||||
|
||||
- name: Run tests in docker
|
||||
run: |
|
||||
cd beremiz/tests/tools/Docker
|
||||
./do_test_in_docker.sh
|
||||
|
||||
- name: Upload test resuts artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: test_results
|
||||
path: ${{ github.workspace }}/test
|
||||
retention-days: 5
|
9
editor/.gitignore
vendored
Normal file
9
editor/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
*.pyc
|
||||
**/__pycache__
|
||||
.vscode
|
||||
**/build/**
|
||||
*.class
|
||||
**/.svghmithumbs/**
|
||||
**/my_*.der
|
||||
**/my_*.pem
|
||||
tests/tools/Docker/requirements.txt
|
@ -1,6 +0,0 @@
|
||||
repo: 215982c73cd664bf5b82a086a6bd0e75f8fe3d60
|
||||
node: 8fb5c6eddc723baec392be98fe1969044539baee
|
||||
branch: default
|
||||
latesttag: null
|
||||
latesttagdistance: 2129
|
||||
changessincelatesttag: 2565
|
5
editor/.hgignore
Executable file → Normal file
5
editor/.hgignore
Executable file → Normal file
@ -1,5 +1,7 @@
|
||||
.project
|
||||
|
||||
.svghmithumbs
|
||||
|
||||
.directory
|
||||
.pytest_cache
|
||||
.cache
|
||||
@ -7,6 +9,7 @@
|
||||
|
||||
syntax: regexp
|
||||
^tests/.*/build$
|
||||
^exemples/.*/build$
|
||||
^.idea/.*
|
||||
syntax: regexp
|
||||
^.*\.pyc$
|
||||
@ -21,3 +24,5 @@ revision
|
||||
|
||||
doc/_build
|
||||
doc/locale
|
||||
|
||||
^.*\$py.class$
|
||||
|
0
editor/.pylint
Executable file → Normal file
0
editor/.pylint
Executable file → Normal file
@ -104,7 +104,7 @@ class BeremizIDELauncher(object):
|
||||
|
||||
def CreateApplication(self):
|
||||
|
||||
BeremizAppType = wx.App if wx.VERSION >= (3, 0, 0) else wx.PySimpleApp
|
||||
BeremizAppType = wx.App
|
||||
|
||||
class BeremizApp(BeremizAppType):
|
||||
def OnInit(_self): # pylint: disable=no-self-argument
|
||||
@ -113,8 +113,6 @@ class BeremizIDELauncher(object):
|
||||
|
||||
self.app = BeremizApp(redirect=self.debug)
|
||||
self.app.SetAppName('beremiz')
|
||||
if wx.VERSION < (3, 0, 0):
|
||||
wx.InitAllImageHandlers()
|
||||
|
||||
def ShowSplashScreen(self):
|
||||
class Splash(AdvancedSplash):
|
||||
|
@ -29,8 +29,9 @@ import pickle
|
||||
import sys
|
||||
import shutil
|
||||
import time
|
||||
import signal
|
||||
from time import time as gettime
|
||||
from threading import Lock, Timer, currentThread
|
||||
from threading import Lock, Timer, current_thread
|
||||
|
||||
import wx.lib.buttons
|
||||
import wx.lib.statbmp
|
||||
@ -82,12 +83,12 @@ from IDEFrame import \
|
||||
|
||||
from LocalRuntimeMixin import LocalRuntimeMixin
|
||||
|
||||
|
||||
# Define OpenPLC Editor FileMenu extra items id
|
||||
[
|
||||
ID_OPENPLCFILEMENUUPDATE
|
||||
] = [wx.NewId() for _init_coll_FileMenu_Items in range(1)]
|
||||
|
||||
|
||||
def AppendMenu(parent, help, id, kind, text):
|
||||
return parent.Append(wx.MenuItem(helpString=help, id=id, kind=kind, text=text))
|
||||
|
||||
@ -106,7 +107,7 @@ else:
|
||||
}
|
||||
|
||||
|
||||
MainThread = currentThread().ident
|
||||
MainThread = current_thread().ident
|
||||
REFRESH_PERIOD = 0.1
|
||||
|
||||
|
||||
@ -157,7 +158,7 @@ class LogPseudoFile(object):
|
||||
self.LastRefreshTimer = None
|
||||
|
||||
def _should_write(self):
|
||||
if MainThread == currentThread().ident:
|
||||
if MainThread == current_thread().ident:
|
||||
app = wx.GetApp()
|
||||
if app is not None:
|
||||
self._write()
|
||||
@ -251,9 +252,9 @@ class Beremiz(IDEFrame, LocalRuntimeMixin):
|
||||
kind=wx.ITEM_NORMAL, text=_('New') + '\tCTRL+N')
|
||||
AppendMenu(parent, help='', id=wx.ID_OPEN,
|
||||
kind=wx.ITEM_NORMAL, text=_('Open') + '\tCTRL+O')
|
||||
parent.Append(ID_FILEMENURECENTPROJECTS, _("&Recent Projects"), self.RecentProjectsMenu)
|
||||
self.RecentProjectsMenuItem = parent.AppendSubMenu(self.RecentProjectsMenu, _("&Recent Projects"))
|
||||
parent.AppendSeparator()
|
||||
parent.Append(wx.ID_ANY, _("&Tutorials and Examples"), self.TutorialsProjectsMenu)
|
||||
parent.AppendSubMenu(self.TutorialsProjectsMenu, _("&Tutorials and Examples"))
|
||||
|
||||
examples_dir = Bpath("examples")
|
||||
project_list = sorted(os.listdir(examples_dir))
|
||||
@ -449,6 +450,7 @@ class Beremiz(IDEFrame, LocalRuntimeMixin):
|
||||
# then we prefix CWD to PATH in order to ensure that
|
||||
# commands invoked by build process by default are
|
||||
# found here.
|
||||
#os.environ["PATH"] = os.getcwd()+';'+os.environ["PATH"]
|
||||
os.environ["PATH"] = os.getcwd()+'\\mingw\\bin;'+os.environ["PATH"]
|
||||
|
||||
def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True, logf=None):
|
||||
@ -515,6 +517,8 @@ class Beremiz(IDEFrame, LocalRuntimeMixin):
|
||||
self.RefreshAll()
|
||||
self.LogConsole.SetFocus()
|
||||
|
||||
signal.signal(signal.SIGTERM,self.signalTERM_handler)
|
||||
|
||||
def RefreshTitle(self):
|
||||
name = _("OpenPLC Editor")
|
||||
if self.CTR is not None:
|
||||
@ -651,6 +655,11 @@ class Beremiz(IDEFrame, LocalRuntimeMixin):
|
||||
# prevent event to continue, i.e. cancel closing
|
||||
event.Veto()
|
||||
|
||||
def signalTERM_handler(self, sig, frame):
|
||||
print ("Signal TERM caught: kill local runtime and quit, no save")
|
||||
self.KillLocalRuntime()
|
||||
sys.exit()
|
||||
|
||||
def RefreshFileMenu(self):
|
||||
self.RefreshRecentProjectsMenu()
|
||||
|
||||
@ -708,7 +717,7 @@ class Beremiz(IDEFrame, LocalRuntimeMixin):
|
||||
item = self.RecentProjectsMenu.FindItemByPosition(0)
|
||||
self.RecentProjectsMenu.Remove(item)
|
||||
|
||||
self.FileMenu.Enable(ID_FILEMENURECENTPROJECTS, len(recent_projects) > 0)
|
||||
self.RecentProjectsMenuItem.Enable(len(recent_projects) > 0)
|
||||
for idx, projectpath in enumerate(recent_projects):
|
||||
text = '&%d: %s' % (idx + 1, projectpath)
|
||||
|
||||
@ -985,14 +994,14 @@ class Beremiz(IDEFrame, LocalRuntimeMixin):
|
||||
|
||||
def OnProjectTreeItemBeginEdit(self, event):
|
||||
selected = event.GetItem()
|
||||
if self.ProjectTree.GetPyData(selected)["type"] == ITEM_CONFNODE:
|
||||
if self.ProjectTree.GetItemData(selected)["type"] == ITEM_CONFNODE:
|
||||
event.Veto()
|
||||
else:
|
||||
IDEFrame.OnProjectTreeItemBeginEdit(self, event)
|
||||
|
||||
def OnProjectTreeRightUp(self, event):
|
||||
item = event.GetItem()
|
||||
item_infos = self.ProjectTree.GetPyData(item)
|
||||
item_infos = self.ProjectTree.GetItemData(item)
|
||||
|
||||
if item_infos["type"] == ITEM_CONFNODE:
|
||||
confnode_menu = wx.Menu(title='')
|
||||
@ -1028,7 +1037,7 @@ class Beremiz(IDEFrame, LocalRuntimeMixin):
|
||||
|
||||
def OnProjectTreeItemActivated(self, event):
|
||||
selected = event.GetItem()
|
||||
item_infos = self.ProjectTree.GetPyData(selected)
|
||||
item_infos = self.ProjectTree.GetItemData(selected)
|
||||
if item_infos["type"] == ITEM_CONFNODE:
|
||||
item_infos["confnode"]._OpenView()
|
||||
event.Skip()
|
||||
@ -1039,7 +1048,7 @@ class Beremiz(IDEFrame, LocalRuntimeMixin):
|
||||
|
||||
def ProjectTreeItemSelect(self, select_item):
|
||||
if select_item is not None and select_item.IsOk():
|
||||
item_infos = self.ProjectTree.GetPyData(select_item)
|
||||
item_infos = self.ProjectTree.GetItemData(select_item)
|
||||
if item_infos["type"] == ITEM_CONFNODE:
|
||||
item_infos["confnode"]._OpenView(onlyopened=True)
|
||||
elif item_infos["type"] == ITEM_PROJECT:
|
||||
|
@ -117,7 +117,8 @@ def process_pipeline(session, processors, **kwargs):
|
||||
click.echo("Press Ctrl+C to quit")
|
||||
try:
|
||||
while True:
|
||||
time.sleep(1)
|
||||
session.controller.UpdateMethodsFromPLCStatus()
|
||||
time.sleep(0.5)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
|
@ -31,7 +31,7 @@ import threading
|
||||
import shlex
|
||||
import traceback
|
||||
import threading
|
||||
from threading import Thread, Semaphore, Lock, currentThread
|
||||
from threading import Thread, Semaphore, Lock, current_thread
|
||||
import builtins
|
||||
from functools import partial
|
||||
|
||||
@ -182,6 +182,12 @@ def Bpath(*args):
|
||||
return os.path.join(beremiz_dir, *args)
|
||||
|
||||
|
||||
import locale
|
||||
# Matiec's standard library relies on libC's locale-dependent
|
||||
# string to/from number convertions, but IEC-61131 counts
|
||||
# on '.' for decimal point. Therefore locale is reset to "C" */
|
||||
locale.setlocale(locale.LC_NUMERIC, "C")
|
||||
|
||||
def SetupI18n():
|
||||
# Get folder containing translation files
|
||||
localedir = os.path.join(beremiz_dir, "locale")
|
||||
@ -202,20 +208,7 @@ def SetupI18n():
|
||||
# Define locale domain
|
||||
loc.AddCatalog(domain)
|
||||
|
||||
import locale
|
||||
global default_locale
|
||||
default_locale = locale.getdefaultlocale()[1]
|
||||
|
||||
# sys.stdout.encoding = default_locale
|
||||
# if Beremiz_service is started from Beremiz IDE
|
||||
# sys.stdout.encoding is None (that means 'ascii' encoding').
|
||||
# And unicode string returned by wx.GetTranslation() are
|
||||
# automatically converted to 'ascii' string.
|
||||
def unicode_translation(message):
|
||||
return wx.GetTranslation(message).encode(default_locale)
|
||||
|
||||
builtins.__dict__['_'] = unicode_translation
|
||||
# builtins.__dict__['_'] = wx.GetTranslation
|
||||
builtins.__dict__['_'] = wx.GetTranslation
|
||||
|
||||
|
||||
# Life is hard... have a candy.
|
||||
@ -232,10 +225,7 @@ if enablewx:
|
||||
import re
|
||||
import wx.adv
|
||||
|
||||
if wx.VERSION >= (3, 0, 0):
|
||||
app = wx.App(redirect=False)
|
||||
else:
|
||||
app = wx.PySimpleApp(redirect=False)
|
||||
app = wx.App(redirect=False)
|
||||
app.SetTopWindow(wx.Frame(None, -1))
|
||||
|
||||
default_locale = None
|
||||
@ -369,7 +359,7 @@ if enablewx:
|
||||
_servicename = self.pyroserver.servicename
|
||||
_servicename = '' if _servicename is None else _servicename
|
||||
dlg = ParamsEntryDialog(None, _("Enter a name "), defaultValue=_servicename)
|
||||
dlg.SetTests([(lambda name: len(name) is not 0, _("Name must not be null!"))])
|
||||
dlg.SetTests([(lambda name: len(name) != 0, _("Name must not be null!"))])
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
self.pyroserver.servicename = dlg.GetValue()
|
||||
self.pyroserver.Restart()
|
||||
@ -446,10 +436,10 @@ if havewx:
|
||||
obj.res = default_evaluator(tocall, *args, **kwargs)
|
||||
wx_eval_lock.release()
|
||||
|
||||
main_thread_id = currentThread().ident
|
||||
main_thread_id = current_thread().ident
|
||||
def evaluator(tocall, *args, **kwargs):
|
||||
# To prevent deadlocks, check if current thread is not one already main
|
||||
current_id = currentThread().ident
|
||||
current_id = current_thread().ident
|
||||
|
||||
if main_thread_id != current_id:
|
||||
o = type('', (object,), dict(call=(tocall, args, kwargs), res=None))
|
||||
@ -533,7 +523,6 @@ if havetwisted:
|
||||
try:
|
||||
website = NS.RegisterWebsite(interface, webport)
|
||||
pyruntimevars["website"] = website
|
||||
statuschange.append(NS.website_statuslistener_factory(website))
|
||||
except Exception:
|
||||
LogMessageAndException(_("Nevow Web service failed. "))
|
||||
|
||||
@ -569,8 +558,9 @@ def FirstWorkerJob():
|
||||
|
||||
# Beremiz IDE detects LOCAL:// runtime is ready by looking
|
||||
# for self.workdir in the daemon's stdout.
|
||||
sys.stdout.write(_("Current working directory :") + WorkingDir + "\n")
|
||||
sys.stdout.flush()
|
||||
if sys.stdout:
|
||||
sys.stdout.write(_("Current working directory :") + WorkingDir + "\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
runtime.GetPLCObjectSingleton().AutoLoad(autostart)
|
||||
|
||||
|
@ -78,38 +78,11 @@ class CLIController(LocalRuntimeMixin, ProjectController):
|
||||
log = Log()
|
||||
LocalRuntimeMixin.__init__(self, log, use_gui=False)
|
||||
ProjectController.__init__(self, None, log)
|
||||
self.CLIStatusTimer = None
|
||||
self.KillCLIStatusTimer = False
|
||||
|
||||
|
||||
def StartCLIStatusTimer(self):
|
||||
if self.CLIStatusTimer is not None:
|
||||
return
|
||||
self.CLIStatusTimer = Timer(0.5, self.CLIStatusTimerProc)
|
||||
self.KillCLIStatusTimer = False
|
||||
self.CLIStatusTimer.start()
|
||||
|
||||
def StopCLIStatusTimer(self):
|
||||
if self.CLIStatusTimer is None:
|
||||
return
|
||||
self.KillCLIStatusTimer = True
|
||||
self.CLIStatusTimer.cancel()
|
||||
self.CLIStatusTimer = None
|
||||
|
||||
def CLIStatusTimerProc(self):
|
||||
self.CLIStatusTimer = None
|
||||
if not self.KillCLIStatusTimer:
|
||||
self.PullPLCStatusProc(None)
|
||||
self.StartCLIStatusTimer()
|
||||
|
||||
def _SetConnector(self, connector, update_status=True):
|
||||
self._connector = connector
|
||||
self.previous_log_count = [None]*LogLevelsCount
|
||||
if connector is not None:
|
||||
self.StartCLIStatusTimer()
|
||||
else:
|
||||
self.StopCLIStatusTimer()
|
||||
if update_status:
|
||||
if connector is None and update_status:
|
||||
self.UpdateMethodsFromPLCStatus()
|
||||
|
||||
def UpdatePLCLog(self, log_count):
|
||||
@ -143,6 +116,9 @@ class CLIController(LocalRuntimeMixin, ProjectController):
|
||||
_("\"%s\" is not a valid Beremiz project\n") % self.session.project_home)
|
||||
return True
|
||||
|
||||
if not os.path.isabs(self.session.project_home):
|
||||
self.session.project_home = os.path.join(os.getcwd(), self.session.project_home)
|
||||
|
||||
errmsg, error = self.LoadProject(self.session.project_home, self.session.buildpath)
|
||||
if error:
|
||||
self.logger.write_error(errmsg)
|
||||
@ -154,14 +130,9 @@ class CLIController(LocalRuntimeMixin, ProjectController):
|
||||
|
||||
@with_project_loaded
|
||||
def build_project(self, target):
|
||||
|
||||
if target:
|
||||
self.SetParamsAttribute("BeremizRoot.TargetType", target)
|
||||
elif sys.platform.startswith('linux'):
|
||||
self.SetParamsAttribute("BeremizRoot.TargetType", "Linux")
|
||||
elif sys.platform.startswith('darwin'):
|
||||
self.SetParamsAttribute("BeremizRoot.TargetType", "OSX")
|
||||
elif sys.platform.startswith('win'):
|
||||
self.SetParamsAttribute("BeremizRoot.TargetType", "Win32")
|
||||
|
||||
return 0 if self._Build() else 1
|
||||
|
||||
|
@ -193,7 +193,7 @@ class CodeFile(object):
|
||||
self.CodeFile,
|
||||
pretty_print=True,
|
||||
xml_declaration=True,
|
||||
encoding='utf-8'))
|
||||
encoding='utf-8').decode())
|
||||
xmlfile.close()
|
||||
|
||||
self.MarkCodeFileAsSaved()
|
||||
|
@ -131,6 +131,15 @@ class ConfigTreeNode(object):
|
||||
def CTNTestModified(self):
|
||||
return self.ChangesToSave
|
||||
|
||||
def CTNMarkModified(self):
|
||||
oldChangesToSave = self.ChangesToSave
|
||||
self.ChangesToSave = True
|
||||
if not oldChangesToSave:
|
||||
appframe = self.GetCTRoot().AppFrame
|
||||
if appframe is not None:
|
||||
appframe.RefreshTitle()
|
||||
appframe.RefreshPageTitles()
|
||||
|
||||
def ProjectTestModified(self):
|
||||
"""
|
||||
recursively check modified status
|
||||
@ -549,9 +558,12 @@ class ConfigTreeNode(object):
|
||||
ChildrenWithSameClass = self.Children.setdefault(CTNType, list())
|
||||
# Check count
|
||||
if getattr(CTNClass, "CTNMaxCount", None) and len(ChildrenWithSameClass) >= CTNClass.CTNMaxCount:
|
||||
raise Exception(
|
||||
_("Max count ({a1}) reached for this confnode of type {a2} ").
|
||||
format(a1=CTNClass.CTNMaxCount, a2=CTNType))
|
||||
|
||||
msg = _("Max count ({a1}) reached for this confnode of type {a2} ").format(
|
||||
a1=CTNClass.CTNMaxCount, a2=CTNType)
|
||||
self.GetCTRoot().logger.write_warning(msg)
|
||||
|
||||
return None
|
||||
|
||||
# create the final class, derived of provided confnode and template
|
||||
class FinalCTNClass(CTNClass, ConfigTreeNode):
|
||||
|
@ -137,7 +137,7 @@ def GetDeleteElementFunction(remove_function, parent_type=None, check_function=N
|
||||
name = self.ProjectTree.GetItemText(selected)
|
||||
if check_function is None or check_function(name):
|
||||
if parent_type is not None:
|
||||
item_infos = self.ProjectTree.GetPyData(selected)
|
||||
item_infos = self.ProjectTree.GetItemData(selected)
|
||||
parent_name = item_infos["tagname"].split("::")[1]
|
||||
remove_function(self.Controler, parent_name, name)
|
||||
else:
|
||||
@ -389,7 +389,7 @@ class IDEFrame(wx.Frame):
|
||||
parent.AppendSeparator()
|
||||
add_menu = wx.Menu(title='')
|
||||
self._init_coll_AddMenu_Items(add_menu)
|
||||
parent.Append(wx.ID_ADD, _("&Add Element"), add_menu)
|
||||
self.AddMenuItem = parent.AppendSubMenu(add_menu, _("&Add Element"))
|
||||
AppendMenu(parent, help='', id=wx.ID_SELECTALL,
|
||||
kind=wx.ITEM_NORMAL, text=_('Select All') + '\tCTRL+A')
|
||||
AppendMenu(parent, help='', id=wx.ID_DELETE,
|
||||
@ -440,16 +440,17 @@ class IDEFrame(wx.Frame):
|
||||
kind=wx.ITEM_NORMAL, text=_('Clear Errors') + '\tCTRL+K')
|
||||
parent.AppendSeparator()
|
||||
zoommenu = wx.Menu(title='')
|
||||
parent.Append(wx.ID_ZOOM_FIT, _("Zoom"), zoommenu)
|
||||
self.ZoomMenuItem = parent.AppendSubMenu(zoommenu, _("Zoom"))
|
||||
for idx, value in enumerate(ZOOM_FACTORS):
|
||||
new_item = AppendMenu(zoommenu, help='',
|
||||
kind=wx.ITEM_RADIO, text=str(int(round(value * 100))) + "%")
|
||||
self.Bind(wx.EVT_MENU, self.GenerateZoomFunction(idx), new_item)
|
||||
|
||||
parent.AppendSeparator()
|
||||
AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENUSWITCHPERSPECTIVE,
|
||||
kind=wx.ITEM_NORMAL, text=_('Switch perspective') + '\tF12')
|
||||
self.Bind(wx.EVT_MENU, self.SwitchPerspective, id=ID_PLCOPENEDITORDISPLAYMENUSWITCHPERSPECTIVE)
|
||||
if wx.VERSION >= (4, 1, 0):
|
||||
AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENUSWITCHPERSPECTIVE,
|
||||
kind=wx.ITEM_NORMAL, text=_('Switch perspective') + '\tF12')
|
||||
self.Bind(wx.EVT_MENU, self.SwitchPerspective, id=ID_PLCOPENEDITORDISPLAYMENUSWITCHPERSPECTIVE)
|
||||
|
||||
AppendMenu(parent, help='', id=ID_PLCOPENEDITORDISPLAYMENUFULLSCREEN,
|
||||
kind=wx.ITEM_NORMAL, text=_('Full screen') + '\tShift-F12')
|
||||
@ -1182,7 +1183,7 @@ class IDEFrame(wx.Frame):
|
||||
selected > -1 and self.SearchParams is not None)
|
||||
self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, True)
|
||||
MenuToolBar.EnableTool(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, True)
|
||||
self.EditMenu.Enable(wx.ID_ADD, True)
|
||||
self.AddMenuItem.Enable(True)
|
||||
self.EditMenu.Enable(wx.ID_DELETE, True)
|
||||
if self.TabsOpened.GetPageCount() > 0:
|
||||
self.EditMenu.Enable(wx.ID_CUT, True)
|
||||
@ -1222,7 +1223,7 @@ class IDEFrame(wx.Frame):
|
||||
self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUFINDPREVIOUS, False)
|
||||
self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, False)
|
||||
MenuToolBar.EnableTool(ID_PLCOPENEDITOREDITMENUSEARCHINPROJECT, False)
|
||||
self.EditMenu.Enable(wx.ID_ADD, False)
|
||||
self.AddMenuItem.Enable( False)
|
||||
self.EditMenu.Enable(wx.ID_DELETE, False)
|
||||
|
||||
def CloseTabsWithoutModel(self, refresh=True):
|
||||
@ -1297,7 +1298,7 @@ class IDEFrame(wx.Frame):
|
||||
if window == self.ProjectTree or window is None:
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
if selected is not None and selected.IsOk():
|
||||
function = self.DeleteFunctions.get(self.ProjectTree.GetPyData(selected)["type"], None)
|
||||
function = self.DeleteFunctions.get(self.ProjectTree.GetItemData(selected)["type"], None)
|
||||
if function is not None:
|
||||
function(self, selected)
|
||||
self.CloseTabsWithoutModel()
|
||||
@ -1354,24 +1355,24 @@ class IDEFrame(wx.Frame):
|
||||
if selected != -1:
|
||||
window = self.TabsOpened.GetPage(selected)
|
||||
if isinstance(window, Viewer):
|
||||
self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, True)
|
||||
zoommenu = self.DisplayMenu.FindItemById(wx.ID_ZOOM_FIT).GetSubMenu()
|
||||
self.ZoomMenuItem.Enable(True)
|
||||
zoommenu = self.ZoomMenuItem.GetSubMenu()
|
||||
zoomitem = zoommenu.FindItemByPosition(window.GetScale())
|
||||
zoomitem.Check(True)
|
||||
else:
|
||||
self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
|
||||
self.ZoomMenuItem.Enable(False)
|
||||
else:
|
||||
self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
|
||||
self.ZoomMenuItem.Enable(False)
|
||||
else:
|
||||
self.DisplayMenu.Enable(wx.ID_REFRESH, False)
|
||||
self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
|
||||
self.ZoomMenuItem.Enable(False)
|
||||
if self.EnableDebug:
|
||||
self.DisplayMenu.Enable(wx.ID_CLEAR, True)
|
||||
else:
|
||||
self.DisplayMenu.Enable(wx.ID_REFRESH, False)
|
||||
if self.EnableDebug:
|
||||
self.DisplayMenu.Enable(wx.ID_CLEAR, False)
|
||||
self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False)
|
||||
self.ZoomMenuItem.Enable(False)
|
||||
|
||||
def OnRefreshMenu(self, event):
|
||||
self.RefreshEditor()
|
||||
@ -1409,10 +1410,11 @@ class IDEFrame(wx.Frame):
|
||||
for child in self.TabsOpened.GetChildren():
|
||||
if isinstance(child, wx.aui.AuiTabCtrl):
|
||||
auitabctrl.append(child)
|
||||
if child not in self.AuiTabCtrl:
|
||||
if wx.VERSION >= (4, 1, 0) and child not in self.AuiTabCtrl:
|
||||
child.Bind(wx.EVT_LEFT_DCLICK, self.GetTabsOpenedDClickFunction(child))
|
||||
self.AuiTabCtrl = auitabctrl
|
||||
if self.TabsOpened.GetPageCount() == 0:
|
||||
# on wxPython 4.0.7, AuiManager has no "RestorePane" method...
|
||||
if wx.VERSION >= (4, 1, 0) and self.TabsOpened.GetPageCount() == 0:
|
||||
pane = self.AUIManager.GetPane(self.TabsOpened)
|
||||
# on wxPython 4.1.0, AuiPaneInfo has no "IsMaximized" attribute...
|
||||
if (not hasattr(pane, "IsMaximized")) or pane.IsMaximized():
|
||||
@ -1502,6 +1504,8 @@ class IDEFrame(wx.Frame):
|
||||
return OnTabsOpenedDClick
|
||||
|
||||
def SwitchPerspective(self, evt):
|
||||
if not hasattr(self.AUIManager, "MaximizePane"):
|
||||
return
|
||||
pane = self.AUIManager.GetPane(self.TabsOpened)
|
||||
# on wxPython 4.1.0, AuiPaneInfo has no "IsMaximized" attribute...
|
||||
IsMaximized = pane.IsMaximized() if hasattr(pane, "IsMaximized") \
|
||||
@ -1527,7 +1531,7 @@ class IDEFrame(wx.Frame):
|
||||
# Extract current selected item tagname
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
if selected is not None and selected.IsOk():
|
||||
item_infos = self.ProjectTree.GetPyData(selected)
|
||||
item_infos = self.ProjectTree.GetItemData(selected)
|
||||
tagname = item_infos.get("tagname", None)
|
||||
else:
|
||||
tagname = None
|
||||
@ -1607,7 +1611,7 @@ class IDEFrame(wx.Frame):
|
||||
found = False
|
||||
item, root_cookie = self.ProjectTree.GetFirstChild(root)
|
||||
while item is not None and item.IsOk() and not found:
|
||||
item_infos = self.ProjectTree.GetPyData(item)
|
||||
item_infos = self.ProjectTree.GetItemData(item)
|
||||
if (item_infos["name"].split(":")[-1].strip(), item_infos["type"]) == items[0]:
|
||||
if len(items) == 1:
|
||||
self.SelectedItem = item
|
||||
@ -1628,7 +1632,7 @@ class IDEFrame(wx.Frame):
|
||||
selected_item = (self.SelectedItem
|
||||
if self.SelectedItem is not None
|
||||
else event.GetItem())
|
||||
if selected_item.IsOk() and self.ProjectTree.GetPyData(selected_item)["type"] == ITEM_POU:
|
||||
if selected_item.IsOk() and self.ProjectTree.GetItemData(selected_item)["type"] == ITEM_POU:
|
||||
block_name = self.ProjectTree.GetItemText(selected_item)
|
||||
block_type = self.Controler.GetPouType(block_name)
|
||||
if block_type != "program":
|
||||
@ -1640,7 +1644,7 @@ class IDEFrame(wx.Frame):
|
||||
|
||||
def OnProjectTreeItemBeginEdit(self, event):
|
||||
selected = event.GetItem()
|
||||
if self.ProjectTree.GetPyData(selected)["type"] in ITEMS_UNEDITABLE:
|
||||
if self.ProjectTree.GetItemData(selected)["type"] in ITEMS_UNEDITABLE:
|
||||
event.Veto()
|
||||
else:
|
||||
event.Skip()
|
||||
@ -1657,7 +1661,7 @@ class IDEFrame(wx.Frame):
|
||||
else:
|
||||
item = event.GetItem()
|
||||
old_name = self.ProjectTree.GetItemText(item)
|
||||
item_infos = self.ProjectTree.GetPyData(item)
|
||||
item_infos = self.ProjectTree.GetItemData(item)
|
||||
if item_infos["type"] == ITEM_PROJECT:
|
||||
self.Controler.SetProjectProperties(name=new_name)
|
||||
elif item_infos["type"] == ITEM_DATATYPE:
|
||||
@ -1761,7 +1765,7 @@ class IDEFrame(wx.Frame):
|
||||
|
||||
def OnProjectTreeItemActivated(self, event):
|
||||
selected = event.GetItem()
|
||||
item_infos = self.ProjectTree.GetPyData(selected)
|
||||
item_infos = self.ProjectTree.GetItemData(selected)
|
||||
if item_infos["type"] == ITEM_PROJECT:
|
||||
self.EditProjectSettings()
|
||||
else:
|
||||
@ -1773,7 +1777,7 @@ class IDEFrame(wx.Frame):
|
||||
|
||||
def ProjectTreeItemSelect(self, select_item):
|
||||
if select_item is not None and select_item.IsOk():
|
||||
item_infos = self.ProjectTree.GetPyData(select_item)
|
||||
item_infos = self.ProjectTree.GetItemData(select_item)
|
||||
if item_infos["type"] in [ITEM_DATATYPE, ITEM_POU,
|
||||
ITEM_CONFIGURATION, ITEM_RESOURCE,
|
||||
ITEM_TRANSITION, ITEM_ACTION]:
|
||||
@ -1792,7 +1796,7 @@ class IDEFrame(wx.Frame):
|
||||
pt = wx.Point(event.GetX(), event.GetY())
|
||||
item, flags = self.ProjectTree.HitTest(pt)
|
||||
if item is not None and item.IsOk() and flags & wx.TREE_HITTEST_ONITEMLABEL:
|
||||
item_infos = self.ProjectTree.GetPyData(item)
|
||||
item_infos = self.ProjectTree.GetItemData(item)
|
||||
if item != self.LastToolTipItem and self.LastToolTipItem is not None:
|
||||
self.ProjectTree.SetToolTip(None)
|
||||
self.LastToolTipItem = None
|
||||
@ -1820,7 +1824,7 @@ class IDEFrame(wx.Frame):
|
||||
event.Skip()
|
||||
|
||||
def OnProjectTreeItemChanging(self, event):
|
||||
if self.ProjectTree.GetPyData(event.GetItem())["type"] not in ITEMS_UNEDITABLE and self.SelectedItem is None:
|
||||
if self.ProjectTree.GetItemData(event.GetItem())["type"] not in ITEMS_UNEDITABLE and self.SelectedItem is None:
|
||||
self.SelectedItem = event.GetItem()
|
||||
event.Veto()
|
||||
else:
|
||||
@ -1902,7 +1906,7 @@ class IDEFrame(wx.Frame):
|
||||
self.ProjectTree.SelectItem(item)
|
||||
self.ProjectTreeItemSelect(item)
|
||||
name = self.ProjectTree.GetItemText(item)
|
||||
item_infos = self.ProjectTree.GetPyData(item)
|
||||
item_infos = self.ProjectTree.GetItemData(item)
|
||||
|
||||
menu = None
|
||||
if item_infos["type"] in ITEMS_UNEDITABLE + [ITEM_PROJECT]:
|
||||
@ -1926,7 +1930,7 @@ class IDEFrame(wx.Frame):
|
||||
new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Paste POU"))
|
||||
self.Bind(wx.EVT_MENU, self.OnPastePou, new_item)
|
||||
if self.GetCopyBuffer() is None:
|
||||
menu.Enable(new_item, False)
|
||||
new_item.Enable(False)
|
||||
|
||||
elif name == "Configurations":
|
||||
menu = wx.Menu(title='')
|
||||
@ -1937,30 +1941,30 @@ class IDEFrame(wx.Frame):
|
||||
menu = wx.Menu(title='')
|
||||
new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Transition"))
|
||||
parent = self.ProjectTree.GetItemParent(item)
|
||||
parent_type = self.ProjectTree.GetPyData(parent)["type"]
|
||||
parent_type = self.ProjectTree.GetItemData(parent)["type"]
|
||||
while parent_type != ITEM_POU:
|
||||
parent = self.ProjectTree.GetItemParent(parent)
|
||||
parent_type = self.ProjectTree.GetPyData(parent)["type"]
|
||||
parent_type = self.ProjectTree.GetItemData(parent)["type"]
|
||||
self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(self.ProjectTree.GetItemText(parent)), new_item)
|
||||
|
||||
elif name == "Actions":
|
||||
menu = wx.Menu(title='')
|
||||
new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Action"))
|
||||
parent = self.ProjectTree.GetItemParent(item)
|
||||
parent_type = self.ProjectTree.GetPyData(parent)["type"]
|
||||
parent_type = self.ProjectTree.GetItemData(parent)["type"]
|
||||
while parent_type != ITEM_POU:
|
||||
parent = self.ProjectTree.GetItemParent(parent)
|
||||
parent_type = self.ProjectTree.GetPyData(parent)["type"]
|
||||
parent_type = self.ProjectTree.GetItemData(parent)["type"]
|
||||
self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(self.ProjectTree.GetItemText(parent)), new_item)
|
||||
|
||||
elif name == "Resources":
|
||||
menu = wx.Menu(title='')
|
||||
new_item = AppendMenu(menu, help='', kind=wx.ITEM_NORMAL, text=_("Add Resource"))
|
||||
parent = self.ProjectTree.GetItemParent(item)
|
||||
parent_type = self.ProjectTree.GetPyData(parent)["type"]
|
||||
parent_type = self.ProjectTree.GetItemData(parent)["type"]
|
||||
while parent_type not in [ITEM_CONFIGURATION, ITEM_PROJECT]:
|
||||
parent = self.ProjectTree.GetItemParent(parent)
|
||||
parent_type = self.ProjectTree.GetPyData(parent)["type"]
|
||||
parent_type = self.ProjectTree.GetItemData(parent)["type"]
|
||||
parent_name = None
|
||||
if parent_type == ITEM_PROJECT:
|
||||
config_names = self.Controler.GetProjectConfigNames()
|
||||
@ -2405,7 +2409,7 @@ class IDEFrame(wx.Frame):
|
||||
def GenerateChangePouTypeFunction(self, name, new_type):
|
||||
def OnChangePouTypeMenu(event):
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU:
|
||||
if self.ProjectTree.GetItemData(selected)["type"] == ITEM_POU:
|
||||
self.Controler.ProjectChangePouType(name, new_type)
|
||||
self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, PROJECTTREE, LIBRARYTREE)
|
||||
return OnChangePouTypeMenu
|
||||
@ -2422,7 +2426,7 @@ class IDEFrame(wx.Frame):
|
||||
def OnPastePou(self, event):
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
|
||||
if self.ProjectTree.GetPyData(selected)["type"] != ITEM_PROJECT:
|
||||
if self.ProjectTree.GetItemData(selected)["type"] != ITEM_PROJECT:
|
||||
pou_type = self.ProjectTree.GetItemText(selected)
|
||||
pou_type = self.UNEDITABLE_NAMES_DICT[pou_type] # one of 'Functions', 'Function Blocks' or 'Programs'
|
||||
pou_type = {'Functions': 'function', 'Function Blocks': 'functionBlock', 'Programs': 'program'}[pou_type]
|
||||
@ -2467,7 +2471,7 @@ class IDEFrame(wx.Frame):
|
||||
|
||||
def OnRemoveDataTypeMenu(self, event):
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
if self.ProjectTree.GetPyData(selected)["type"] == ITEM_DATATYPE:
|
||||
if self.ProjectTree.GetItemData(selected)["type"] == ITEM_DATATYPE:
|
||||
name = self.ProjectTree.GetItemText(selected)
|
||||
if self.CheckDataTypeIsUsedBeforeDeletion(name):
|
||||
self.Controler.ProjectRemoveDataType(name)
|
||||
@ -2479,12 +2483,12 @@ class IDEFrame(wx.Frame):
|
||||
|
||||
def OnRenamePouMenu(self, event):
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU:
|
||||
if self.ProjectTree.GetItemData(selected)["type"] == ITEM_POU:
|
||||
wx.CallAfter(self.ProjectTree.EditLabel, selected)
|
||||
|
||||
def OnRemovePouMenu(self, event):
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
if self.ProjectTree.GetPyData(selected)["type"] == ITEM_POU:
|
||||
if self.ProjectTree.GetItemData(selected)["type"] == ITEM_POU:
|
||||
name = self.ProjectTree.GetItemText(selected)
|
||||
if self.CheckPouIsUsedBeforeDeletion(name):
|
||||
self.Controler.ProjectRemovePou(name)
|
||||
@ -2496,7 +2500,7 @@ class IDEFrame(wx.Frame):
|
||||
|
||||
def OnRemoveTransitionMenu(self, event):
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
item_infos = self.ProjectTree.GetPyData(selected)
|
||||
item_infos = self.ProjectTree.GetItemData(selected)
|
||||
if item_infos["type"] == ITEM_TRANSITION:
|
||||
transition = self.ProjectTree.GetItemText(selected)
|
||||
pou_name = item_infos["tagname"].split("::")[1]
|
||||
@ -2509,7 +2513,7 @@ class IDEFrame(wx.Frame):
|
||||
|
||||
def OnRemoveActionMenu(self, event):
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
item_infos = self.ProjectTree.GetPyData(selected)
|
||||
item_infos = self.ProjectTree.GetItemData(selected)
|
||||
if item_infos["type"] == ITEM_ACTION:
|
||||
action = self.ProjectTree.GetItemText(selected)
|
||||
pou_name = item_infos["tagname"].split("::")[1]
|
||||
@ -2522,7 +2526,7 @@ class IDEFrame(wx.Frame):
|
||||
|
||||
def OnRemoveConfigurationMenu(self, event):
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
if self.ProjectTree.GetPyData(selected)["type"] == ITEM_CONFIGURATION:
|
||||
if self.ProjectTree.GetItemData(selected)["type"] == ITEM_CONFIGURATION:
|
||||
name = self.ProjectTree.GetItemText(selected)
|
||||
self.Controler.ProjectRemoveConfiguration(name)
|
||||
tagname = ComputeConfigurationName(name)
|
||||
@ -2533,7 +2537,7 @@ class IDEFrame(wx.Frame):
|
||||
|
||||
def OnRemoveResourceMenu(self, event):
|
||||
selected = self.ProjectTree.GetSelection()
|
||||
item_infos = self.ProjectTree.GetPyData(selected)
|
||||
item_infos = self.ProjectTree.GetItemData(selected)
|
||||
if item_infos["type"] == ITEM_RESOURCE:
|
||||
resource = self.ProjectTree.GetItemText(selected)
|
||||
config_name = item_infos["tagname"].split("::")[1]
|
||||
|
@ -6,14 +6,14 @@ import sys
|
||||
import tempfile
|
||||
import random
|
||||
import shutil
|
||||
|
||||
from util.ProcessLogger import ProcessLogger
|
||||
from util.paths import Bpath
|
||||
|
||||
LocalRuntimeInterpreterPath = \
|
||||
os.environ["BEREMIZPYTHONPATH"] \
|
||||
if "BEREMIZPYTHONPATH" in os.environ \
|
||||
else sys.executable if "windows" not in sys.platform \
|
||||
else sys.executable + 'w'
|
||||
_exec = sys.executable if "windows" not in sys.platform else sys.executable + 'w'
|
||||
LocalRuntimeInterpreterPath = os.environ.get("BEREMIZPYTHONPATH", _exec)
|
||||
|
||||
LocalHost = os.environ.get("BEREMIZ_LOCAL_HOST", "127.0.0.1")
|
||||
|
||||
class LocalRuntimeMixin():
|
||||
|
||||
|
@ -1,119 +0,0 @@
|
||||
import time
|
||||
from threading import Lock, Timer, currentThread
|
||||
from time import time as gettime
|
||||
|
||||
import wx
|
||||
|
||||
MainThread = currentThread().ident
|
||||
REFRESH_PERIOD = 0.1
|
||||
|
||||
|
||||
class LogPseudoFile(object):
|
||||
""" Base class for file like objects to facilitate StdOut for the Shell."""
|
||||
|
||||
def __init__(self, output, risecall):
|
||||
self.red_white = 1
|
||||
self.red_yellow = 2
|
||||
self.black_white = wx.stc.STC_STYLE_DEFAULT
|
||||
self.output = output
|
||||
self.risecall = risecall
|
||||
# to prevent rapid fire on rising log panel
|
||||
self.rising_timer = 0
|
||||
self.lock = Lock()
|
||||
self.YieldLock = Lock()
|
||||
self.RefreshLock = Lock()
|
||||
self.TimerAccessLock = Lock()
|
||||
self.stack = []
|
||||
self.LastRefreshTime = gettime()
|
||||
self.LastRefreshTimer = None
|
||||
|
||||
def write(self, s, style=None):
|
||||
if self.lock.acquire():
|
||||
self.stack.append((s, style))
|
||||
self.lock.release()
|
||||
current_time = gettime()
|
||||
self.TimerAccessLock.acquire()
|
||||
if self.LastRefreshTimer:
|
||||
self.LastRefreshTimer.cancel()
|
||||
self.LastRefreshTimer = None
|
||||
self.TimerAccessLock.release()
|
||||
if current_time - self.LastRefreshTime > REFRESH_PERIOD and self.RefreshLock.acquire(False):
|
||||
self._should_write()
|
||||
else:
|
||||
self.TimerAccessLock.acquire()
|
||||
self.LastRefreshTimer = Timer(REFRESH_PERIOD, self._timer_expired)
|
||||
self.LastRefreshTimer.start()
|
||||
self.TimerAccessLock.release()
|
||||
|
||||
def _timer_expired(self):
|
||||
if self.RefreshLock.acquire(False):
|
||||
self._should_write()
|
||||
else:
|
||||
self.TimerAccessLock.acquire()
|
||||
self.LastRefreshTimer = Timer(REFRESH_PERIOD, self._timer_expired)
|
||||
self.LastRefreshTimer.start()
|
||||
self.TimerAccessLock.release()
|
||||
|
||||
def _should_write(self):
|
||||
app = wx.GetApp()
|
||||
if app is not None:
|
||||
wx.CallAfter(self._write)
|
||||
|
||||
if MainThread == currentThread().ident:
|
||||
if app is not None:
|
||||
if self.YieldLock.acquire(0):
|
||||
app.Yield()
|
||||
self.YieldLock.release()
|
||||
|
||||
def _write(self):
|
||||
if self.output:
|
||||
self.output.Freeze()
|
||||
self.lock.acquire()
|
||||
for s, style in self.stack:
|
||||
if style is None:
|
||||
style = self.black_white
|
||||
if style != self.black_white:
|
||||
#self.output.StartStyling(self.output.GetLength(), 0xff)
|
||||
style = self.black_white
|
||||
|
||||
# Temporary deactivate read only mode on StyledTextCtrl for
|
||||
# adding text. It seems that text modifications, even
|
||||
# programmatically, are disabled in StyledTextCtrl when read
|
||||
# only is active
|
||||
start_pos = self.output.GetLength()
|
||||
self.output.SetReadOnly(False)
|
||||
self.output.AppendText(s)
|
||||
self.output.SetReadOnly(True)
|
||||
text_len = self.output.GetLength() - start_pos
|
||||
|
||||
if style != self.black_white:
|
||||
self.output.SetStyling(text_len, style)
|
||||
self.stack = []
|
||||
self.lock.release()
|
||||
self.output.Thaw()
|
||||
self.LastRefreshTime = gettime()
|
||||
try:
|
||||
self.RefreshLock.release()
|
||||
except Exception:
|
||||
pass
|
||||
newtime = time.time()
|
||||
if newtime - self.rising_timer > 1:
|
||||
self.risecall(self.output)
|
||||
self.rising_timer = newtime
|
||||
|
||||
def write_warning(self, s):
|
||||
self.write(s, self.red_white)
|
||||
|
||||
def write_error(self, s):
|
||||
self.write(s, self.red_yellow)
|
||||
|
||||
def flush(self):
|
||||
# Temporary deactivate read only mode on StyledTextCtrl for clearing
|
||||
# text. It seems that text modifications, even programmatically, are
|
||||
# disabled in StyledTextCtrl when read only is active
|
||||
self.output.SetReadOnly(False)
|
||||
self.output.SetText("")
|
||||
self.output.SetReadOnly(True)
|
||||
|
||||
def isatty(self):
|
||||
return False
|
@ -445,12 +445,12 @@ class PLCControler(object):
|
||||
return len(self.GetInstanceList(pou_infos, name, debug)) > 0
|
||||
return False
|
||||
|
||||
def GenerateProgram(self, filepath=None):
|
||||
def GenerateProgram(self, filepath=None, **kwargs):
|
||||
errors = []
|
||||
warnings = []
|
||||
if self.Project is not None:
|
||||
try:
|
||||
self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings)
|
||||
self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings,**kwargs)
|
||||
self.NextCompiledProject = self.Copy(self.Project)
|
||||
program_text = "".join([item[0] for item in self.ProgramChunks])
|
||||
if filepath is not None:
|
||||
@ -1144,28 +1144,35 @@ class PLCControler(object):
|
||||
|
||||
def GetConfigurationExtraVariables(self):
|
||||
global_vars = []
|
||||
for var_name, var_type, var_initial in self.GetConfNodeGlobalInstances():
|
||||
tempvar = PLCOpenParser.CreateElement("variable", "globalVars")
|
||||
tempvar.setname(var_name)
|
||||
for global_instance in self.GetConfNodeGlobalInstances():
|
||||
if type(global_instance)==tuple:
|
||||
# usual global without modifier from a CTN or a library
|
||||
var_name, var_type, var_initial = global_instance
|
||||
tempvar = PLCOpenParser.CreateElement("variable", "globalVars")
|
||||
tempvar.setname(var_name)
|
||||
|
||||
tempvartype = PLCOpenParser.CreateElement("type", "variable")
|
||||
if var_type in self.GetBaseTypes():
|
||||
tempvartype.setcontent(PLCOpenParser.CreateElement(
|
||||
var_type.lower()
|
||||
if var_type in ["STRING", "WSTRING"]
|
||||
else var_type, "dataType"))
|
||||
tempvartype = PLCOpenParser.CreateElement("type", "variable")
|
||||
if var_type in self.GetBaseTypes():
|
||||
tempvartype.setcontent(PLCOpenParser.CreateElement(
|
||||
var_type.lower()
|
||||
if var_type in ["STRING", "WSTRING"]
|
||||
else var_type, "dataType"))
|
||||
else:
|
||||
tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType")
|
||||
tempderivedtype.setname(var_type)
|
||||
tempvartype.setcontent(tempderivedtype)
|
||||
tempvar.settype(tempvartype)
|
||||
|
||||
if var_initial != "":
|
||||
value = PLCOpenParser.CreateElement("initialValue", "variable")
|
||||
value.setvalue(var_initial)
|
||||
tempvar.setinitialValue(value)
|
||||
|
||||
global_vars.append(tempvar)
|
||||
else:
|
||||
tempderivedtype = PLCOpenParser.CreateElement("derived", "dataType")
|
||||
tempderivedtype.setname(var_type)
|
||||
tempvartype.setcontent(tempderivedtype)
|
||||
tempvar.settype(tempvartype)
|
||||
# case of varlists from a TC6 library
|
||||
global_vars.append(global_instance)
|
||||
|
||||
if var_initial != "":
|
||||
value = PLCOpenParser.CreateElement("initialValue", "variable")
|
||||
value.setvalue(var_initial)
|
||||
tempvar.setinitialValue(value)
|
||||
|
||||
global_vars.append(tempvar)
|
||||
return global_vars
|
||||
|
||||
# Function that returns the block definition associated to the block type given
|
||||
|
@ -277,21 +277,27 @@ class ProgramGenerator(object):
|
||||
("\n", ())]
|
||||
var_number = 0
|
||||
|
||||
varlists = [(varlist, varlist.getvariable()[:]) for varlist in configuration.getglobalVars()]
|
||||
varlists = configuration.getglobalVars()[:]
|
||||
|
||||
extra_variables = self.Controler.GetConfigurationExtraVariables()
|
||||
extra_global_vars = None
|
||||
if len(extra_variables) > 0 and len(varlists) == 0:
|
||||
extra_global_vars = PLCOpenParser.CreateElement("globalVars", "interface")
|
||||
configuration.setglobalVars([extra_global_vars])
|
||||
varlists = [(extra_global_vars, [])]
|
||||
extra_CTN_globals = []
|
||||
|
||||
for variable in extra_variables:
|
||||
varlists[-1][0].appendvariable(variable)
|
||||
varlists[-1][1].append(variable)
|
||||
for item in extra_variables:
|
||||
if item.getLocalTag() == "globalVars":
|
||||
varlists.append(item)
|
||||
else:
|
||||
extra_CTN_globals.append(item)
|
||||
|
||||
if len(extra_CTN_globals) > 0:
|
||||
extra_varlist = PLCOpenParser.CreateElement("globalVars", "interface")
|
||||
|
||||
for variable in extra_CTN_globals:
|
||||
extra_varlist.appendvariable(variable)
|
||||
|
||||
varlists.append(extra_varlist)
|
||||
|
||||
# Generate any global variable in configuration
|
||||
for varlist, varlist_variables in varlists:
|
||||
for varlist in varlists:
|
||||
variable_type = errorVarTypes.get("VAR_GLOBAL", "var_local")
|
||||
# Generate variable block with modifier
|
||||
config += [(" VAR_GLOBAL", ())]
|
||||
@ -303,7 +309,7 @@ class ProgramGenerator(object):
|
||||
config += [(" NON_RETAIN", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "non_retain"))]
|
||||
config += [("\n", ())]
|
||||
# Generate any variable of this block
|
||||
for var in varlist_variables:
|
||||
for var in varlist.getvariable():
|
||||
vartype_content = var.gettype().getcontent()
|
||||
if vartype_content.getLocalTag() == "derived":
|
||||
var_type = vartype_content.getname()
|
||||
@ -331,12 +337,6 @@ class ProgramGenerator(object):
|
||||
var_number += 1
|
||||
config += [(" END_VAR\n", ())]
|
||||
|
||||
if extra_global_vars is not None:
|
||||
configuration.remove(extra_global_vars)
|
||||
else:
|
||||
for variable in extra_variables:
|
||||
varlists[-1][0].remove(variable)
|
||||
|
||||
# Generate any resource in the configuration
|
||||
for resource in configuration.getresource():
|
||||
config += self.GenerateResource(resource, configuration.getname())
|
||||
@ -458,7 +458,7 @@ class ProgramGenerator(object):
|
||||
return resrce
|
||||
|
||||
# Generate the entire program for current project
|
||||
def GenerateProgram(self, log):
|
||||
def GenerateProgram(self, log, noconfig=False):
|
||||
log("Collecting data types")
|
||||
# Find all data types defined
|
||||
for datatype in self.Project.getdataTypes():
|
||||
@ -480,6 +480,8 @@ class ProgramGenerator(object):
|
||||
for pou_name in list(self.PouComputed.keys()):
|
||||
log("Generate POU %s"%pou_name)
|
||||
self.GeneratePouProgram(pou_name)
|
||||
if noconfig:
|
||||
return
|
||||
# Generate every configurations defined
|
||||
log("Generate Config(s)")
|
||||
for config in self.Project.getconfigurations():
|
||||
@ -1765,7 +1767,7 @@ class PouProgramGenerator(object):
|
||||
return program
|
||||
|
||||
|
||||
def GenerateCurrentProgram(controler, project, errors, warnings):
|
||||
def GenerateCurrentProgram(controler, project, errors, warnings, **kwargs):
|
||||
generator = ProgramGenerator(controler, project, errors, warnings)
|
||||
if hasattr(controler, "logger"):
|
||||
def log(txt):
|
||||
@ -1774,5 +1776,5 @@ def GenerateCurrentProgram(controler, project, errors, warnings):
|
||||
def log(txt):
|
||||
pass
|
||||
|
||||
generator.GenerateProgram(log)
|
||||
generator.GenerateProgram(log,**kwargs)
|
||||
return generator.GetGeneratedProgram()
|
||||
|
@ -424,8 +424,6 @@ class PLCOpenEditorApp(wx.App):
|
||||
self.SetAppName('plcopeneditor')
|
||||
self.ParseCommandLine()
|
||||
InstallLocalRessources(beremiz_dir)
|
||||
if wx.VERSION < (3, 0, 0):
|
||||
wx.InitAllImageHandlers()
|
||||
util.ExceptionHandler.AddExceptHook(version.app_version)
|
||||
self.frame = PLCOpenEditor(None, fileOpen=self.fileOpen)
|
||||
return True
|
||||
|
@ -44,7 +44,7 @@ class POULibrary(object):
|
||||
|
||||
def GetSTCode(self):
|
||||
if not self.program:
|
||||
self.program = self.LibraryControler.GenerateProgram()[0]+"\n"
|
||||
self.program = self.LibraryControler.GenerateProgram(noconfig=True)[0]+"\n"
|
||||
return self.program
|
||||
|
||||
def GetName(self):
|
||||
@ -65,9 +65,14 @@ class POULibrary(object):
|
||||
|
||||
def GlobalInstances(self):
|
||||
"""
|
||||
@return: [(instance_name, instance_type),...]
|
||||
@return: [varlist_object, ...]
|
||||
"""
|
||||
return []
|
||||
varlists = []
|
||||
for configuration in self.LibraryControler.Project.getconfigurations():
|
||||
varlist = configuration.getglobalVars()
|
||||
if len(varlist)>0 :
|
||||
varlists += varlist
|
||||
return varlists
|
||||
|
||||
def FatalError(self, message):
|
||||
""" Raise an exception that will trigger error message intended to
|
||||
|
@ -27,8 +27,9 @@
|
||||
Beremiz Project Controller
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import platform as os_platform
|
||||
import traceback
|
||||
import time
|
||||
from time import localtime
|
||||
@ -36,11 +37,13 @@ import shutil
|
||||
import re
|
||||
import tempfile
|
||||
import hashlib
|
||||
import codecs
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from weakref import WeakKeyDictionary
|
||||
from functools import reduce
|
||||
|
||||
from distutils.dir_util import copy_tree
|
||||
from jinja2 import PackageLoader, Environment, FileSystemLoader
|
||||
|
||||
import wx
|
||||
|
||||
@ -57,7 +60,7 @@ from editors.FileManagementPanel import FileManagementPanel
|
||||
from editors.ProjectNodeEditor import ProjectNodeEditor
|
||||
from editors.IECCodeViewer import IECCodeViewer
|
||||
from editors.DebugViewer import DebugViewer, REFRESH_PERIOD
|
||||
from dialogs import UriEditor, IDManager, ArduinoUploadDialog
|
||||
from dialogs import UriEditor, IDManager, ArduinoUploadDialog, DebuggerRemoteConnDialog
|
||||
from PLCControler import PLCControler
|
||||
from plcopen.structures import IEC_KEYWORDS
|
||||
from plcopen.types_enums import ComputeConfigurationResourceName, ITEM_CONFNODE
|
||||
@ -123,6 +126,7 @@ class Iec2CSettings(object):
|
||||
cmd = "iec2c.exe"
|
||||
elif platform.system() == "Linux":
|
||||
cmd = "iec2c"
|
||||
|
||||
paths = [
|
||||
os.path.join(base_folder, "matiec")
|
||||
]
|
||||
@ -254,6 +258,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
|
||||
self.MandatoryParams = None
|
||||
self._builder = None
|
||||
self._buildType = "simulator"
|
||||
self._connector = None
|
||||
self.DispatchDebugValuesTimer = None
|
||||
self.DebugValuesBuffers = []
|
||||
@ -376,12 +381,16 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
return "PROJECT"
|
||||
|
||||
def GetDefaultTargetName(self):
|
||||
if wx.Platform == '__WXMSW__':
|
||||
return "Win32"
|
||||
elif wx.Platform == '__WXMAC__':
|
||||
return "OSX"
|
||||
else:
|
||||
if sys.platform.startswith('linux'):
|
||||
return "Linux"
|
||||
elif sys.platform.startswith('darwin'):
|
||||
return "OSX"
|
||||
elif sys.platform.startswith('win32'):
|
||||
return "Win32"
|
||||
|
||||
# Fall back to Linux as default target
|
||||
return "Linux"
|
||||
|
||||
|
||||
def GetTarget(self):
|
||||
target = self.BeremizRoot.getTargetType()
|
||||
@ -596,7 +605,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
old_projectfiles_path = self._getProjectFilesPath(
|
||||
from_project_path)
|
||||
if os.path.isdir(old_projectfiles_path):
|
||||
copy_tree(old_projectfiles_path,
|
||||
shutil.copytree(old_projectfiles_path,
|
||||
self._getProjectFilesPath(self.ProjectPath))
|
||||
self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
|
||||
result = self.CTNRequestSave(from_project_path)
|
||||
@ -768,7 +777,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
if self._Generate_PLC_ST():
|
||||
return self._Compile_ST_to_SoftPLC()
|
||||
return False
|
||||
|
||||
|
||||
def RemoveLocatedVariables(self, st_program):
|
||||
modified_program = ""
|
||||
for line in st_program.splitlines(True):
|
||||
@ -781,7 +790,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
else:
|
||||
modified_program += line
|
||||
return modified_program
|
||||
|
||||
|
||||
def _Generate_PLC_ST(self):
|
||||
"""
|
||||
Generate SoftPLC ST/IL/SFC code out of PLCOpenEditor controller, and compile it with IEC2C
|
||||
@ -830,7 +839,10 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
with open(IECcodepath, "w") as plc_file:
|
||||
#plc_file.write(IECCodeContent)
|
||||
#plc_file.write(POUsIECCodeContent)
|
||||
plc_file.write(self.RemoveLocatedVariables(fullPLCProg))
|
||||
if self._buildType == "simulator":
|
||||
plc_file.write(self.RemoveLocatedVariables(fullPLCProg))
|
||||
else:
|
||||
plc_file.write(fullPLCProg)
|
||||
|
||||
hasher = hashlib.md5()
|
||||
hasher.update(IECCodeContent.encode())
|
||||
@ -906,6 +918,8 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
# Now extract C files of stdout
|
||||
C_files = [fname for fname in result.splitlines() if fname[
|
||||
-2:] == ".c" or fname[-2:] == ".C"]
|
||||
# remove those that are not to be compiled because included by others
|
||||
C_files.remove("POUS.c")
|
||||
if not C_files:
|
||||
self.logger.write_error(
|
||||
_("Error : At least one configuration and one resource must be declared in PLC !\n"))
|
||||
@ -914,14 +928,14 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
C_files = [os.path.join(buildpath, filename) for filename in C_files]
|
||||
|
||||
# remove '#include "POUS.c"', compile it separately
|
||||
for c in C_files:
|
||||
with open(c, 'r+') as f:
|
||||
d = ''.join([i for i in f if "POUS.c" not in i])
|
||||
f.seek(0)
|
||||
if "POUS" in c:
|
||||
f.write('#include "POUS.h"\n')
|
||||
f.write(d)
|
||||
f.truncate()
|
||||
#for c in C_files:
|
||||
# with open(c, 'r+') as f:
|
||||
# d = ''.join([i for i in f if "POUS.c" not in i])
|
||||
# f.seek(0)
|
||||
# if "POUS" in c:
|
||||
# f.write('#include "POUS.h"\n')
|
||||
# f.write(d)
|
||||
# f.truncate()
|
||||
|
||||
# prepend beremiz include to configuration header
|
||||
H_files = [fname for fname in result.splitlines() if fname[
|
||||
@ -1079,6 +1093,72 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
|
||||
return True
|
||||
|
||||
def Generate_plc_debug_cvars(self):
|
||||
"""
|
||||
Generate debug C variables out of PLC variable list
|
||||
"""
|
||||
if not self._DbgVariablesList and not self._VariablesList:
|
||||
self.GetIECProgramsAndVariables()
|
||||
type_suffix = {"EXT": "_P_ENUM",
|
||||
"IN" : "_P_ENUM",
|
||||
"MEM": "_O_ENUM",
|
||||
"OUT": "_O_ENUM",
|
||||
"VAR": "_ENUM"}
|
||||
|
||||
#variable_decl_array = [
|
||||
# f"{{&({v['C_path']}), {v['type']}{type_suffix[v['vartype']]}}}"
|
||||
# for v in self._DbgVariablesList
|
||||
#]
|
||||
variable_decl_array = [
|
||||
"{{&({}), {}{}}}".format(
|
||||
v['C_path'], v['type'], type_suffix[v['vartype']]
|
||||
) for v in self._DbgVariablesList
|
||||
]
|
||||
# unique list of types
|
||||
#enum_types = [*{*[f"{v['type']}{type_suffix[v['vartype']]}"
|
||||
# for v in self._DbgVariablesList]}]
|
||||
enum_types = list(set([v['type'] + type_suffix[v['vartype']]
|
||||
for v in self._DbgVariablesList]))
|
||||
types = {"EXT": ("extern __IEC_", "_p"),
|
||||
"IN": ("extern __IEC_", "_p"),
|
||||
"MEM": ("extern __IEC_", "_p"),
|
||||
"OUT": ("extern __IEC_", "_p"),
|
||||
"VAR": ("extern __IEC_", "_t"),
|
||||
"FB": ("extern ", "")}
|
||||
|
||||
#extern_variables_declarations = [
|
||||
# f"{types[v['vartype']][0]}{v['type']}{types[v['vartype']][1]} {v['C_path']};"
|
||||
# for v in self._VariablesList if '.' not in v['C_path']
|
||||
#]
|
||||
extern_variables_declarations = [
|
||||
"{}{}{} {};".format(types[v['vartype']][0], v['type'], types[v['vartype']][1], v['C_path'])
|
||||
for v in self._VariablesList if '.' not in v['C_path']
|
||||
]
|
||||
return variable_decl_array, extern_variables_declarations, enum_types
|
||||
|
||||
def generate_embed_plc_debugger(self):
|
||||
dvars, externs, enums = self.Generate_plc_debug_cvars()
|
||||
if os_platform.system() == 'Windows':
|
||||
template_path = 'editor\\arduino\\src'
|
||||
else:
|
||||
template_path = 'editor/arduino/src'
|
||||
|
||||
base_folder = paths.AbsDir(__file__)
|
||||
loader = FileSystemLoader(
|
||||
os.path.join(base_folder, 'arduino', 'src'))
|
||||
template = Environment(loader=loader).get_template('debug.c.j2')
|
||||
cfile = os.path.join(base_folder, 'arduino', 'src', 'debug.c')
|
||||
with open(cfile, 'w') as f:
|
||||
f.write(template.render(
|
||||
debug={
|
||||
'externs': externs,
|
||||
'vars': dvars,
|
||||
'enums': enums,
|
||||
'types': list(set(a.split("_",1)[0] for a in enums))
|
||||
})
|
||||
)
|
||||
return cfile, ''
|
||||
|
||||
def Generate_plc_debugger(self):
|
||||
"""
|
||||
Generate trace/debug code out of PLC variable list
|
||||
@ -1162,6 +1242,13 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
"init_calls": "\n",
|
||||
"cleanup_calls": "\n"
|
||||
}
|
||||
|
||||
located_var_counter = 0
|
||||
for iec_var in self.PLCGeneratedLocatedVars:
|
||||
plc_main_code += 'IEC_' + iec_var["IEC_TYPE"] + ' var' + str(located_var_counter) + ';\n'
|
||||
plc_main_code += 'IEC_' + iec_var["IEC_TYPE"] + ' *' + iec_var["NAME"] + ' = &var' + str(located_var_counter) + ';\n'
|
||||
located_var_counter += 1
|
||||
|
||||
plc_main_code += targets.GetTargetCode(
|
||||
self.GetTarget().getcontent().getLocalTag())
|
||||
plc_main_code += targets.GetCode("plc_main_tail.c")
|
||||
@ -1235,7 +1322,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
LibCFilesAndCFLAGS, LibLDFLAGS, LibExtraFiles = self.GetLibrariesCCode(
|
||||
buildpath)
|
||||
except UserAddressedException as e:
|
||||
self.logger.write_error(e.message)
|
||||
self.logger.write_error(str(e))
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.write_error(
|
||||
@ -1249,7 +1336,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
buildpath,
|
||||
self.PLCGeneratedLocatedVars)
|
||||
except UserAddressedException as e:
|
||||
self.logger.write_error(e.message)
|
||||
self.logger.write_error(str(e))
|
||||
return False
|
||||
except Exception:
|
||||
self.logger.write_error(
|
||||
@ -1360,7 +1447,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
|
||||
def _OpenView(self, name=None, onlyopened=False):
|
||||
if name == "IEC code":
|
||||
if self._IECCodeView is None:
|
||||
if not self._IECCodeView:
|
||||
plc_file = self._getIECcodepath()
|
||||
|
||||
self._IECCodeView = IECCodeViewer(
|
||||
@ -1382,7 +1469,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
return self._IECCodeView
|
||||
|
||||
elif name == "IEC raw code":
|
||||
if self._IECRawCodeView is None:
|
||||
if not self._IECRawCodeView:
|
||||
controler = MiniTextControler(self._getIECrawcodepath(), self)
|
||||
|
||||
self._IECRawCodeView = IECCodeViewer(
|
||||
@ -1399,7 +1486,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
return self._IECRawCodeView
|
||||
|
||||
elif name == "Project Files":
|
||||
if self._ProjectFilesView is None:
|
||||
if not self._ProjectFilesView:
|
||||
self._ProjectFilesView = FileManagementPanel(
|
||||
self.AppFrame.TabsOpened, self, name, self._getProjectFilesPath(), True)
|
||||
|
||||
@ -1488,7 +1575,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
|
||||
def UpdateButtons(self):
|
||||
wx.CallAfter(self._UpdateButtons)
|
||||
|
||||
|
||||
def _BlockButtons(self):
|
||||
self.EnableMethod("_Run", False)
|
||||
if self.AppFrame is not None and not self.UpdateMethodsFromPLCStatus():
|
||||
@ -1519,8 +1606,10 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
"_Disconnect": False,
|
||||
"_showIECcode": False,
|
||||
"_showIDManager": False,
|
||||
"_Repair": False,
|
||||
"_generateOpenPLC": True,
|
||||
"_generateArduino": True
|
||||
"_generateArduino": True,
|
||||
"_debugPLC" : True
|
||||
}
|
||||
|
||||
MethodsFromStatus = {
|
||||
@ -1530,31 +1619,35 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
"_Connect": False,
|
||||
"_Disconnect": False,
|
||||
"_generateOpenPLC": True,
|
||||
"_generateArduino": True},
|
||||
"_generateArduino": True,
|
||||
"_debugPLC": False},
|
||||
PlcStatus.Stopped: {"_Run": True,
|
||||
"_Stop": False,
|
||||
"_Transfer": False,
|
||||
"_Connect": False,
|
||||
"_Disconnect": False,
|
||||
"_Repair": False,
|
||||
"_generateOpenPLC": True,
|
||||
"_generateArduino": True},
|
||||
PlcStatus.Empty: {"_Transfer": True,
|
||||
"_generateArduino": True,
|
||||
"_debugPLC": True},
|
||||
PlcStatus.Empty: {"_Transfer": False,
|
||||
"_Connect": False,
|
||||
"_Disconnect": True},
|
||||
PlcStatus.Broken: {"_Connect": False,
|
||||
"_Repair": False,
|
||||
"_Disconnect": True},
|
||||
PlcStatus.Disconnected: {},
|
||||
}
|
||||
|
||||
def UpdateMethodsFromPLCStatus(self):
|
||||
updated = False
|
||||
status = None
|
||||
status = PlcStatus.Disconnected
|
||||
if self._connector is not None:
|
||||
PLCstatus = self._connector.GetPLCstatus()
|
||||
if PLCstatus is not None:
|
||||
status, log_count = PLCstatus
|
||||
self.UpdatePLCLog(log_count)
|
||||
if status is None:
|
||||
if status == PlcStatus.Disconnected:
|
||||
self._SetConnector(None, False)
|
||||
status = PlcStatus.Disconnected
|
||||
if self.previous_plcstate != status:
|
||||
@ -1567,15 +1660,11 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
if self.AppFrame is not None:
|
||||
updated = True
|
||||
self.AppFrame.RefreshStatusToolBar()
|
||||
if status == PlcStatus.Disconnected:
|
||||
self.AppFrame.ConnectionStatusBar.SetStatusText(
|
||||
_(status), 1)
|
||||
self.AppFrame.ConnectionStatusBar.SetStatusText('', 2)
|
||||
else:
|
||||
self.AppFrame.ConnectionStatusBar.SetStatusText(
|
||||
_("Connected to URI: %s") % self.BeremizRoot.getURI_location().strip(), 1)
|
||||
self.AppFrame.ConnectionStatusBar.SetStatusText(
|
||||
_(status), 2)
|
||||
texts = [_(PlcStatus.Disconnected), ''] \
|
||||
if status == PlcStatus.Disconnected or self._connector is None else \
|
||||
[_("Connected to URI: %s") % self.BeremizRoot.getURI_location().strip(), _(status)]
|
||||
for i,txt in enumerate(texts):
|
||||
self.AppFrame.ConnectionStatusBar.SetStatusText(txt, i+1)
|
||||
return updated
|
||||
|
||||
def ShowPLCProgress(self, status="", progress=0):
|
||||
@ -1858,6 +1947,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
self.BlockButtons()
|
||||
# Clean build folder
|
||||
self._Clean()
|
||||
self._buildType = "simulator"
|
||||
# Build Project
|
||||
if (self._Build() is False):
|
||||
self.UnblockButtons()
|
||||
@ -1866,6 +1956,8 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
if (self._Connect() is False):
|
||||
self.UnblockButtons()
|
||||
return success
|
||||
#Set debugger type
|
||||
self._connector.SetDebuggerType('simulation')
|
||||
# Transfer PLC program
|
||||
if (self._Transfer() is False):
|
||||
self.UnblockButtons()
|
||||
@ -1887,7 +1979,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
"""
|
||||
if self._connector is not None and not self._connector.StopPLC():
|
||||
self.logger.write_error(_("Couldn't stop PLC !\n"))
|
||||
|
||||
|
||||
self._Disconnect()
|
||||
|
||||
# debugthread should die on his own
|
||||
@ -1976,7 +2068,6 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
if self._connector is None:
|
||||
# Oups.
|
||||
self.logger.write_error(_("Connection failed to %s!\n") % uri)
|
||||
success = False
|
||||
else:
|
||||
self.CompareLocalAndRemotePLC()
|
||||
|
||||
@ -2090,7 +2181,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
|
||||
wx.CallAfter(self.UpdateMethodsFromPLCStatus)
|
||||
return success
|
||||
|
||||
|
||||
def _generateOpenPLC(self):
|
||||
self._Clean()
|
||||
if (self._Build() is True):
|
||||
@ -2113,14 +2204,36 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
|
||||
def _generateArduino(self):
|
||||
self._Clean()
|
||||
self._buildType = "remote"
|
||||
if (self._Build() is True):
|
||||
# Get MD5 of the plc_debugger.c file and store that on target
|
||||
debuggerLocation = None
|
||||
CTRoot = self.GetCTRoot()
|
||||
for location, cfiles, calls in CTRoot.LocationCFilesAndCFLAGS:
|
||||
if cfiles:
|
||||
for file, flag in cfiles:
|
||||
if "plc_debugger.c" in file:
|
||||
debuggerLocation = file
|
||||
break
|
||||
|
||||
if debuggerLocation is None:
|
||||
self.logger.write_error("Error building project: Debugger file is null\n")
|
||||
return
|
||||
MD5 = hashlib.md5(open(debuggerLocation, "rb").read()).hexdigest()
|
||||
if MD5 is None:
|
||||
self.logger.write_error("Error building project: md5 object is null\n")
|
||||
return
|
||||
self.logger.write("Build MD5: ")
|
||||
self.logger.write(MD5)
|
||||
|
||||
f = open(self._getIECgeneratedcodepath(), 'r')
|
||||
program = f.read()
|
||||
f.close()
|
||||
dialog = ArduinoUploadDialog.ArduinoUploadDialog(
|
||||
self.AppFrame, program)
|
||||
|
||||
self.generate_embed_plc_debugger()
|
||||
dialog = ArduinoUploadDialog.ArduinoUploadDialog(self.AppFrame, program, MD5)
|
||||
dialog.ShowModal()
|
||||
|
||||
|
||||
def _Repair(self):
|
||||
dialog = wx.MessageDialog(
|
||||
self.AppFrame,
|
||||
@ -2132,6 +2245,82 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
if answer == wx.ID_YES:
|
||||
self._connector.RepairPLC()
|
||||
|
||||
def _debugPLC(self):
|
||||
self.BlockButtons()
|
||||
#Clean build folder
|
||||
self._Clean()
|
||||
self._buildType = "remote"
|
||||
#Build Project
|
||||
if (self._Build() is False):
|
||||
self.UnblockButtons()
|
||||
return
|
||||
#Connect to target
|
||||
if (self._Connect() is False):
|
||||
self.UnblockButtons()
|
||||
return
|
||||
|
||||
#Set debugger type
|
||||
self._connector.SetDebuggerType('remote')
|
||||
dialog = DebuggerRemoteConnDialog.DebuggerRemoteConnDialog(self.AppFrame, self._connector)
|
||||
ret = dialog.ShowModal()
|
||||
if ret > 1:
|
||||
self.logger.write_warning('User dismissed connection\n')
|
||||
self.logger.write('Stopping debugger...\n')
|
||||
self._Stop()
|
||||
|
||||
elif ret == -1:
|
||||
self.logger.write_warning('Invalid parameters\n')
|
||||
self.logger.write('Stopping debugger...\n')
|
||||
self._Stop()
|
||||
elif ret == 0:
|
||||
# Connect to remote target
|
||||
self._connector.DisconnectRemoteTarget() # Make sure target is disconnected first
|
||||
remoteTarget = self._connector.ConnectRemoteTarget()
|
||||
if remoteTarget == None or remoteTarget == False:
|
||||
self.logger.write_error("Error connecting to target board. Make sure your board is running OpenPLC Runtime with debug enabled, and that your connection settings match your board parameters.\n")
|
||||
self._Stop()
|
||||
return
|
||||
# Get MD5 of the plc_debugger.c file and compare with the one on target
|
||||
debuggerLocation = None
|
||||
CTRoot = self.GetCTRoot()
|
||||
for location, cfiles, calls in CTRoot.LocationCFilesAndCFLAGS:
|
||||
if cfiles:
|
||||
for file, flag in cfiles:
|
||||
if "plc_debugger.c" in file:
|
||||
debuggerLocation = file
|
||||
break
|
||||
|
||||
if debuggerLocation is None:
|
||||
self.logger.write_error("Error building project: Debugger file is null\n")
|
||||
self._Stop()
|
||||
return
|
||||
MD5 = hashlib.md5(open(debuggerLocation, "rb").read()).hexdigest()
|
||||
if MD5 is None:
|
||||
self.logger.write_error("Error building project: md5 object is null\n")
|
||||
return
|
||||
|
||||
if self._connector.MatchMD5(MD5) == True:
|
||||
self.logger.write("Program matches PLC MD5\n")
|
||||
#Transfer PLC program
|
||||
if (self._Transfer() is False):
|
||||
self.UnblockButtons()
|
||||
return
|
||||
#Run
|
||||
if self.GetIECProgramsAndVariables():
|
||||
self._connector.StartPLC()
|
||||
self.logger.write(_("Starting PLC\n"))
|
||||
self._connect_debug()
|
||||
else:
|
||||
self.logger.write_error(_("Couldn't start PLC !\n"))
|
||||
self.UnblockButtons()
|
||||
wx.CallAfter(self.UpdateMethodsFromPLCStatus)
|
||||
else:
|
||||
self.logger.write_error("This project does not match the program running on target. Upload the project to target and try again.\n")
|
||||
self._Stop()
|
||||
else:
|
||||
print('Invalid return from remote settings dialog')
|
||||
self._Stop()
|
||||
|
||||
StatusMethods = [
|
||||
{
|
||||
"bitmap": "Build",
|
||||
@ -2158,7 +2347,7 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
{
|
||||
"bitmap": "Stop",
|
||||
"name": _("Stop"),
|
||||
"tooltip": _("Stop PLC Simulation"),
|
||||
"tooltip": _("Stop PLC"),
|
||||
"method": "_Stop",
|
||||
"shown": False,
|
||||
},
|
||||
@ -2218,6 +2407,13 @@ class ProjectController(ConfigTreeNode, PLCControler):
|
||||
"method": "_generateArduino",
|
||||
"shown": True,
|
||||
},
|
||||
{
|
||||
"bitmap": "Debug",
|
||||
"name": _("Debug PLC"),
|
||||
"tooltip": _("Live debug remote PLC"),
|
||||
"method": "_debugPLC",
|
||||
"shown": True,
|
||||
},
|
||||
]
|
||||
|
||||
ConfNodeMethods = [
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!---
|
||||
[](https://beremiz.readthedocs.io)
|
||||
-->
|
||||
[](https://github.com/beremiz/beremiz/actions/workflows/run_tests_in_docker.yml)
|
||||
|
||||
# Beremiz #
|
||||
|
||||
@ -41,34 +42,17 @@ Searchable archive using search engine of your choice is available [here](http:/
|
||||
|
||||
## Build on Linux (developer setup) ##
|
||||
|
||||
### Prerequisites (Ubuntu/Debian) :
|
||||
### System prerequisites (Ubuntu 22.04) :
|
||||
```
|
||||
sudo apt-get install build-essential bison flex autoconf
|
||||
sudo apt-get install python2-dev libpython2.7-dev libgtk-3-dev libssl-dev libgl1-mesa-dev libglu1-mesa-dev python-setuptools
|
||||
|
||||
python2 -m pip install \
|
||||
future \
|
||||
matplotlib \
|
||||
msgpack_python \
|
||||
u-msgpack-python \
|
||||
zeroconf2 \
|
||||
enum34 \
|
||||
pyro \
|
||||
sslpsk \
|
||||
posix_spawn \
|
||||
twisted \
|
||||
nevow \
|
||||
autobahn \
|
||||
click \
|
||||
opcua \
|
||||
pycountry \
|
||||
fonttools \
|
||||
Brotli \
|
||||
lxml==4.5.0 \
|
||||
wxPython==4.1.1
|
||||
|
||||
# install required system packages as root
|
||||
sudo apt-get install \
|
||||
build-essential automake flex bison mercurial \
|
||||
libgtk-3-dev libgl1-mesa-dev libglu1-mesa-dev \
|
||||
libpython3.10-dev libssl-dev \
|
||||
python3.10 virtualenv cmake git mercurial
|
||||
```
|
||||
|
||||
|
||||
### Prepare build directory
|
||||
|
||||
All commands hereafter assume that selected directory to contain all downloaded source code and build results is `~/Beremiz`
|
||||
@ -94,6 +78,16 @@ git clone https://github.com/beremiz/beremiz
|
||||
git clone https://github.com/beremiz/matiec
|
||||
```
|
||||
|
||||
### Python prerequisites (virtualenv) :
|
||||
```
|
||||
# setup isolated python environment
|
||||
virtualenv ~/Beremiz/venv
|
||||
|
||||
# install required python packages
|
||||
~/Beremiz/venv/bin/pip install -r ~/Beremiz/beremiz/requirements.txt
|
||||
|
||||
```
|
||||
|
||||
### Build MatIEC compiler
|
||||
|
||||
```
|
||||
@ -109,8 +103,12 @@ Only needed for CANopen support. Please read CanFestival manual to choose CAN in
|
||||
|
||||
```
|
||||
cd ~/Beremiz
|
||||
hg clone http://hg.beremiz.org/CanFestival-3
|
||||
cd ~/Beremiz/CanFestival-3
|
||||
|
||||
hg clone http://hg.beremiz.org/canfestival
|
||||
# -- or --
|
||||
git clone https://github.com/beremiz/canfestival
|
||||
|
||||
cd ~/Beremiz/canfestival
|
||||
./configure --can=virtual
|
||||
make
|
||||
```
|
||||
@ -121,7 +119,11 @@ Only needed for Modbus support.
|
||||
|
||||
```
|
||||
cd ~/Beremiz
|
||||
hg clone https://hg.beremiz.org/Modbus
|
||||
|
||||
hg clone http://hg.beremiz.org/Modbus
|
||||
# -- or --
|
||||
git clone https://github.com/beremiz/Modbus
|
||||
|
||||
cd ~/Beremiz/Modbus
|
||||
make
|
||||
```
|
||||
@ -140,8 +142,7 @@ make MAKE_DEFINE='-fPIC' MY_BACNET_DEFINES='-DPRINT_ENABLED=1 -DBACAPP_ALL -DBAC
|
||||
### Launch Beremiz IDE
|
||||
|
||||
```
|
||||
cd ~/Beremiz/beremiz
|
||||
python Beremiz.py
|
||||
~/Beremiz/venv/python ~/Beremiz/beremiz/Beremiz.py
|
||||
```
|
||||
|
||||
## Run standalone Beremiz runtime ##
|
||||
@ -150,7 +151,7 @@ python Beremiz.py
|
||||
|
||||
```
|
||||
mkdir ~/beremiz_runtime_workdir
|
||||
python Beremiz_service.py -p 61194 -i localhost -x 0 -a 1 ~/beremiz_runtime_workdir
|
||||
~/Beremiz/venv/python ~/Beremiz/beremiz/Beremiz_service.py -p 61194 -i localhost -x 0 -a 1 ~/beremiz_runtime_workdir
|
||||
```
|
||||
|
||||
To connect IDE with runtime, enter target location URI in project's settings (project->Config->BeremizRoot/URI_location) pointed to your running Beremiz service in this case :
|
||||
|
BIN
editor/arduino/.DS_Store
vendored
BIN
editor/arduino/.DS_Store
vendored
Binary file not shown.
@ -22,6 +22,7 @@ def scrollToEnd(txtCtrl):
|
||||
|
||||
def runCommand(command):
|
||||
cmd_response = None
|
||||
|
||||
try:
|
||||
cmd_response = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
|
||||
#cmd_response = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
|
||||
@ -55,11 +56,116 @@ def saveHals(halObj):
|
||||
f.write(jsonStr)
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
def readBoardInstalled(platform):
|
||||
hals = loadHals()
|
||||
cli_command = ''
|
||||
if os_platform.system() == 'Windows':
|
||||
cli_command = 'editor\\arduino\\bin\\arduino-cli-w32'
|
||||
elif os_platform.system() == 'Darwin':
|
||||
cli_command = 'editor/arduino/bin/arduino-cli-mac'
|
||||
else:
|
||||
cli_command = 'editor/arduino/bin/arduino-cli-l64'
|
||||
for board in hals:
|
||||
if hals[board]['platform'] == platform:
|
||||
board_details = runCommand(cli_command + ' board details -b ' + platform)
|
||||
board_details = board_details.splitlines()
|
||||
board_version = '0'
|
||||
for line in board_details:
|
||||
if "Board version:" in line:
|
||||
board_version = line.split('Board version:')[1]
|
||||
board_version = ''.join(board_version.split()) #remove white spaces
|
||||
hals[board]['version'] = board_version
|
||||
saveHals(hals)
|
||||
break
|
||||
|
||||
def readBoardsInstalled():
|
||||
hasToSave = False
|
||||
hals = loadHals()
|
||||
cli_command = ''
|
||||
if os_platform.system() == 'Windows':
|
||||
cli_command = 'editor\\arduino\\bin\\arduino-cli-w32'
|
||||
elif os_platform.system() == 'Darwin':
|
||||
cli_command = 'editor/arduino/bin/arduino-cli-mac'
|
||||
else:
|
||||
cli_command = 'editor/arduino/bin/arduino-cli-l64'
|
||||
boardInstalled = runCommand(cli_command + ' board listall')
|
||||
try:
|
||||
for board in hals:
|
||||
if board in boardInstalled:
|
||||
platform = hals[board]['platform']
|
||||
board_details = runCommand(cli_command + ' board details -b ' + platform)
|
||||
board_details = board_details.splitlines()
|
||||
board_version = '0'
|
||||
for line in board_details:
|
||||
if "Board version:" in line:
|
||||
board_version = line.split('Board version:')[1]
|
||||
board_version = ''.join(board_version.split()) #remove white spaces
|
||||
hals[board]['version'] = board_version
|
||||
hasToSave = True
|
||||
break
|
||||
if board not in boardInstalled:
|
||||
hals[board]['version'] = '0'
|
||||
hasToSave = True
|
||||
|
||||
if hasToSave:
|
||||
saveHals(hals)
|
||||
except:
|
||||
pass
|
||||
|
||||
def setLangArduino():
|
||||
cli_command = ''
|
||||
if os_platform.system() == 'Windows':
|
||||
cli_command = 'editor\\arduino\\bin\\arduino-cli-w32'
|
||||
elif os_platform.system() == 'Darwin':
|
||||
cli_command = 'editor/arduino/bin/arduino-cli-mac'
|
||||
else:
|
||||
cli_command = 'editor/arduino/bin/arduino-cli-l64'
|
||||
|
||||
# Initialize arduino-cli config - if it hasn't been initialized yet
|
||||
runCommand(cli_command + ' config init')
|
||||
|
||||
# Disabling this as it is causing more problems than solutions
|
||||
"""
|
||||
dump = runCommand(cli_command + ' config dump')
|
||||
dump = dump.splitlines()
|
||||
arduino_dir = ''
|
||||
for line in dump:
|
||||
if 'data:' in line:
|
||||
#get the directory of arduino ide
|
||||
arduino_dir = line.split('data:')[1]
|
||||
arduino_dir = ''.join(arduino_dir.split()) #remove white spaces
|
||||
|
||||
if 'locale:' in line:
|
||||
if 'en' not in line:
|
||||
#remove the line from dump variable
|
||||
dump.remove(line)
|
||||
else:
|
||||
return #already set to english
|
||||
|
||||
dump.append('locale: en')
|
||||
dump = '\n'.join(dump)
|
||||
#write on the config file all the lines# Open the file in write mode
|
||||
with open(arduino_dir + '/arduino-cli.yaml', 'w') as f:
|
||||
# Write the variable to the file
|
||||
f.write(str(dump))
|
||||
|
||||
#runCommand('echo ' + dump + ' > ' + arduino_dir + '/arduino-cli.yaml')
|
||||
"""
|
||||
|
||||
|
||||
def build(st_file, platform, source_file, port, txtCtrl, update_subsystem):
|
||||
global compiler_logs
|
||||
compiler_logs = ''
|
||||
compiler_logs = ''
|
||||
setLangArduino()
|
||||
|
||||
#check if platform is installed in the arduino ide
|
||||
readBoardInstalled(platform)
|
||||
|
||||
hals = loadHals()
|
||||
|
||||
|
||||
|
||||
|
||||
#Check if board is installed
|
||||
board_installed = False
|
||||
@ -126,6 +232,11 @@ def build(st_file, platform, source_file, port, txtCtrl, update_subsystem):
|
||||
=> arduino-cli board details -fqbn [board fqbn]
|
||||
"""
|
||||
|
||||
# Initialize arduino-cli config - if it hasn't been initialized yet
|
||||
compiler_logs += runCommand(cli_command + ' config init')
|
||||
wx.CallAfter(txtCtrl.SetValue, compiler_logs)
|
||||
wx.CallAfter(scrollToEnd, txtCtrl)
|
||||
|
||||
# Setup boards - remove 3rd party boards to re-add them later since we don't know if they're there or not
|
||||
compiler_logs += runCommand(
|
||||
cli_command + ' config remove board_manager.additional_urls \
|
||||
@ -134,6 +245,8 @@ https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32
|
||||
https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json \
|
||||
https://raw.githubusercontent.com/CONTROLLINO-PLC/CONTROLLINO_Library/master/Boards/package_ControllinoHardware_index.json \
|
||||
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json \
|
||||
https://facts-engineering.gitlab.io/facts-open-source/p1am/beta_file_hosting/package_productivity-P1AM_200-boardmanagermodule_index.json \
|
||||
https://raw.githubusercontent.com/VEA-SRL/IRUINO_Library/main/package_vea_index.json \
|
||||
"2>&1"')
|
||||
wx.CallAfter(txtCtrl.SetValue, compiler_logs)
|
||||
wx.CallAfter(scrollToEnd, txtCtrl)
|
||||
@ -145,7 +258,9 @@ https://arduino.esp8266.com/stable/package_esp8266com_index.json \
|
||||
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json \
|
||||
https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json \
|
||||
https://raw.githubusercontent.com/CONTROLLINO-PLC/CONTROLLINO_Library/master/Boards/package_ControllinoHardware_index.json \
|
||||
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json')
|
||||
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json \
|
||||
https://facts-engineering.gitlab.io/facts-open-source/p1am/beta_file_hosting/package_productivity-P1AM_200-boardmanagermodule_index.json \
|
||||
https://raw.githubusercontent.com/VEA-SRL/IRUINO_Library/main/package_vea_index.json')
|
||||
wx.CallAfter(txtCtrl.SetValue, compiler_logs)
|
||||
wx.CallAfter(scrollToEnd, txtCtrl)
|
||||
|
||||
@ -172,34 +287,21 @@ OneWire \
|
||||
DallasTemperature \
|
||||
P1AM \
|
||||
CONTROLLINO \
|
||||
"Adafruit ADS1X15" \
|
||||
PubSubClient \
|
||||
ArduinoJson \
|
||||
arduinomqttclient \
|
||||
RP2040_PWM')
|
||||
RP2040_PWM \
|
||||
AVR_PWM \
|
||||
megaAVR_PWM \
|
||||
ESP32_FastPWM \
|
||||
SAMD_PWM \
|
||||
SAMDUE_PWM \
|
||||
Portenta_H7_PWM \
|
||||
STM32_PWM')
|
||||
wx.CallAfter(txtCtrl.SetValue, compiler_logs)
|
||||
wx.CallAfter(scrollToEnd, txtCtrl)
|
||||
|
||||
# Read back installed core version
|
||||
board_details = runCommand(cli_command + ' board details -b ' + platform)
|
||||
board_details = board_details.splitlines()
|
||||
board_version = '0'
|
||||
for line in board_details:
|
||||
if " Error getting board details" in line:
|
||||
compiler_logs += 'Error installing support for board ' + platform
|
||||
wx.CallAfter(txtCtrl.SetValue, compiler_logs)
|
||||
wx.CallAfter(scrollToEnd, txtCtrl)
|
||||
return
|
||||
if "Board version:" in line:
|
||||
board_version = line.split('Board version:')[1]
|
||||
board_version = ''.join(board_version.split()) #remove white spaces
|
||||
break
|
||||
|
||||
# Update version for all platforms using this core
|
||||
for board in hals:
|
||||
if hals[board]['core'] == core:
|
||||
hals[board]['version'] = board_version
|
||||
saveHals(hals)
|
||||
readBoardsInstalled()
|
||||
|
||||
# Generate C files
|
||||
compiler_logs += "Compiling .st file...\n"
|
||||
|
BIN
editor/arduino/examples/.DS_Store
vendored
BIN
editor/arduino/examples/.DS_Store
vendored
Binary file not shown.
Binary file not shown.
@ -14,10 +14,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
unsigned long __tick = 0;
|
||||
uint32_t __tick = 0;
|
||||
|
||||
unsigned long scan_cycle;
|
||||
unsigned long timer_ms = 0;
|
||||
unsigned long timer_us = 0;
|
||||
|
||||
#include "arduino_libs.h"
|
||||
|
||||
@ -44,29 +44,8 @@ int availableMemory(char *msg)
|
||||
|
||||
void setupCycleDelay(unsigned long long cycle_time)
|
||||
{
|
||||
scan_cycle = (uint32_t)(cycle_time/1000000);
|
||||
timer_ms = millis() + scan_cycle;
|
||||
}
|
||||
|
||||
void cycleDelay()
|
||||
{
|
||||
//just wait until it is time to start a new cycle
|
||||
#ifdef MODBUS_ENABLED
|
||||
syncModbusBuffers();
|
||||
#endif
|
||||
while(timer_ms > millis())
|
||||
{
|
||||
#ifdef MODBUS_ENABLED
|
||||
//Only run Modbus task again if we have at least 100ms gap until the next cycle
|
||||
if (timer_ms - millis() >= 100)
|
||||
{
|
||||
syncModbusBuffers();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
//noInterrupts();
|
||||
timer_ms += scan_cycle; //set timer for the next scan cycle
|
||||
//interrupts();
|
||||
scan_cycle = (uint32_t)(cycle_time/1000);
|
||||
timer_us = micros() + scan_cycle;
|
||||
}
|
||||
|
||||
void setup()
|
||||
@ -105,9 +84,9 @@ void setup()
|
||||
if (pinMask_AOUT[i] == MBSERIAL_TXPIN)
|
||||
pinMask_AOUT[i] = 255;
|
||||
}
|
||||
mbconfig_serial_iface(&MBSERIAL_IFACE, MBSERIAL_BAUD, MBSERIAL_TXPIN);
|
||||
mbconfig_serial_iface((HardwareSerial *)&MBSERIAL_IFACE, MBSERIAL_BAUD, MBSERIAL_TXPIN);
|
||||
#else
|
||||
mbconfig_serial_iface(&MBSERIAL_IFACE, MBSERIAL_BAUD, -1);
|
||||
mbconfig_serial_iface((HardwareSerial *)&MBSERIAL_IFACE, MBSERIAL_BAUD, -1);;
|
||||
#endif
|
||||
|
||||
//Set the Slave ID
|
||||
@ -176,7 +155,8 @@ void mapEmptyBuffers()
|
||||
}
|
||||
}
|
||||
}
|
||||
void syncModbusBuffers()
|
||||
|
||||
void modbusTask()
|
||||
{
|
||||
//Sync OpenPLC Buffers with Modbus Buffers
|
||||
for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++)
|
||||
@ -229,18 +209,41 @@ void syncModbusBuffers()
|
||||
}
|
||||
#endif
|
||||
|
||||
void loop()
|
||||
void plcCycleTask()
|
||||
{
|
||||
updateInputBuffers();
|
||||
|
||||
#ifdef MODBUS_ENABLED
|
||||
syncModbusBuffers();
|
||||
#endif
|
||||
|
||||
config_run__(__tick++);
|
||||
config_run__(__tick++); //PLC Logic
|
||||
updateOutputBuffers();
|
||||
updateTime();
|
||||
|
||||
//sleep until next scan cycle
|
||||
cycleDelay();
|
||||
}
|
||||
|
||||
void scheduler()
|
||||
{
|
||||
// Run tasks round robin - higher priority first
|
||||
|
||||
plcCycleTask();
|
||||
|
||||
#ifdef MODBUS_ENABLED
|
||||
modbusTask();
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
scheduler();
|
||||
|
||||
//set timer for the next scan cycle
|
||||
timer_us += scan_cycle;
|
||||
|
||||
//sleep until next scan cycle (run lower priority tasks if time permits)
|
||||
while(timer_us > micros())
|
||||
{
|
||||
#ifdef MODBUS_ENABLED
|
||||
//Only run Modbus task again if we have at least 10ms gap until the next cycle
|
||||
if (timer_us - micros() >= 10000)
|
||||
{
|
||||
modbusTask();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -129,11 +129,6 @@ void mbconfig_serial_iface(HardwareSerial* port, long baud, int txPin)
|
||||
#ifdef MBTCP
|
||||
void mbconfig_ethernet_iface(uint8_t *mac, uint8_t *ip, uint8_t *dns, uint8_t *gateway, uint8_t *subnet)
|
||||
{
|
||||
//Serial.begin(115200);
|
||||
//while (!Serial) {
|
||||
// ; // wait for serial port to connect. Needed for native USB port only
|
||||
//}
|
||||
//Serial.println("Serial ready!");
|
||||
#ifdef MBTCP_ETHERNET
|
||||
if (ip == NULL)
|
||||
Ethernet.begin(mac);
|
||||
@ -157,7 +152,6 @@ void mbconfig_ethernet_iface(uint8_t *mac, uint8_t *ip, uint8_t *dns, uint8_t *g
|
||||
#elif defined(BOARD_PORTENTA)
|
||||
if (ip != NULL && subnet != NULL && gateway != NULL)
|
||||
{
|
||||
Serial.println("Trying to start with a fixed IP");
|
||||
WiFi.config(IPAddress(ip), IPAddress(subnet), IPAddress(gateway));
|
||||
}
|
||||
#else
|
||||
@ -175,17 +169,12 @@ void mbconfig_ethernet_iface(uint8_t *mac, uint8_t *ip, uint8_t *dns, uint8_t *g
|
||||
#endif
|
||||
WiFi.begin(MBTCP_SSID, MBTCP_PWD);
|
||||
int num_tries = 0;
|
||||
Serial.print("Connecting to SSID");
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(500);
|
||||
num_tries++;
|
||||
if (num_tries == 10) break;
|
||||
}
|
||||
Serial.print("IP: ");
|
||||
IPAddress myIP = WiFi.localIP();
|
||||
Serial.println(myIP);
|
||||
#endif
|
||||
mb_server.begin();
|
||||
}
|
||||
@ -420,11 +409,16 @@ void handle_serial()
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void process_mbpacket()
|
||||
{
|
||||
uint8_t fcode = mb_frame[1];
|
||||
uint16_t field1 = (uint16_t)mb_frame[2] << 8 | (uint16_t)mb_frame[3];
|
||||
uint16_t field2 = (uint16_t)mb_frame[4] << 8 | (uint16_t)mb_frame[5];
|
||||
uint8_t flag = mb_frame[4];
|
||||
uint16_t len = (uint16_t)mb_frame[5] << 8 | (uint16_t)mb_frame[6];
|
||||
void *value = &mb_frame[7];
|
||||
void *endianness_check = &mb_frame[2];
|
||||
|
||||
switch (fcode)
|
||||
{
|
||||
@ -468,6 +462,29 @@ void process_mbpacket()
|
||||
writeMultipleCoils(field1, field2, mb_frame[6]);
|
||||
break;
|
||||
|
||||
case MB_FC_DEBUG_INFO:
|
||||
debugInfo();
|
||||
break;
|
||||
|
||||
case MB_FC_DEBUG_GET:
|
||||
//field1 = startidx, field2 = endidx
|
||||
debugGetTrace(field1, field2);
|
||||
break;
|
||||
|
||||
case MB_FC_DEBUG_GET_LIST:
|
||||
//field1 = numIndexes
|
||||
debugGetTraceList(field1, &mb_frame[4]);
|
||||
break;
|
||||
|
||||
case MB_FC_DEBUG_SET:
|
||||
//field1 = varidx
|
||||
debugSetTrace(field1, flag, len, value);
|
||||
break;
|
||||
|
||||
case MB_FC_DEBUG_GET_MD5:
|
||||
debugGetMd5(endianness_check);
|
||||
break;
|
||||
|
||||
default:
|
||||
exceptionResponse(fcode, MB_EX_ILLEGAL_FUNCTION);
|
||||
}
|
||||
@ -787,6 +804,282 @@ void writeMultipleCoils(uint16_t startreg, uint16_t numoutputs, uint16_t bytecou
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a Modbus response frame for the DEBUG_INFO function code.
|
||||
*
|
||||
* This function constructs a Modbus response frame for the DEBUG_INFO function code.
|
||||
* The response frame includes the number of variables defined in the PLC program.
|
||||
*
|
||||
* Modbus Response Frame (DEBUG_INFO):
|
||||
* +-----+-------+-------+
|
||||
* | MB | Count | Count |
|
||||
* | FC | | |
|
||||
* +-----+-------+-------+
|
||||
* |0x41 | High | Low |
|
||||
* | | Byte | Byte |
|
||||
* | | | |
|
||||
* +-----+-------+-------+
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void debugInfo()
|
||||
{
|
||||
uint16_t variableCount = get_var_count();
|
||||
mb_frame_len = 4;
|
||||
mb_frame[1] = MB_FC_DEBUG_INFO;
|
||||
mb_frame[2] = (uint8_t)(variableCount >> 8); // High byte
|
||||
mb_frame[3] = (uint8_t)(variableCount & 0xFF); // Low byte
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a Modbus response frame for the DEBUG_SET function code.
|
||||
*
|
||||
* This function constructs a Modbus response frame for the DEBUG_SET function code.
|
||||
* The response frame indicates whether the set trace command was successful or if
|
||||
* there was an error, such as an out-of-bounds index.
|
||||
*
|
||||
* Modbus Response Frame (DEBUG_SET):
|
||||
* +-----+------+
|
||||
* | MB | Resp.|
|
||||
* | FC | Code |
|
||||
* +-----+------+
|
||||
* |0x42 | Code |
|
||||
* +-----+------+
|
||||
*
|
||||
* @param varidx The index of the variable to set trace for.
|
||||
* @param flag The trace flag.
|
||||
* @param len The length of the trace data.
|
||||
* @param value Pointer to the trace data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void debugSetTrace(uint16_t varidx, uint8_t flag, uint16_t len, void *value)
|
||||
{
|
||||
uint16_t variableCount = get_var_count();
|
||||
if (varidx >= variableCount || len > (MAX_MB_FRAME - 7))
|
||||
{
|
||||
// Respond with an error indicating that the index is out of range
|
||||
mb_frame_len = 3;
|
||||
mb_frame[1] = MB_FC_DEBUG_SET;
|
||||
mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute set trace command
|
||||
set_trace((size_t)varidx, (bool)flag, value);
|
||||
|
||||
// Response
|
||||
mb_frame_len = 3;
|
||||
mb_frame[1] = MB_FC_DEBUG_SET;
|
||||
mb_frame[2] = MB_DEBUG_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a Modbus response frame for the DEBUG_GET function code.
|
||||
*
|
||||
* This function constructs a Modbus response frame for the DEBUG_GET function code.
|
||||
* The response frame includes the trace data for variables within the specified index range.
|
||||
*
|
||||
* Modbus Response Frame (DEBUG_GET):
|
||||
* +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+
|
||||
* | MB | Resp. | Last | Last | Tick | Tick | Tick | Tick | Resp. | Resp.| Data |
|
||||
* | FC | Code | Index | Index | | | | | Size | Size | Bytes |
|
||||
* +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+
|
||||
* |0x44 | Code | High | Low | High | Mid | Mid | Low | High | Low | Data |
|
||||
* | | | Byte | Byte | Byte | Byte | Byte | Byte | Byte | Byte | Bytes |
|
||||
* +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+
|
||||
*
|
||||
* @param startidx The start index of the variables to get trace for.
|
||||
* @param endidx The end index of the variables to get trace for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void debugGetTrace(uint16_t startidx, uint16_t endidx)
|
||||
{
|
||||
uint16_t variableCount = get_var_count();
|
||||
// Verify that startidx and endidx fall within the valid range of variables
|
||||
if (startidx >= variableCount || endidx >= variableCount || startidx > endidx)
|
||||
{
|
||||
// Respond with an error indicating that the indices are out of range
|
||||
mb_frame_len = 3;
|
||||
mb_frame[1] = MB_FC_DEBUG_GET;
|
||||
mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t lastVarIdx = startidx;
|
||||
size_t responseSize = 0;
|
||||
uint8_t *responsePtr = &(mb_frame[11]); // Start of response data
|
||||
|
||||
for (uint16_t varidx = startidx; varidx <= endidx; varidx++)
|
||||
{
|
||||
size_t varSize = get_var_size(varidx);
|
||||
if ((responseSize + 11) + varSize <= MAX_MB_FRAME) // Make sure the response fits
|
||||
{
|
||||
void *varAddr = get_var_addr(varidx);
|
||||
|
||||
// Copy the variable value to the response buffer
|
||||
memcpy(responsePtr, varAddr, varSize);
|
||||
|
||||
// Update response pointer and size
|
||||
responsePtr += varSize;
|
||||
responseSize += varSize;
|
||||
|
||||
// Update the lastVarIdx
|
||||
lastVarIdx = varidx;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Response buffer is full, break the loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mb_frame_len = 7 + responseSize; // Update response length
|
||||
mb_frame[1] = MB_FC_DEBUG_GET;
|
||||
mb_frame[2] = MB_DEBUG_SUCCESS;
|
||||
mb_frame[3] = (uint8_t)(lastVarIdx >> 8); // High byte
|
||||
mb_frame[4] = (uint8_t)(lastVarIdx & 0xFF); // Low byte
|
||||
mb_frame[5] = (uint8_t)((__tick >> 24) & 0xFF); // Highest byte
|
||||
mb_frame[6] = (uint8_t)((__tick >> 16) & 0xFF); // Second highest byte
|
||||
mb_frame[7] = (uint8_t)((__tick >> 8) & 0xFF); // Second lowest byte
|
||||
mb_frame[8] = (uint8_t)(__tick & 0xFF); // Lowest byte
|
||||
mb_frame[9] = (uint8_t)(responseSize >> 8); // High byte
|
||||
mb_frame[10] = (uint8_t)(responseSize & 0xFF); // Low byte
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a Modbus response frame for the DEBUG_GET_LIST function code.
|
||||
*
|
||||
* This function constructs a Modbus response frame for the DEBUG_GET_LIST function code.
|
||||
* The response frame includes the trace data for variables specified in the provided index list.
|
||||
*
|
||||
* Modbus Response Frame (DEBUG_GET_LIST):
|
||||
* +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+
|
||||
* | MB | Resp. | Last | Last | Tick | Tick | Tick | Tick | Resp. | Resp.| Data |
|
||||
* | FC | Code | Index | Index | | | | | Size | Size | Bytes |
|
||||
* +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+
|
||||
* |0x44 | Code | High | Low | High | Mid | Mid | Low | High | Low | Data |
|
||||
* | | | Byte | Byte | Byte | Byte | Byte | Byte | Byte | Byte | Bytes |
|
||||
* +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+
|
||||
*
|
||||
* @param numIndexes The number of indexes requested.
|
||||
* @param indexArray Pointer to the array containing variable indexes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void debugGetTraceList(uint16_t numIndexes, uint8_t *indexArray)
|
||||
{
|
||||
uint16_t response_idx = 11; // Start of response data in the response buffer
|
||||
uint16_t responseSize = 0;
|
||||
uint16_t lastVarIdx = 0;
|
||||
uint16_t variableCount = get_var_count();
|
||||
uint16_t *varidx_array = NULL;
|
||||
|
||||
// Allocate space for all indexes
|
||||
varidx_array = (uint16_t *)malloc(numIndexes * sizeof(uint16_t));
|
||||
if (varidx_array == NULL)
|
||||
{
|
||||
// Respond with a memory error
|
||||
mb_frame_len = 3;
|
||||
mb_frame[1] = MB_FC_DEBUG_GET_LIST;
|
||||
mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy all indexes to array
|
||||
for (uint16_t i = 0; i < numIndexes; i++)
|
||||
{
|
||||
varidx_array[i] = (uint16_t)indexArray[i * 2] << 8 | indexArray[i * 2 + 1];
|
||||
}
|
||||
|
||||
// Validate if all requested indexes are in range
|
||||
for (uint16_t i = 0; i < numIndexes; i++)
|
||||
{
|
||||
if (varidx_array[i] >= variableCount)
|
||||
{
|
||||
// Respond with an error indicating that the index is out of range
|
||||
mb_frame_len = 3;
|
||||
mb_frame[1] = MB_FC_DEBUG_GET_LIST;
|
||||
mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS;
|
||||
free(varidx_array);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add requested indexes and their traces to the response buffer
|
||||
size_t varSize = get_var_size(varidx_array[i]);
|
||||
|
||||
// Make sure there is enough space in the response buffer
|
||||
if (response_idx + varSize <= MAX_MB_FRAME)
|
||||
{
|
||||
// Add variable data to the response buffer
|
||||
void *varAddr = get_var_addr(varidx_array[i]);
|
||||
memcpy(&mb_frame[response_idx], varAddr, varSize);
|
||||
response_idx += varSize;
|
||||
responseSize += varSize;
|
||||
|
||||
// Update the lastVarIdx
|
||||
lastVarIdx = varidx_array[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Response buffer is full, break the loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update response length, lastVarIdx, and response size
|
||||
mb_frame_len = response_idx;
|
||||
mb_frame[1] = MB_FC_DEBUG_GET_LIST;
|
||||
mb_frame[2] = MB_DEBUG_SUCCESS;
|
||||
mb_frame[3] = (uint8_t)(lastVarIdx >> 8); // High byte
|
||||
mb_frame[4] = (uint8_t)(lastVarIdx & 0xFF); // Low byte
|
||||
mb_frame[5] = (uint8_t)((__tick >> 24) & 0xFF); // Highest byte
|
||||
mb_frame[6] = (uint8_t)((__tick >> 16) & 0xFF); // Second highest byte
|
||||
mb_frame[7] = (uint8_t)((__tick >> 8) & 0xFF); // Second lowest byte
|
||||
mb_frame[8] = (uint8_t)(__tick & 0xFF); // Lowest byte
|
||||
mb_frame[9] = (uint8_t)(responseSize >> 8); // High byte
|
||||
mb_frame[10] = (uint8_t)(responseSize & 0xFF); // Low byte
|
||||
free(varidx_array);
|
||||
}
|
||||
|
||||
void debugGetMd5(void *endianness)
|
||||
{
|
||||
// Check endianness
|
||||
uint16_t endian_check = 0;
|
||||
memcpy(&endian_check, endianness, 2);
|
||||
if (endian_check == 0xDEAD)
|
||||
{
|
||||
set_endianness(SAME_ENDIANNESS);
|
||||
}
|
||||
else if (endian_check == 0xADDE)
|
||||
{
|
||||
set_endianness(REVERSE_ENDIANNESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Respond with an error indicating that the argument is wrong
|
||||
mb_frame_len = 3;
|
||||
mb_frame[1] = MB_FC_DEBUG_GET_MD5;
|
||||
mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS;
|
||||
//return;
|
||||
}
|
||||
|
||||
mb_frame[1] = MB_FC_DEBUG_GET_MD5;
|
||||
mb_frame[2] = MB_DEBUG_SUCCESS;
|
||||
|
||||
// Copy MD5 string byte by byte to mb_frame starting from index 3
|
||||
const char md5[] = PROGRAM_MD5;
|
||||
int md5_len = 0;
|
||||
for (md5_len = 0; md5[md5_len] != '\0'; md5_len++)
|
||||
{
|
||||
mb_frame[md5_len + 3] = md5[md5_len];
|
||||
}
|
||||
|
||||
// Calculate mb_frame_len (MD5 string length + 3)
|
||||
mb_frame_len = md5_len + 3;
|
||||
}
|
||||
|
||||
uint16_t calcCrc()
|
||||
{
|
||||
uint8_t CRCHi = 0xFF, CRCLo = 0x0FF, Index;
|
||||
|
@ -16,9 +16,9 @@ Copyright (C) 2022 OpenPLC - Thiago Alves
|
||||
#define COILS 0
|
||||
#define INPUTSTATUS 1
|
||||
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
|
||||
#define MAX_MB_FRAME 32
|
||||
#define MAX_MB_FRAME 128
|
||||
#else
|
||||
#define MAX_MB_FRAME 64
|
||||
#define MAX_MB_FRAME 256
|
||||
#endif
|
||||
#define MAX_SRV_CLIENTS 3 //how many clients should be able to connect to TCP server at the same time
|
||||
#define MBAP_SIZE 6
|
||||
@ -46,6 +46,22 @@ Copyright (C) 2022 OpenPLC - Thiago Alves
|
||||
#include "Controllino.h"
|
||||
#endif
|
||||
|
||||
// Debugger functions
|
||||
extern "C" uint16_t get_var_count(void);
|
||||
extern "C" size_t get_var_size(size_t);// {return 0;}
|
||||
extern "C" void *get_var_addr(size_t);// {return 0;}
|
||||
extern "C" void force_var(size_t, bool, void *);// {}
|
||||
extern "C" void set_trace(size_t, bool, void *);// {}
|
||||
extern "C" void trace_reset(void);// {}
|
||||
extern "C" void set_endianness(uint8_t value);
|
||||
extern uint32_t __tick;
|
||||
|
||||
#define MB_DEBUG_SUCCESS 0x7E
|
||||
#define MB_DEBUG_ERROR_OUT_OF_BOUNDS 0x81
|
||||
#define MB_DEBUG_ERROR_OUT_OF_MEMORY 0x82
|
||||
#define SAME_ENDIANNESS 0
|
||||
#define REVERSE_ENDIANNESS 1
|
||||
|
||||
//Modbus registers struct
|
||||
struct MBinfo {
|
||||
uint8_t slaveid;
|
||||
@ -69,6 +85,11 @@ enum {
|
||||
MB_FC_WRITE_REG = 0x06, // Preset Single Register 4xxxx
|
||||
MB_FC_WRITE_COILS = 0x0F, // Write Multiple Coils (Outputs) 0xxxx
|
||||
MB_FC_WRITE_REGS = 0x10, // Write block of contiguous registers 4xxxx
|
||||
MB_FC_DEBUG_INFO = 0x41, // Request debug variables count
|
||||
MB_FC_DEBUG_SET = 0x42, // Debug set trace (force variable)
|
||||
MB_FC_DEBUG_GET = 0x43, // Debug get trace (read variables)
|
||||
MB_FC_DEBUG_GET_LIST = 0x44, // Debug get trace list (read list of variables)
|
||||
MB_FC_DEBUG_GET_MD5 = 0x45, // Debug get current program MD5
|
||||
};
|
||||
|
||||
//Exception Codes
|
||||
@ -130,6 +151,12 @@ void readInputStatus(uint16_t startreg, uint16_t numregs);
|
||||
void readInputRegisters(uint16_t startreg, uint16_t numregs);
|
||||
void writeSingleCoil(uint16_t reg, uint16_t status);
|
||||
void writeMultipleCoils(uint16_t startreg, uint16_t numoutputs, uint16_t bytecount);
|
||||
void debugInfo(void);
|
||||
void debugSetTrace(uint16_t varidx, uint8_t flag, uint16_t len, void *value);
|
||||
void debugGetTrace(uint16_t startidx, uint16_t endidx);
|
||||
void debugGetTraceList(uint16_t numIndexes, uint8_t *indexArray);
|
||||
void debugGetMd5(void *endianness);
|
||||
|
||||
|
||||
/* Table of CRC values for high-order byte */
|
||||
const byte _auchCRCHi[] = {
|
||||
@ -174,4 +201,4 @@ const byte _auchCRCLo[] = {
|
||||
0x40};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -23,4 +23,8 @@ extern uint8_t pinMask_AOUT[];
|
||||
|
||||
#ifdef USE_SM_BLOCKS
|
||||
#include "modules/sm_cards.c"
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARDUINOCAN_BLOCK
|
||||
#include "modules/arduinocan.c"
|
||||
#endif
|
@ -1,32 +1,32 @@
|
||||
//Program MD5
|
||||
#define PROGRAM_MD5 "e62be992fb489c046da9ff04f064e653"
|
||||
//Comms configurations
|
||||
#define MBSERIAL_IFACE Serial
|
||||
#define MBSERIAL_BAUD 115200
|
||||
#define MBSERIAL_SLAVE 0
|
||||
#define MBSERIAL_SLAVE 1
|
||||
#define MBTCP_MAC 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD
|
||||
#define MBTCP_IP
|
||||
#define MBTCP_DNS
|
||||
#define MBTCP_GATEWAY
|
||||
#define MBTCP_IP 192,168,1,195
|
||||
#define MBTCP_DNS 8,8,8,8
|
||||
#define MBTCP_GATEWAY 192,168,1,1
|
||||
#define MBTCP_SUBNET 255,255,255,0
|
||||
#define MBTCP_SSID ""
|
||||
#define MBTCP_PWD ""
|
||||
#define MBTCP
|
||||
#define MBTCP_PWD "password"
|
||||
#define MBSERIAL
|
||||
#define MODBUS_ENABLED
|
||||
#define MBTCP_ETHERNET
|
||||
|
||||
|
||||
//IO Config
|
||||
#define PINMASK_DIN 2, 3, 4, 5, 6
|
||||
#define PINMASK_AIN A0, A1, A2, A3, A4, A5
|
||||
#define PINMASK_DOUT 7, 8, 12, 13
|
||||
#define PINMASK_AOUT 9, 10, 11
|
||||
#define NUM_DISCRETE_INPUT 5
|
||||
#define NUM_ANALOG_INPUT 6
|
||||
#define NUM_DISCRETE_OUTPUT 4
|
||||
#define NUM_ANALOG_OUTPUT 3
|
||||
#define PINMASK_DIN 62, 63, 64, 65, 66, 67, 68, 69, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52
|
||||
#define PINMASK_AIN A0, A1, A2, A3, A4, A5, A6, A7
|
||||
#define PINMASK_DOUT 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53
|
||||
#define PINMASK_AOUT 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
|
||||
#define NUM_DISCRETE_INPUT 24
|
||||
#define NUM_ANALOG_INPUT 8
|
||||
#define NUM_DISCRETE_OUTPUT 25
|
||||
#define NUM_ANALOG_OUTPUT 11
|
||||
|
||||
|
||||
//Arduino Libraries
|
||||
#define USE_MQTT_BLOCKS
|
||||
|
||||
|
||||
//Pin Array Sizes
|
||||
|
File diff suppressed because one or more lines are too long
93
editor/arduino/examples/Baremetal/modules/arduino_cloud.c
Normal file → Executable file
93
editor/arduino/examples/Baremetal/modules/arduino_cloud.c
Normal file → Executable file
@ -1,48 +1,47 @@
|
||||
#include <ArduinoIoTCloud.h>
|
||||
#include <Arduino_ConnectionHandler.h>
|
||||
|
||||
extern "C" void cloud_begin(char *, char *, char *);
|
||||
extern "C" void cloud_add_bool(char *, int *);
|
||||
extern "C" void cloud_add_int(char *, int *);
|
||||
extern "C" void cloud_add_float(char *, float *);
|
||||
extern "C" void cloud_update();
|
||||
|
||||
bool first_update = true;
|
||||
|
||||
WiFiConnectionHandler *ArduinoIoTPreferredConnection;
|
||||
|
||||
void cloud_begin(char *thing_id, char *str_ssid, char *str_pass)
|
||||
{
|
||||
Serial.begin(9600);
|
||||
ArduinoIoTPreferredConnection = new WiFiConnectionHandler(str_ssid, str_pass);
|
||||
ArduinoCloud.setThingId(thing_id);
|
||||
}
|
||||
|
||||
void cloud_update()
|
||||
{
|
||||
if (first_update)
|
||||
{
|
||||
first_update = false;
|
||||
ArduinoCloud.begin(*ArduinoIoTPreferredConnection);
|
||||
|
||||
//Temporary
|
||||
setDebugMessageLevel(4);
|
||||
ArduinoCloud.printDebugInfo();
|
||||
}
|
||||
ArduinoCloud.update();
|
||||
}
|
||||
|
||||
void cloud_add_bool(char *var_name, int *bool_var)
|
||||
{
|
||||
ArduinoCloud.addPropertyReal(*bool_var, String(var_name));
|
||||
}
|
||||
|
||||
void cloud_add_int(char *var_name, int *int_var)
|
||||
{
|
||||
ArduinoCloud.addPropertyReal(*int_var, String(var_name));
|
||||
}
|
||||
|
||||
void cloud_add_float(char *var_name, float *float_var)
|
||||
{
|
||||
ArduinoCloud.addPropertyReal(*float_var, String(var_name));
|
||||
#include <ArduinoIoTCloud.h>
|
||||
#include <Arduino_ConnectionHandler.h>
|
||||
|
||||
extern "C" void cloud_begin(char *, char *, char *);
|
||||
extern "C" void cloud_add_bool(char *, int *);
|
||||
extern "C" void cloud_add_int(char *, int *);
|
||||
extern "C" void cloud_add_float(char *, float *);
|
||||
extern "C" void cloud_update();
|
||||
|
||||
bool first_update = true;
|
||||
|
||||
WiFiConnectionHandler *ArduinoIoTPreferredConnection;
|
||||
|
||||
void cloud_begin(char *thing_id, char *str_ssid, char *str_pass)
|
||||
{
|
||||
ArduinoIoTPreferredConnection = new WiFiConnectionHandler(str_ssid, str_pass);
|
||||
ArduinoCloud.setThingId(thing_id);
|
||||
}
|
||||
|
||||
void cloud_update()
|
||||
{
|
||||
if (first_update)
|
||||
{
|
||||
first_update = false;
|
||||
ArduinoCloud.begin(*ArduinoIoTPreferredConnection);
|
||||
|
||||
//Temporary
|
||||
setDebugMessageLevel(4);
|
||||
ArduinoCloud.printDebugInfo();
|
||||
}
|
||||
ArduinoCloud.update();
|
||||
}
|
||||
|
||||
void cloud_add_bool(char *var_name, int *bool_var)
|
||||
{
|
||||
ArduinoCloud.addPropertyReal(*bool_var, String(var_name));
|
||||
}
|
||||
|
||||
void cloud_add_int(char *var_name, int *int_var)
|
||||
{
|
||||
ArduinoCloud.addPropertyReal(*int_var, String(var_name));
|
||||
}
|
||||
|
||||
void cloud_add_float(char *var_name, float *float_var)
|
||||
{
|
||||
ArduinoCloud.addPropertyReal(*float_var, String(var_name));
|
||||
}
|
74
editor/arduino/examples/Baremetal/modules/arduinocan.c
Executable file
74
editor/arduino/examples/Baremetal/modules/arduinocan.c
Executable file
@ -0,0 +1,74 @@
|
||||
#include <Arduino_CAN.h>
|
||||
|
||||
extern "C" void *init_arduinocan(uint8_t,int);
|
||||
extern "C" bool write_arduinocan(uint32_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t);
|
||||
extern "C" bool write_arduinocan_word(uint32_t,uint64_t);
|
||||
extern "C" uint64_t read_arduinocan();
|
||||
|
||||
void *init_arduinocan(uint8_t pin_en, int baudrate)
|
||||
{
|
||||
#ifdef PIN_CAN0_STBY
|
||||
if(PIN_CAN0_STBY > -1) {
|
||||
pinMode(PIN_CAN0_STBY, OUTPUT);
|
||||
digitalWrite(PIN_CAN0_STBY, LOW);
|
||||
} else {
|
||||
pinMode(pin_en, OUTPUT);
|
||||
digitalWrite(pin_en, LOW);
|
||||
}
|
||||
#elif
|
||||
pinMode(pin_en, OUTPUT);
|
||||
digitalWrite(pin_en, LOW);
|
||||
#endif
|
||||
if (!CAN.begin((CanBitRate)baudrate))
|
||||
{
|
||||
Serial.println("CAN.begin(...) failed.");
|
||||
for (;;) {}
|
||||
}
|
||||
}
|
||||
|
||||
bool write_arduinocan(uint32_t id ,uint8_t d0, uint8_t d1 ,uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5,
|
||||
uint8_t d6, uint8_t d7)
|
||||
{
|
||||
//uint8_t data[4] = {d1, d2, d3, d4};
|
||||
uint8_t const msg_data[] = {d0, d1, d2, d3, d4, d5, d6, d7};
|
||||
//memcpy((void *)(msg_data + 4), &data, sizeof(data));
|
||||
CanMsg msg(id, sizeof(msg_data), msg_data);
|
||||
|
||||
/* Transmit the CAN message, capture and display an
|
||||
* error core in case of failure.
|
||||
*/
|
||||
if (int const rc = CAN.write(msg); rc < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool write_arduinocan_word(uint32_t id , uint64_t data)
|
||||
{
|
||||
|
||||
uint32_t const msg_data[2] = {0,0};
|
||||
memcpy((void *)(msg_data), &data, sizeof(data));
|
||||
CanMsg msg(id, sizeof(msg_data), (uint8_t *)&msg_data);
|
||||
|
||||
if (int const rc = CAN.write(msg); rc < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t read_arduinocan()
|
||||
{
|
||||
uint64_t data = 0;
|
||||
if (CAN.available())
|
||||
{
|
||||
CanMsg const msg = CAN.read();
|
||||
uint8_t payload[8] = {0};
|
||||
for(int i = 0; i < msg.data_length || i < 8; i++) {
|
||||
payload[i] = msg.data[i];
|
||||
}
|
||||
memcpy((void *)(&data), &payload, sizeof(payload));
|
||||
}
|
||||
return data;
|
||||
}
|
100
editor/arduino/examples/Baremetal/modules/ds18b20.c
Normal file → Executable file
100
editor/arduino/examples/Baremetal/modules/ds18b20.c
Normal file → Executable file
@ -1,51 +1,51 @@
|
||||
#include <OneWire.h>
|
||||
#include <DallasTemperature.h>
|
||||
|
||||
extern "C" void *init_ds18b20(uint8_t);
|
||||
extern "C" void request_ds18b20_temperatures(void *);
|
||||
extern "C" float read_ds18b20(void *, uint8_t);
|
||||
|
||||
void *init_ds18b20(uint8_t pin)
|
||||
{
|
||||
//Disable pin
|
||||
//disabled_pins[disabled_pins[0]] = pin;
|
||||
//if (disabled_pins[0] < 10) disabled_pins[0]++;
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
if (pinMask_DIN[i] == pin)
|
||||
pinMask_DIN[i] = 255;
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
if (pinMask_AIN[i] == pin)
|
||||
pinMask_AIN[i] = 255;
|
||||
}
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
if (pinMask_DOUT[i] == pin)
|
||||
pinMask_DOUT[i] = 255;
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
if (pinMask_AOUT[i] == pin)
|
||||
pinMask_AOUT[i] = 255;
|
||||
}
|
||||
|
||||
OneWire *oneWire;
|
||||
DallasTemperature *sensors;
|
||||
oneWire = new OneWire(pin);
|
||||
sensors = new DallasTemperature(oneWire);
|
||||
sensors->begin();
|
||||
return sensors;
|
||||
}
|
||||
void request_ds18b20_temperatures(void *class_pointer)
|
||||
{
|
||||
DallasTemperature *sensors = (DallasTemperature *)class_pointer;
|
||||
sensors->requestTemperatures();
|
||||
}
|
||||
float read_ds18b20(void *class_pointer, uint8_t index)
|
||||
{
|
||||
DallasTemperature *sensors = (DallasTemperature *)class_pointer;
|
||||
return sensors->getTempCByIndex(index);
|
||||
#include <OneWire.h>
|
||||
#include <DallasTemperature.h>
|
||||
|
||||
extern "C" void *init_ds18b20(uint8_t);
|
||||
extern "C" void request_ds18b20_temperatures(void *);
|
||||
extern "C" float read_ds18b20(void *, uint8_t);
|
||||
|
||||
void *init_ds18b20(uint8_t pin)
|
||||
{
|
||||
//Disable pin
|
||||
//disabled_pins[disabled_pins[0]] = pin;
|
||||
//if (disabled_pins[0] < 10) disabled_pins[0]++;
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
if (pinMask_DIN[i] == pin)
|
||||
pinMask_DIN[i] = 255;
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
if (pinMask_AIN[i] == pin)
|
||||
pinMask_AIN[i] = 255;
|
||||
}
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
if (pinMask_DOUT[i] == pin)
|
||||
pinMask_DOUT[i] = 255;
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
if (pinMask_AOUT[i] == pin)
|
||||
pinMask_AOUT[i] = 255;
|
||||
}
|
||||
|
||||
OneWire *oneWire;
|
||||
DallasTemperature *sensors;
|
||||
oneWire = new OneWire(pin);
|
||||
sensors = new DallasTemperature(oneWire);
|
||||
sensors->begin();
|
||||
return sensors;
|
||||
}
|
||||
void request_ds18b20_temperatures(void *class_pointer)
|
||||
{
|
||||
DallasTemperature *sensors = (DallasTemperature *)class_pointer;
|
||||
sensors->requestTemperatures();
|
||||
}
|
||||
float read_ds18b20(void *class_pointer, uint8_t index)
|
||||
{
|
||||
DallasTemperature *sensors = (DallasTemperature *)class_pointer;
|
||||
return sensors->getTempCByIndex(index);
|
||||
}
|
432
editor/arduino/examples/Baremetal/modules/mqtt.c
Normal file → Executable file
432
editor/arduino/examples/Baremetal/modules/mqtt.c
Normal file → Executable file
@ -1,217 +1,217 @@
|
||||
/*
|
||||
#include <ArduinoMqttClient.h>
|
||||
|
||||
WiFiClient wifiClient;
|
||||
MqttClient mqttClient(wifiClient);
|
||||
|
||||
extern "C" uint8_t connect_mqtt(char *broker, uint16_t port);
|
||||
extern "C" uint8_t mqtt_send(char *topic, char *message);
|
||||
|
||||
uint8_t connect_mqtt(char *broker, uint16_t port)
|
||||
{
|
||||
return mqttClient.connect(broker, port);
|
||||
}
|
||||
|
||||
uint8_t mqtt_send(char *topic, char *message)
|
||||
{
|
||||
mqttClient.beginMessage(topic);
|
||||
mqttClient.print(message);
|
||||
mqttClient.endMessage();
|
||||
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
#include <PubSubClient.h>
|
||||
//Reference: https://www.hivemq.com/blog/mqtt-client-library-encyclopedia-arduino-pubsubclient/
|
||||
|
||||
#ifdef MBTCP_ETHERNET
|
||||
EthernetClient wifiClient;
|
||||
#else
|
||||
WiFiClient wifiClient;
|
||||
#endif
|
||||
PubSubClient mqttClient(wifiClient);
|
||||
|
||||
extern "C" uint8_t connect_mqtt(char *broker, uint16_t port);
|
||||
extern "C" uint8_t connect_mqtt_auth(char *broker, uint16_t port, char *user, char *password);
|
||||
extern "C" uint8_t mqtt_send(char *topic, char *message);
|
||||
extern "C" uint8_t mqtt_receive(char *topic, char *message);
|
||||
extern "C" uint8_t mqtt_subscribe(char *topic);
|
||||
extern "C" uint8_t mqtt_unsubscribe(char *topic);
|
||||
extern "C" uint8_t mqtt_disconnect();
|
||||
extern "C" void mqtt_loop();
|
||||
|
||||
#define STR_MAX_LEN 126
|
||||
#define POOL_INCREMENT 2
|
||||
#define MAX_POOL_SIZE 10
|
||||
|
||||
struct MQTTpool {
|
||||
char mqtt_msg[STR_MAX_LEN];
|
||||
char mqtt_topic[STR_MAX_LEN];
|
||||
uint8_t is_free = true;
|
||||
};
|
||||
|
||||
uint8_t pool_size = 0;
|
||||
struct MQTTpool **msg_pool = NULL;
|
||||
|
||||
void add_message_to_pool(char *topic, char *msg)
|
||||
{
|
||||
// Initialize array
|
||||
if (pool_size == 0)
|
||||
{
|
||||
pool_size += POOL_INCREMENT;
|
||||
msg_pool = (struct MQTTpool **)malloc(pool_size * sizeof(struct MQTTpool *));
|
||||
|
||||
if (msg_pool == NULL)
|
||||
{
|
||||
// Allocation failed! Nothing to do here
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate memory for each pool item
|
||||
for (int i = 0; i < POOL_INCREMENT; i++)
|
||||
{
|
||||
msg_pool[i] = (struct MQTTpool *)malloc(sizeof(struct MQTTpool));
|
||||
if (msg_pool[i] == NULL)
|
||||
{
|
||||
// Allocation failed! Nothing to do here
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add message to the pool
|
||||
uint8_t message_added = false;
|
||||
while (!message_added)
|
||||
{
|
||||
for (int i = 0; i < pool_size; i++)
|
||||
{
|
||||
if (msg_pool[i]->is_free)
|
||||
{
|
||||
strncpy(msg_pool[i]->mqtt_topic, topic, STR_MAX_LEN);
|
||||
msg_pool[i]->mqtt_topic[STR_MAX_LEN - 1] = '\0'; // Safe termination
|
||||
strncpy(msg_pool[i]->mqtt_msg, msg, STR_MAX_LEN);
|
||||
msg_pool[i]->mqtt_msg[STR_MAX_LEN - 1] = '\0'; // Safe termination
|
||||
msg_pool[i]->is_free = false;
|
||||
message_added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pool is full
|
||||
if (!message_added)
|
||||
{
|
||||
// Increase pool size
|
||||
pool_size += POOL_INCREMENT;
|
||||
if (pool_size > MAX_POOL_SIZE)
|
||||
{
|
||||
// This is bad! No more space left. We must remove one of the messages
|
||||
pool_size -= POOL_INCREMENT;
|
||||
msg_pool[0]->is_free = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reallocate new size
|
||||
msg_pool = (struct MQTTpool **)realloc(msg_pool, pool_size * sizeof(struct MQTTpool *));
|
||||
|
||||
if (msg_pool == NULL)
|
||||
{
|
||||
// This is VERY bad!! Let's ignore this message, remove everything and start over
|
||||
pool_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate memory for each pool item
|
||||
for (int i = (pool_size - POOL_INCREMENT); i < pool_size; i++)
|
||||
{
|
||||
msg_pool[i] = (struct MQTTpool *)malloc(sizeof(struct MQTTpool));
|
||||
if (msg_pool[i] == NULL)
|
||||
{
|
||||
// Allocation failed! Nothing to do here
|
||||
return;
|
||||
}
|
||||
msg_pool[i]->is_free = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void callback(char* topic, byte* payload, unsigned int length)
|
||||
{
|
||||
if (length > (STR_MAX_LEN - 1))
|
||||
{
|
||||
length = (STR_MAX_LEN - 1); // truncate string to max size
|
||||
}
|
||||
payload[length] = 0; // make sure string is NULL terminated
|
||||
|
||||
add_message_to_pool(topic, (char *)payload);
|
||||
}
|
||||
|
||||
void mqtt_loop()
|
||||
{
|
||||
mqttClient.loop();
|
||||
}
|
||||
|
||||
uint8_t connect_mqtt(char *broker, uint16_t port)
|
||||
{
|
||||
mqttClient.setServer(broker, port);
|
||||
mqttClient.setCallback(callback);
|
||||
return mqttClient.connect("openplc-client");
|
||||
}
|
||||
|
||||
uint8_t connect_mqtt_auth(char *broker, uint16_t port, char *user, char *password)
|
||||
{
|
||||
mqttClient.setServer(broker, port);
|
||||
mqttClient.setCallback(callback);
|
||||
return mqttClient.connect("openplc-client", user, password);
|
||||
}
|
||||
|
||||
uint8_t mqtt_send(char *topic, char *message)
|
||||
{
|
||||
/*
|
||||
mqttClient.beginMessage(topic);
|
||||
mqttClient.print(message);
|
||||
mqttClient.endMessage();
|
||||
|
||||
return 1;
|
||||
*/
|
||||
|
||||
return mqttClient.publish(topic, message);
|
||||
}
|
||||
|
||||
uint8_t mqtt_subscribe(char *topic)
|
||||
{
|
||||
return (uint8_t)mqttClient.subscribe(topic);
|
||||
}
|
||||
|
||||
uint8_t mqtt_receive(char *topic, char *message)
|
||||
{
|
||||
// Return the first message in the pool that matches topic
|
||||
for (int i = 0; i < pool_size; i++)
|
||||
{
|
||||
// Check if there are messages in the pool
|
||||
if (!msg_pool[i]->is_free)
|
||||
{
|
||||
if (!strncmp(topic, msg_pool[i]->mqtt_topic, STR_MAX_LEN))
|
||||
{
|
||||
strncpy(message, msg_pool[i]->mqtt_msg, STR_MAX_LEN);
|
||||
msg_pool[i]->is_free = true;
|
||||
return strlen(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t mqtt_unsubscribe(char *topic)
|
||||
{
|
||||
return (uint8_t)mqttClient.unsubscribe(topic);
|
||||
}
|
||||
|
||||
uint8_t mqtt_disconnect()
|
||||
{
|
||||
mqttClient.disconnect();
|
||||
return 1;
|
||||
/*
|
||||
#include <ArduinoMqttClient.h>
|
||||
|
||||
WiFiClient wifiClient;
|
||||
MqttClient mqttClient(wifiClient);
|
||||
|
||||
extern "C" uint8_t connect_mqtt(char *broker, uint16_t port);
|
||||
extern "C" uint8_t mqtt_send(char *topic, char *message);
|
||||
|
||||
uint8_t connect_mqtt(char *broker, uint16_t port)
|
||||
{
|
||||
return mqttClient.connect(broker, port);
|
||||
}
|
||||
|
||||
uint8_t mqtt_send(char *topic, char *message)
|
||||
{
|
||||
mqttClient.beginMessage(topic);
|
||||
mqttClient.print(message);
|
||||
mqttClient.endMessage();
|
||||
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
#include <PubSubClient.h>
|
||||
//Reference: https://www.hivemq.com/blog/mqtt-client-library-encyclopedia-arduino-pubsubclient/
|
||||
|
||||
#ifdef MBTCP_ETHERNET
|
||||
EthernetClient wifiClient;
|
||||
#else
|
||||
WiFiClient wifiClient;
|
||||
#endif
|
||||
PubSubClient mqttClient(wifiClient);
|
||||
|
||||
extern "C" uint8_t connect_mqtt(char *broker, uint16_t port);
|
||||
extern "C" uint8_t connect_mqtt_auth(char *broker, uint16_t port, char *user, char *password);
|
||||
extern "C" uint8_t mqtt_send(char *topic, char *message);
|
||||
extern "C" uint8_t mqtt_receive(char *topic, char *message);
|
||||
extern "C" uint8_t mqtt_subscribe(char *topic);
|
||||
extern "C" uint8_t mqtt_unsubscribe(char *topic);
|
||||
extern "C" uint8_t mqtt_disconnect();
|
||||
extern "C" void mqtt_loop();
|
||||
|
||||
#define STR_MAX_LEN 126
|
||||
#define POOL_INCREMENT 2
|
||||
#define MAX_POOL_SIZE 10
|
||||
|
||||
struct MQTTpool {
|
||||
char mqtt_msg[STR_MAX_LEN];
|
||||
char mqtt_topic[STR_MAX_LEN];
|
||||
uint8_t is_free = true;
|
||||
};
|
||||
|
||||
uint8_t pool_size = 0;
|
||||
struct MQTTpool **msg_pool = NULL;
|
||||
|
||||
void add_message_to_pool(char *topic, char *msg)
|
||||
{
|
||||
// Initialize array
|
||||
if (pool_size == 0)
|
||||
{
|
||||
pool_size += POOL_INCREMENT;
|
||||
msg_pool = (struct MQTTpool **)malloc(pool_size * sizeof(struct MQTTpool *));
|
||||
|
||||
if (msg_pool == NULL)
|
||||
{
|
||||
// Allocation failed! Nothing to do here
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate memory for each pool item
|
||||
for (int i = 0; i < POOL_INCREMENT; i++)
|
||||
{
|
||||
msg_pool[i] = (struct MQTTpool *)malloc(sizeof(struct MQTTpool));
|
||||
if (msg_pool[i] == NULL)
|
||||
{
|
||||
// Allocation failed! Nothing to do here
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add message to the pool
|
||||
uint8_t message_added = false;
|
||||
while (!message_added)
|
||||
{
|
||||
for (int i = 0; i < pool_size; i++)
|
||||
{
|
||||
if (msg_pool[i]->is_free)
|
||||
{
|
||||
strncpy(msg_pool[i]->mqtt_topic, topic, STR_MAX_LEN);
|
||||
msg_pool[i]->mqtt_topic[STR_MAX_LEN - 1] = '\0'; // Safe termination
|
||||
strncpy(msg_pool[i]->mqtt_msg, msg, STR_MAX_LEN);
|
||||
msg_pool[i]->mqtt_msg[STR_MAX_LEN - 1] = '\0'; // Safe termination
|
||||
msg_pool[i]->is_free = false;
|
||||
message_added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pool is full
|
||||
if (!message_added)
|
||||
{
|
||||
// Increase pool size
|
||||
pool_size += POOL_INCREMENT;
|
||||
if (pool_size > MAX_POOL_SIZE)
|
||||
{
|
||||
// This is bad! No more space left. We must remove one of the messages
|
||||
pool_size -= POOL_INCREMENT;
|
||||
msg_pool[0]->is_free = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reallocate new size
|
||||
msg_pool = (struct MQTTpool **)realloc(msg_pool, pool_size * sizeof(struct MQTTpool *));
|
||||
|
||||
if (msg_pool == NULL)
|
||||
{
|
||||
// This is VERY bad!! Let's ignore this message, remove everything and start over
|
||||
pool_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate memory for each pool item
|
||||
for (int i = (pool_size - POOL_INCREMENT); i < pool_size; i++)
|
||||
{
|
||||
msg_pool[i] = (struct MQTTpool *)malloc(sizeof(struct MQTTpool));
|
||||
if (msg_pool[i] == NULL)
|
||||
{
|
||||
// Allocation failed! Nothing to do here
|
||||
return;
|
||||
}
|
||||
msg_pool[i]->is_free = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void callback(char* topic, byte* payload, unsigned int length)
|
||||
{
|
||||
if (length > (STR_MAX_LEN - 1))
|
||||
{
|
||||
length = (STR_MAX_LEN - 1); // truncate string to max size
|
||||
}
|
||||
payload[length] = 0; // make sure string is NULL terminated
|
||||
|
||||
add_message_to_pool(topic, (char *)payload);
|
||||
}
|
||||
|
||||
void mqtt_loop()
|
||||
{
|
||||
mqttClient.loop();
|
||||
}
|
||||
|
||||
uint8_t connect_mqtt(char *broker, uint16_t port)
|
||||
{
|
||||
mqttClient.setServer(broker, port);
|
||||
mqttClient.setCallback(callback);
|
||||
return mqttClient.connect("openplc-client");
|
||||
}
|
||||
|
||||
uint8_t connect_mqtt_auth(char *broker, uint16_t port, char *user, char *password)
|
||||
{
|
||||
mqttClient.setServer(broker, port);
|
||||
mqttClient.setCallback(callback);
|
||||
return mqttClient.connect("openplc-client", user, password);
|
||||
}
|
||||
|
||||
uint8_t mqtt_send(char *topic, char *message)
|
||||
{
|
||||
/*
|
||||
mqttClient.beginMessage(topic);
|
||||
mqttClient.print(message);
|
||||
mqttClient.endMessage();
|
||||
|
||||
return 1;
|
||||
*/
|
||||
|
||||
return mqttClient.publish(topic, message);
|
||||
}
|
||||
|
||||
uint8_t mqtt_subscribe(char *topic)
|
||||
{
|
||||
return (uint8_t)mqttClient.subscribe(topic);
|
||||
}
|
||||
|
||||
uint8_t mqtt_receive(char *topic, char *message)
|
||||
{
|
||||
// Return the first message in the pool that matches topic
|
||||
for (int i = 0; i < pool_size; i++)
|
||||
{
|
||||
// Check if there are messages in the pool
|
||||
if (!msg_pool[i]->is_free)
|
||||
{
|
||||
if (!strncmp(topic, msg_pool[i]->mqtt_topic, STR_MAX_LEN))
|
||||
{
|
||||
strncpy(message, msg_pool[i]->mqtt_msg, STR_MAX_LEN);
|
||||
msg_pool[i]->is_free = true;
|
||||
return strlen(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t mqtt_unsubscribe(char *topic)
|
||||
{
|
||||
return (uint8_t)mqttClient.unsubscribe(topic);
|
||||
}
|
||||
|
||||
uint8_t mqtt_disconnect()
|
||||
{
|
||||
mqttClient.disconnect();
|
||||
return 1;
|
||||
}
|
66
editor/arduino/examples/Baremetal/modules/p1am.c
Normal file → Executable file
66
editor/arduino/examples/Baremetal/modules/p1am.c
Normal file → Executable file
@ -1,34 +1,34 @@
|
||||
#include <P1AM.h>
|
||||
extern "C" uint8_t p1am_init();
|
||||
extern "C" void p1am_writeDiscrete(uint32_t, uint8_t, uint8_t);
|
||||
extern "C" uint32_t p1am_readDiscrete(uint8_t, uint8_t);
|
||||
extern "C" uint16_t p1am_readAnalog(uint8_t, uint8_t);
|
||||
|
||||
uint8_t modules_initialized = 0;
|
||||
|
||||
uint8_t p1am_init()
|
||||
{
|
||||
if (modules_initialized == 0)
|
||||
{
|
||||
modules_initialized = P1.init();
|
||||
//P1.init takes a while, so we need to reset scan cycle timer
|
||||
timer_ms = millis() + scan_cycle;
|
||||
}
|
||||
|
||||
return modules_initialized;
|
||||
}
|
||||
|
||||
void p1am_writeDiscrete(uint32_t data, uint8_t slot, uint8_t channel)
|
||||
{
|
||||
P1.writeDiscrete(data, slot, channel);
|
||||
}
|
||||
|
||||
uint32_t p1am_readDiscrete(uint8_t slot, uint8_t channel)
|
||||
{
|
||||
return P1.readDiscrete(slot, channel);
|
||||
}
|
||||
|
||||
uint16_t p1am_readAnalog(uint8_t slot, uint8_t channel)
|
||||
{
|
||||
return (uint16_t)P1.readAnalog(slot, channel);
|
||||
#include <P1AM.h>
|
||||
extern "C" uint8_t p1am_init();
|
||||
extern "C" void p1am_writeDiscrete(uint32_t, uint8_t, uint8_t);
|
||||
extern "C" uint32_t p1am_readDiscrete(uint8_t, uint8_t);
|
||||
extern "C" uint16_t p1am_readAnalog(uint8_t, uint8_t);
|
||||
|
||||
uint8_t modules_initialized = 0;
|
||||
|
||||
uint8_t p1am_init()
|
||||
{
|
||||
if (modules_initialized == 0)
|
||||
{
|
||||
modules_initialized = P1.init();
|
||||
//P1.init takes a while, so we need to reset scan cycle timer
|
||||
timer_ms = millis() + scan_cycle;
|
||||
}
|
||||
|
||||
return modules_initialized;
|
||||
}
|
||||
|
||||
void p1am_writeDiscrete(uint32_t data, uint8_t slot, uint8_t channel)
|
||||
{
|
||||
P1.writeDiscrete(data, slot, channel);
|
||||
}
|
||||
|
||||
uint32_t p1am_readDiscrete(uint8_t slot, uint8_t channel)
|
||||
{
|
||||
return P1.readDiscrete(slot, channel);
|
||||
}
|
||||
|
||||
uint16_t p1am_readAnalog(uint8_t slot, uint8_t channel)
|
||||
{
|
||||
return (uint16_t)P1.readAnalog(slot, channel);
|
||||
}
|
3098
editor/arduino/examples/Baremetal/modules/sm_cards.c
Normal file → Executable file
3098
editor/arduino/examples/Baremetal/modules/sm_cards.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@ -1 +1 @@
|
||||
{"board_type": "Arduino Uno [1.8.6]", "com_port": "COM1", "mb_serial": false, "serial_iface": "Serial", "baud": "115200", "slaveid": "0", "txpin": "-1", "mb_tcp": true, "tcp_iface": "Ethernet", "mac": "0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD", "ip": "", "dns": "", "gateway": "", "subnet": "255.255.255.0", "ssid": "", "pwd": "", "last_update": 1687807475.445833}
|
||||
{"board_type": "Arduino Mega [1.8.6]", "com_port": "IOUSBHostDevice", "mb_serial": true, "serial_iface": "Serial", "baud": "115200", "slaveid": "1", "txpin": "-1", "mb_tcp": false, "tcp_iface": "WiFi", "mac": "0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD", "ip": "192.168.1.195", "dns": "8.8.8.8", "gateway": "192.168.1.1", "subnet": "255.255.255.0", "ssid": "", "pwd": "password", "last_update": 1700084219.5547771}
|
4
editor/arduino/src/Arduino_OpenPLC.h
Normal file → Executable file
4
editor/arduino/src/Arduino_OpenPLC.h
Normal file → Executable file
@ -1,3 +1,3 @@
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
}
|
@ -0,0 +1 @@
|
||||
__LOCATED_VAR(BOOL,__QX0_0,Q,X,0,0)
|
@ -1,42 +1,110 @@
|
||||
#include "POUS.h"
|
||||
|
||||
void MQTT_EXAMPLE_init__(MQTT_EXAMPLE *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->BLINK_LED,__BOOL_LITERAL(FALSE),retain)
|
||||
TON_init__(&data__->TON0,retain);
|
||||
TOF_init__(&data__->TOF0,retain);
|
||||
MQTT_CONNECT_init__(&data__->MQTT_CONNECT0,retain);
|
||||
MQTT_SEND_init__(&data__->MQTT_SEND0,retain);
|
||||
__INIT_VAR(data__->MQTT_CONNECTED,0,retain)
|
||||
void PT2_init__(PT2 *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->IN1,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->IN3,1,retain)
|
||||
__INIT_VAR(data__->IN2,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->IN_TIME,__time_to_timespec(1, 0, 0, 0, 0, 0),retain)
|
||||
__INIT_VAR(data__->OUT1,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->OUT2,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->OUT3,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->ERROR,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->STARTED_TIMER_1,0,retain)
|
||||
__INIT_VAR(data__->TIMER_1_INPUT,0,retain)
|
||||
__INIT_VAR(data__->STARTED_TIMER_2,0,retain)
|
||||
__INIT_VAR(data__->TIMER_2_INPUT,0,retain)
|
||||
TOF_init__(&data__->TOF1,retain);
|
||||
TOF_init__(&data__->TOF2,retain);
|
||||
}
|
||||
|
||||
// Code part
|
||||
void MQTT_EXAMPLE_body__(MQTT_EXAMPLE *data__) {
|
||||
void PT2_body__(PT2 *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
__SET_VAR(data__->TON0.,EN,,__BOOL_LITERAL(TRUE));
|
||||
__SET_VAR(data__->TON0.,IN,,!(__GET_VAR(data__->BLINK_LED,)));
|
||||
__SET_VAR(data__->TON0.,PT,,__time_to_timespec(1, 500, 0, 0, 0, 0));
|
||||
TON_body__(&data__->TON0);
|
||||
__SET_VAR(data__->TOF0.,EN,,__GET_VAR(data__->TON0.ENO,));
|
||||
__SET_VAR(data__->TOF0.,IN,,__GET_VAR(data__->TON0.Q,));
|
||||
__SET_VAR(data__->TOF0.,PT,,__time_to_timespec(1, 500, 0, 0, 0, 0));
|
||||
TOF_body__(&data__->TOF0);
|
||||
__SET_VAR(data__->,BLINK_LED,,__GET_VAR(data__->TOF0.Q,));
|
||||
__SET_VAR(data__->MQTT_CONNECT0.,CONNECT,,!(__GET_VAR(data__->MQTT_CONNECTED,)));
|
||||
__SET_VAR(data__->MQTT_CONNECT0.,BROKER,,__STRING_LITERAL(18,"test.mosquitto.org"));
|
||||
__SET_VAR(data__->MQTT_CONNECT0.,PORT,,1883);
|
||||
MQTT_CONNECT_body__(&data__->MQTT_CONNECT0);
|
||||
__SET_VAR(data__->,MQTT_CONNECTED,,__GET_VAR(data__->MQTT_CONNECT0.SUCCESS,));
|
||||
__SET_VAR(data__->MQTT_SEND0.,SEND,,(__GET_VAR(data__->BLINK_LED,) && __GET_VAR(data__->MQTT_CONNECTED,)));
|
||||
__SET_VAR(data__->MQTT_SEND0.,TOPIC,,__STRING_LITERAL(18,"openplc-test-topic"));
|
||||
__SET_VAR(data__->MQTT_SEND0.,MESSAGE,,__STRING_LITERAL(19,"Hello from OpenPLC!"));
|
||||
MQTT_SEND_body__(&data__->MQTT_SEND0);
|
||||
__SET_VAR(data__->TOF1.,IN,,__GET_VAR(data__->TIMER_1_INPUT,));
|
||||
__SET_VAR(data__->TOF1.,PT,,__time_to_timespec(1, 0, 5, 0, 0, 0));
|
||||
TOF_body__(&data__->TOF1);
|
||||
__SET_VAR(data__->TOF2.,IN,,__GET_VAR(data__->TIMER_2_INPUT,));
|
||||
__SET_VAR(data__->TOF2.,PT,,__time_to_timespec(1, 0, 5, 0, 0, 0));
|
||||
TOF_body__(&data__->TOF2);
|
||||
if ((LE__BOOL__TIME(
|
||||
(BOOL)__BOOL_LITERAL(TRUE),
|
||||
NULL,
|
||||
(UINT)2,
|
||||
(TIME)__GET_VAR(data__->IN_TIME,),
|
||||
(TIME)__time_to_timespec(1, 0, 0, 0, 0, 0)) || GT__BOOL__TIME(
|
||||
(BOOL)__BOOL_LITERAL(TRUE),
|
||||
NULL,
|
||||
(UINT)2,
|
||||
(TIME)__GET_VAR(data__->IN_TIME,),
|
||||
(TIME)__time_to_timespec(1, 0, 300, 0, 0, 0)))) {
|
||||
__SET_VAR(data__->,ERROR,,__BOOL_LITERAL(TRUE));
|
||||
} else {
|
||||
__SET_VAR(data__->,ERROR,,__BOOL_LITERAL(FALSE));
|
||||
};
|
||||
if (((__GET_VAR(data__->IN1,) == __BOOL_LITERAL(TRUE)) && (__GET_VAR(data__->STARTED_TIMER_1,) == __BOOL_LITERAL(FALSE)))) {
|
||||
__SET_VAR(data__->,STARTED_TIMER_1,,__BOOL_LITERAL(TRUE));
|
||||
__SET_VAR(data__->,TIMER_1_INPUT,,__BOOL_LITERAL(TRUE));
|
||||
} else if (((__GET_VAR(data__->STARTED_TIMER_1,) == __BOOL_LITERAL(TRUE)) && (__GET_VAR(data__->TOF1.Q,) == __BOOL_LITERAL(TRUE)))) {
|
||||
__SET_VAR(data__->,TIMER_1_INPUT,,__BOOL_LITERAL(FALSE));
|
||||
} else if ((((__GET_VAR(data__->STARTED_TIMER_1,) == __BOOL_LITERAL(TRUE)) && (__GET_VAR(data__->TOF1.Q,) == __BOOL_LITERAL(FALSE))) && (__GET_VAR(data__->IN1,) == __BOOL_LITERAL(FALSE)))) {
|
||||
__SET_VAR(data__->,STARTED_TIMER_1,,__BOOL_LITERAL(FALSE));
|
||||
__SET_VAR(data__->,TIMER_1_INPUT,,__BOOL_LITERAL(FALSE));
|
||||
};
|
||||
if (((__GET_VAR(data__->IN2,) == __BOOL_LITERAL(TRUE)) && (__GET_VAR(data__->STARTED_TIMER_2,) == __BOOL_LITERAL(FALSE)))) {
|
||||
__SET_VAR(data__->,STARTED_TIMER_2,,__BOOL_LITERAL(TRUE));
|
||||
__SET_VAR(data__->,TIMER_2_INPUT,,__BOOL_LITERAL(TRUE));
|
||||
} else if (((__GET_VAR(data__->STARTED_TIMER_2,) == __BOOL_LITERAL(TRUE)) && (__GET_VAR(data__->TOF2.Q,) == __BOOL_LITERAL(TRUE)))) {
|
||||
__SET_VAR(data__->,TIMER_2_INPUT,,__BOOL_LITERAL(FALSE));
|
||||
} else if ((((__GET_VAR(data__->STARTED_TIMER_2,) == __BOOL_LITERAL(TRUE)) && (__GET_VAR(data__->TOF2.Q,) == __BOOL_LITERAL(FALSE))) && (__GET_VAR(data__->IN2,) == __BOOL_LITERAL(FALSE)))) {
|
||||
__SET_VAR(data__->,STARTED_TIMER_2,,__BOOL_LITERAL(FALSE));
|
||||
__SET_VAR(data__->,TIMER_2_INPUT,,__BOOL_LITERAL(FALSE));
|
||||
};
|
||||
__SET_VAR(data__->,OUT1,,__GET_VAR(data__->TOF1.Q,));
|
||||
__SET_VAR(data__->,OUT2,,__GET_VAR(data__->TOF2.Q,));
|
||||
__SET_VAR(data__->,OUT3,,__GET_VAR(data__->IN3,));
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_EXAMPLE_body__()
|
||||
} // PT2_body__()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void PROGRAM0_init__(PROGRAM0 *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->BUTTON,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_LOCATED(BOOL,__QX0_0,data__->TIMER_OUT,retain)
|
||||
__INIT_LOCATED_VALUE(data__->TIMER_OUT,__BOOL_LITERAL(FALSE))
|
||||
__INIT_VAR(data__->COUNTER_VALUE,0,retain)
|
||||
PT2_init__(&data__->PT20,retain);
|
||||
}
|
||||
|
||||
// Code part
|
||||
void PROGRAM0_body__(PROGRAM0 *data__) {
|
||||
// Initialise TEMP variables
|
||||
|
||||
__SET_VAR(data__->PT20.,IN1,,__GET_VAR(data__->BUTTON,));
|
||||
PT2_body__(&data__->PT20);
|
||||
__SET_LOCATED(data__->,TIMER_OUT,,__GET_VAR(data__->PT20.OUT1,));
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // PROGRAM0_body__()
|
||||
|
||||
|
||||
|
||||
|
@ -4,22 +4,48 @@
|
||||
#include "accessor.h"
|
||||
#include "iec_std_lib.h"
|
||||
|
||||
// PROGRAM MQTT_EXAMPLE
|
||||
// FUNCTION_BLOCK PT2
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,IN1)
|
||||
__DECLARE_VAR(BOOL,IN3)
|
||||
__DECLARE_VAR(BOOL,IN2)
|
||||
__DECLARE_VAR(TIME,IN_TIME)
|
||||
__DECLARE_VAR(BOOL,OUT1)
|
||||
__DECLARE_VAR(BOOL,OUT2)
|
||||
__DECLARE_VAR(BOOL,OUT3)
|
||||
__DECLARE_VAR(BOOL,ERROR)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
__DECLARE_VAR(BOOL,STARTED_TIMER_1)
|
||||
__DECLARE_VAR(BOOL,TIMER_1_INPUT)
|
||||
__DECLARE_VAR(BOOL,STARTED_TIMER_2)
|
||||
__DECLARE_VAR(BOOL,TIMER_2_INPUT)
|
||||
TOF TOF1;
|
||||
TOF TOF2;
|
||||
|
||||
} PT2;
|
||||
|
||||
void PT2_init__(PT2 *data__, BOOL retain);
|
||||
// Code part
|
||||
void PT2_body__(PT2 *data__);
|
||||
// PROGRAM PROGRAM0
|
||||
// Data part
|
||||
typedef struct {
|
||||
// PROGRAM Interface - IN, OUT, IN_OUT variables
|
||||
|
||||
// PROGRAM private variables - TEMP, private and located variables
|
||||
__DECLARE_VAR(BOOL,BLINK_LED)
|
||||
TON TON0;
|
||||
TOF TOF0;
|
||||
MQTT_CONNECT MQTT_CONNECT0;
|
||||
MQTT_SEND MQTT_SEND0;
|
||||
__DECLARE_VAR(BOOL,MQTT_CONNECTED)
|
||||
__DECLARE_VAR(BOOL,BUTTON)
|
||||
__DECLARE_LOCATED(BOOL,TIMER_OUT)
|
||||
__DECLARE_VAR(INT,COUNTER_VALUE)
|
||||
PT2 PT20;
|
||||
|
||||
} MQTT_EXAMPLE;
|
||||
} PROGRAM0;
|
||||
|
||||
void MQTT_EXAMPLE_init__(MQTT_EXAMPLE *data__, BOOL retain);
|
||||
void PROGRAM0_init__(PROGRAM0 *data__, BOOL retain);
|
||||
// Code part
|
||||
void MQTT_EXAMPLE_body__(MQTT_EXAMPLE *data__);
|
||||
void PROGRAM0_body__(PROGRAM0 *data__);
|
||||
#endif //__POUS_H
|
||||
|
@ -17,7 +17,7 @@ extern unsigned long long common_ticktime__;
|
||||
#include "POUS.h"
|
||||
|
||||
BOOL TASK0;
|
||||
MQTT_EXAMPLE RES0__INSTANCE0;
|
||||
PROGRAM0 RES0__INSTANCE0;
|
||||
#define INSTANCE0 RES0__INSTANCE0
|
||||
|
||||
void RES0_init__(void) {
|
||||
@ -25,13 +25,13 @@ void RES0_init__(void) {
|
||||
retain = 0;
|
||||
|
||||
TASK0 = __BOOL_LITERAL(FALSE);
|
||||
MQTT_EXAMPLE_init__(&INSTANCE0,retain);
|
||||
PROGRAM0_init__(&INSTANCE0,retain);
|
||||
}
|
||||
|
||||
void RES0_run__(unsigned long tick) {
|
||||
TASK0 = !(tick % 1);
|
||||
if (TASK0) {
|
||||
MQTT_EXAMPLE_body__(&INSTANCE0);
|
||||
PROGRAM0_body__(&INSTANCE0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,46 +1,48 @@
|
||||
// Programs
|
||||
0;CONFIG0.RES0.INSTANCE0;MQTT_EXAMPLE;
|
||||
0;CONFIG0.RES0.INSTANCE0;PROGRAM0;
|
||||
|
||||
// Variables
|
||||
0;FB;CONFIG0.RES0.INSTANCE0;CONFIG0.RES0.INSTANCE0;MQTT_EXAMPLE;;
|
||||
1;VAR;CONFIG0.RES0.INSTANCE0.BLINK_LED;CONFIG0.RES0.INSTANCE0.BLINK_LED;BOOL;BOOL;
|
||||
2;FB;CONFIG0.RES0.INSTANCE0.TON0;CONFIG0.RES0.INSTANCE0.TON0;TON;;
|
||||
3;VAR;CONFIG0.RES0.INSTANCE0.TON0.EN;CONFIG0.RES0.INSTANCE0.TON0.EN;BOOL;BOOL;
|
||||
4;VAR;CONFIG0.RES0.INSTANCE0.TON0.ENO;CONFIG0.RES0.INSTANCE0.TON0.ENO;BOOL;BOOL;
|
||||
5;VAR;CONFIG0.RES0.INSTANCE0.TON0.IN;CONFIG0.RES0.INSTANCE0.TON0.IN;BOOL;BOOL;
|
||||
6;VAR;CONFIG0.RES0.INSTANCE0.TON0.PT;CONFIG0.RES0.INSTANCE0.TON0.PT;TIME;TIME;
|
||||
7;VAR;CONFIG0.RES0.INSTANCE0.TON0.Q;CONFIG0.RES0.INSTANCE0.TON0.Q;BOOL;BOOL;
|
||||
8;VAR;CONFIG0.RES0.INSTANCE0.TON0.ET;CONFIG0.RES0.INSTANCE0.TON0.ET;TIME;TIME;
|
||||
9;VAR;CONFIG0.RES0.INSTANCE0.TON0.STATE;CONFIG0.RES0.INSTANCE0.TON0.STATE;SINT;SINT;
|
||||
10;VAR;CONFIG0.RES0.INSTANCE0.TON0.PREV_IN;CONFIG0.RES0.INSTANCE0.TON0.PREV_IN;BOOL;BOOL;
|
||||
11;VAR;CONFIG0.RES0.INSTANCE0.TON0.CURRENT_TIME;CONFIG0.RES0.INSTANCE0.TON0.CURRENT_TIME;TIME;TIME;
|
||||
12;VAR;CONFIG0.RES0.INSTANCE0.TON0.START_TIME;CONFIG0.RES0.INSTANCE0.TON0.START_TIME;TIME;TIME;
|
||||
13;FB;CONFIG0.RES0.INSTANCE0.TOF0;CONFIG0.RES0.INSTANCE0.TOF0;TOF;;
|
||||
14;VAR;CONFIG0.RES0.INSTANCE0.TOF0.EN;CONFIG0.RES0.INSTANCE0.TOF0.EN;BOOL;BOOL;
|
||||
15;VAR;CONFIG0.RES0.INSTANCE0.TOF0.ENO;CONFIG0.RES0.INSTANCE0.TOF0.ENO;BOOL;BOOL;
|
||||
16;VAR;CONFIG0.RES0.INSTANCE0.TOF0.IN;CONFIG0.RES0.INSTANCE0.TOF0.IN;BOOL;BOOL;
|
||||
17;VAR;CONFIG0.RES0.INSTANCE0.TOF0.PT;CONFIG0.RES0.INSTANCE0.TOF0.PT;TIME;TIME;
|
||||
18;VAR;CONFIG0.RES0.INSTANCE0.TOF0.Q;CONFIG0.RES0.INSTANCE0.TOF0.Q;BOOL;BOOL;
|
||||
19;VAR;CONFIG0.RES0.INSTANCE0.TOF0.ET;CONFIG0.RES0.INSTANCE0.TOF0.ET;TIME;TIME;
|
||||
20;VAR;CONFIG0.RES0.INSTANCE0.TOF0.STATE;CONFIG0.RES0.INSTANCE0.TOF0.STATE;SINT;SINT;
|
||||
21;VAR;CONFIG0.RES0.INSTANCE0.TOF0.PREV_IN;CONFIG0.RES0.INSTANCE0.TOF0.PREV_IN;BOOL;BOOL;
|
||||
22;VAR;CONFIG0.RES0.INSTANCE0.TOF0.CURRENT_TIME;CONFIG0.RES0.INSTANCE0.TOF0.CURRENT_TIME;TIME;TIME;
|
||||
23;VAR;CONFIG0.RES0.INSTANCE0.TOF0.START_TIME;CONFIG0.RES0.INSTANCE0.TOF0.START_TIME;TIME;TIME;
|
||||
24;FB;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0;MQTT_CONNECT;;
|
||||
25;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.EN;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.EN;BOOL;BOOL;
|
||||
26;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.ENO;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.ENO;BOOL;BOOL;
|
||||
27;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.CONNECT;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.CONNECT;BOOL;BOOL;
|
||||
28;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.BROKER;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.BROKER;STRING;STRING;
|
||||
29;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.PORT;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.PORT;UINT;UINT;
|
||||
30;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.SUCCESS;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.SUCCESS;BOOL;BOOL;
|
||||
31;FB;CONFIG0.RES0.INSTANCE0.MQTT_SEND0;CONFIG0.RES0.INSTANCE0.MQTT_SEND0;MQTT_SEND;;
|
||||
32;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.EN;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.EN;BOOL;BOOL;
|
||||
33;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.ENO;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.ENO;BOOL;BOOL;
|
||||
34;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.SEND;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.SEND;BOOL;BOOL;
|
||||
35;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.TOPIC;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.TOPIC;STRING;STRING;
|
||||
36;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.MESSAGE;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.MESSAGE;STRING;STRING;
|
||||
37;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.SUCCESS;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.SUCCESS;BOOL;BOOL;
|
||||
38;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECTED;CONFIG0.RES0.INSTANCE0.MQTT_CONNECTED;BOOL;BOOL;
|
||||
0;FB;CONFIG0.RES0.INSTANCE0;CONFIG0.RES0.INSTANCE0;PROGRAM0;;
|
||||
1;VAR;CONFIG0.RES0.INSTANCE0.BUTTON;CONFIG0.RES0.INSTANCE0.BUTTON;BOOL;BOOL;
|
||||
2;OUT;CONFIG0.RES0.INSTANCE0.TIMER_OUT;CONFIG0.RES0.INSTANCE0.TIMER_OUT;BOOL;BOOL;
|
||||
3;VAR;CONFIG0.RES0.INSTANCE0.COUNTER_VALUE;CONFIG0.RES0.INSTANCE0.COUNTER_VALUE;INT;INT;
|
||||
4;FB;CONFIG0.RES0.INSTANCE0.PT20;CONFIG0.RES0.INSTANCE0.PT20;PT2;;
|
||||
5;VAR;CONFIG0.RES0.INSTANCE0.PT20.EN;CONFIG0.RES0.INSTANCE0.PT20.EN;BOOL;BOOL;
|
||||
6;VAR;CONFIG0.RES0.INSTANCE0.PT20.ENO;CONFIG0.RES0.INSTANCE0.PT20.ENO;BOOL;BOOL;
|
||||
7;VAR;CONFIG0.RES0.INSTANCE0.PT20.IN1;CONFIG0.RES0.INSTANCE0.PT20.IN1;BOOL;BOOL;
|
||||
8;VAR;CONFIG0.RES0.INSTANCE0.PT20.IN3;CONFIG0.RES0.INSTANCE0.PT20.IN3;BOOL;BOOL;
|
||||
9;VAR;CONFIG0.RES0.INSTANCE0.PT20.IN2;CONFIG0.RES0.INSTANCE0.PT20.IN2;BOOL;BOOL;
|
||||
10;VAR;CONFIG0.RES0.INSTANCE0.PT20.IN_TIME;CONFIG0.RES0.INSTANCE0.PT20.IN_TIME;TIME;TIME;
|
||||
11;VAR;CONFIG0.RES0.INSTANCE0.PT20.OUT1;CONFIG0.RES0.INSTANCE0.PT20.OUT1;BOOL;BOOL;
|
||||
12;VAR;CONFIG0.RES0.INSTANCE0.PT20.OUT2;CONFIG0.RES0.INSTANCE0.PT20.OUT2;BOOL;BOOL;
|
||||
13;VAR;CONFIG0.RES0.INSTANCE0.PT20.OUT3;CONFIG0.RES0.INSTANCE0.PT20.OUT3;BOOL;BOOL;
|
||||
14;VAR;CONFIG0.RES0.INSTANCE0.PT20.ERROR;CONFIG0.RES0.INSTANCE0.PT20.ERROR;BOOL;BOOL;
|
||||
15;VAR;CONFIG0.RES0.INSTANCE0.PT20.STARTED_TIMER_1;CONFIG0.RES0.INSTANCE0.PT20.STARTED_TIMER_1;BOOL;BOOL;
|
||||
16;VAR;CONFIG0.RES0.INSTANCE0.PT20.TIMER_1_INPUT;CONFIG0.RES0.INSTANCE0.PT20.TIMER_1_INPUT;BOOL;BOOL;
|
||||
17;VAR;CONFIG0.RES0.INSTANCE0.PT20.STARTED_TIMER_2;CONFIG0.RES0.INSTANCE0.PT20.STARTED_TIMER_2;BOOL;BOOL;
|
||||
18;VAR;CONFIG0.RES0.INSTANCE0.PT20.TIMER_2_INPUT;CONFIG0.RES0.INSTANCE0.PT20.TIMER_2_INPUT;BOOL;BOOL;
|
||||
19;FB;CONFIG0.RES0.INSTANCE0.PT20.TOF1;CONFIG0.RES0.INSTANCE0.PT20.TOF1;TOF;;
|
||||
20;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.EN;CONFIG0.RES0.INSTANCE0.PT20.TOF1.EN;BOOL;BOOL;
|
||||
21;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.ENO;CONFIG0.RES0.INSTANCE0.PT20.TOF1.ENO;BOOL;BOOL;
|
||||
22;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.IN;CONFIG0.RES0.INSTANCE0.PT20.TOF1.IN;BOOL;BOOL;
|
||||
23;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.PT;CONFIG0.RES0.INSTANCE0.PT20.TOF1.PT;TIME;TIME;
|
||||
24;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.Q;CONFIG0.RES0.INSTANCE0.PT20.TOF1.Q;BOOL;BOOL;
|
||||
25;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.ET;CONFIG0.RES0.INSTANCE0.PT20.TOF1.ET;TIME;TIME;
|
||||
26;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.STATE;CONFIG0.RES0.INSTANCE0.PT20.TOF1.STATE;SINT;SINT;
|
||||
27;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.PREV_IN;CONFIG0.RES0.INSTANCE0.PT20.TOF1.PREV_IN;BOOL;BOOL;
|
||||
28;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.CURRENT_TIME;CONFIG0.RES0.INSTANCE0.PT20.TOF1.CURRENT_TIME;TIME;TIME;
|
||||
29;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.START_TIME;CONFIG0.RES0.INSTANCE0.PT20.TOF1.START_TIME;TIME;TIME;
|
||||
30;FB;CONFIG0.RES0.INSTANCE0.PT20.TOF2;CONFIG0.RES0.INSTANCE0.PT20.TOF2;TOF;;
|
||||
31;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.EN;CONFIG0.RES0.INSTANCE0.PT20.TOF2.EN;BOOL;BOOL;
|
||||
32;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.ENO;CONFIG0.RES0.INSTANCE0.PT20.TOF2.ENO;BOOL;BOOL;
|
||||
33;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.IN;CONFIG0.RES0.INSTANCE0.PT20.TOF2.IN;BOOL;BOOL;
|
||||
34;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.PT;CONFIG0.RES0.INSTANCE0.PT20.TOF2.PT;TIME;TIME;
|
||||
35;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.Q;CONFIG0.RES0.INSTANCE0.PT20.TOF2.Q;BOOL;BOOL;
|
||||
36;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.ET;CONFIG0.RES0.INSTANCE0.PT20.TOF2.ET;TIME;TIME;
|
||||
37;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.STATE;CONFIG0.RES0.INSTANCE0.PT20.TOF2.STATE;SINT;SINT;
|
||||
38;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.PREV_IN;CONFIG0.RES0.INSTANCE0.PT20.TOF2.PREV_IN;BOOL;BOOL;
|
||||
39;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.CURRENT_TIME;CONFIG0.RES0.INSTANCE0.PT20.TOF2.CURRENT_TIME;TIME;TIME;
|
||||
40;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.START_TIME;CONFIG0.RES0.INSTANCE0.PT20.TOF2.START_TIME;TIME;TIME;
|
||||
|
||||
|
||||
// Ticktime
|
||||
|
|
142
editor/arduino/src/arduino.cpp
Normal file → Executable file
142
editor/arduino/src/arduino.cpp
Normal file → Executable file
@ -5,14 +5,29 @@ extern "C" {
|
||||
#include "Arduino.h"
|
||||
#include "../examples/Baremetal/defines.h"
|
||||
|
||||
//OpenPLC HAL for Arduino Uno and Arduino Nano (old) form factor (Uno, Leonardo, Nano, Micro and Zero)
|
||||
#if defined(__AVR__)
|
||||
#include "AVR_PWM.h"
|
||||
#else
|
||||
#include "SAMDUE_PWM.h"
|
||||
#endif
|
||||
|
||||
/******************PINOUT CONFIGURATION*******************
|
||||
Digital In: 2, 3, 4, 5, 6 (%IX0.0 - %IX0.4)
|
||||
Digital Out: 7, 8, 12, 13 (%QX0.0 - %QX0.3)
|
||||
Analog In: A0, A1, A2, A3, A4, A5 (%IW0 - %IW5)
|
||||
Analog Out: 9, 10, 11 (%QW0 - %QW2)
|
||||
**********************************************************/
|
||||
//OpenPLC HAL for Arduino Mega and Arduino Due
|
||||
|
||||
/************************PINOUT CONFIGURATION*************************
|
||||
Digital In: 62, 63, 64, 65, 66, 67, 68, 69 (%IX0.0 - %IX0.7)
|
||||
22, 24, 26, 28, 30, 32, 34, 36 (%IX1.0 - %IX1.7)
|
||||
38, 40, 42, 44, 46, 48, 50, 52 (%IX2.0 - %IX2.7)
|
||||
|
||||
Digital Out: 14, 15, 16, 17, 18, 19, 20, 21 (%QX0.0 - %QX0.7)
|
||||
23, 25, 27, 29, 31, 33, 35, 37 (%QX1.0 - %QX1.7)
|
||||
39, 41, 43, 45, 47, 49, 51, 53 (%QX2.0 - %QX2.7)
|
||||
|
||||
Analog In: A0, A1, A2, A3, A4, A5, A6, A7 (%IW0 - %IW7)
|
||||
|
||||
Analog Out: 2, 3, 4, 5, 6, 7, 8, 9 (%QW0 - %QW7)
|
||||
10, 11, 12, 13 (%QW8 - %QW11)
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
//Create the I/O pin masks
|
||||
uint8_t pinMask_DIN[] = {PINMASK_DIN};
|
||||
@ -20,6 +35,48 @@ uint8_t pinMask_AIN[] = {PINMASK_AIN};
|
||||
uint8_t pinMask_DOUT[] = {PINMASK_DOUT};
|
||||
uint8_t pinMask_AOUT[] = {PINMASK_AOUT};
|
||||
|
||||
#define NUM_OF_PWM_PINS 12
|
||||
#define PWM_DEFAULT_FREQ 490
|
||||
|
||||
#if defined(__AVR__)
|
||||
#define PWM_CHANNEL_0_PIN 2
|
||||
#define PWM_CHANNEL_1_PIN 3
|
||||
#define PWM_CHANNEL_2_PIN 255 // disable pin 4 as it uses TIMER0
|
||||
#define PWM_CHANNEL_3_PIN 5
|
||||
#define PWM_CHANNEL_4_PIN 6
|
||||
#define PWM_CHANNEL_5_PIN 7
|
||||
#define PWM_CHANNEL_6_PIN 8
|
||||
#define PWM_CHANNEL_7_PIN 9
|
||||
#define PWM_CHANNEL_8_PIN 10
|
||||
#define PWM_CHANNEL_9_PIN 11
|
||||
#define PWM_CHANNEL_10_PIN 12
|
||||
#define PWM_CHANNEL_11_PIN 255 // disable pin 13 as it uses TIMER0
|
||||
#else
|
||||
#define PWM_CHANNEL_0_PIN 2
|
||||
#define PWM_CHANNEL_1_PIN 3
|
||||
#define PWM_CHANNEL_2_PIN 4
|
||||
#define PWM_CHANNEL_3_PIN 5
|
||||
#define PWM_CHANNEL_4_PIN 6
|
||||
#define PWM_CHANNEL_5_PIN 7
|
||||
#define PWM_CHANNEL_6_PIN 8
|
||||
#define PWM_CHANNEL_7_PIN 9
|
||||
#define PWM_CHANNEL_8_PIN 10
|
||||
#define PWM_CHANNEL_9_PIN 11
|
||||
#define PWM_CHANNEL_10_PIN 12
|
||||
#define PWM_CHANNEL_11_PIN 13
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__AVR__)
|
||||
AVR_PWM *PWM_Instance[NUM_OF_PWM_PINS];
|
||||
#else
|
||||
SAMDUE_PWM *PWM_Instance[NUM_OF_PWM_PINS];
|
||||
#endif
|
||||
|
||||
extern "C" uint8_t set_hardware_pwm(uint8_t, float, float); //this call is required for the C-based PWM block on the Editor
|
||||
|
||||
bool pwm_initialized = false;
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
@ -47,6 +104,77 @@ void hardwareInit()
|
||||
}
|
||||
}
|
||||
|
||||
void init_pwm()
|
||||
{
|
||||
// If PWM_CONTROLLER block is being used, disable pins from regular analogWrite
|
||||
const uint8_t pins[] = {PWM_CHANNEL_0_PIN, PWM_CHANNEL_1_PIN, PWM_CHANNEL_2_PIN, PWM_CHANNEL_3_PIN, PWM_CHANNEL_4_PIN, PWM_CHANNEL_5_PIN,
|
||||
PWM_CHANNEL_6_PIN, PWM_CHANNEL_7_PIN, PWM_CHANNEL_8_PIN, PWM_CHANNEL_9_PIN, PWM_CHANNEL_10_PIN, PWM_CHANNEL_11_PIN};
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
for (int j = 0; j < NUM_OF_PWM_PINS; j++)
|
||||
{
|
||||
if (pinMask_AOUT[i] == pins[j])
|
||||
{
|
||||
pinMask_AOUT[i] = 255; //disable pin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize PWM pins
|
||||
#if defined(__AVR__)
|
||||
PWM_Instance[0] = new AVR_PWM(PWM_CHANNEL_0_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[1] = new AVR_PWM(PWM_CHANNEL_1_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[2] = new AVR_PWM(PWM_CHANNEL_2_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[3] = new AVR_PWM(PWM_CHANNEL_3_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[4] = new AVR_PWM(PWM_CHANNEL_4_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[5] = new AVR_PWM(PWM_CHANNEL_5_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[6] = new AVR_PWM(PWM_CHANNEL_6_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[7] = new AVR_PWM(PWM_CHANNEL_7_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[8] = new AVR_PWM(PWM_CHANNEL_8_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[9] = new AVR_PWM(PWM_CHANNEL_9_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[10] = new AVR_PWM(PWM_CHANNEL_10_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[11] = new AVR_PWM(PWM_CHANNEL_11_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
#else
|
||||
PWM_Instance[0] = new SAMDUE_PWM(PWM_CHANNEL_0_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[1] = new SAMDUE_PWM(PWM_CHANNEL_1_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[2] = new SAMDUE_PWM(PWM_CHANNEL_2_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[3] = new SAMDUE_PWM(PWM_CHANNEL_3_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[4] = new SAMDUE_PWM(PWM_CHANNEL_4_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[5] = new SAMDUE_PWM(PWM_CHANNEL_5_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[6] = new SAMDUE_PWM(PWM_CHANNEL_6_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[7] = new SAMDUE_PWM(PWM_CHANNEL_7_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[8] = new SAMDUE_PWM(PWM_CHANNEL_8_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[9] = new SAMDUE_PWM(PWM_CHANNEL_9_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[10] = new SAMDUE_PWM(PWM_CHANNEL_10_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[11] = new SAMDUE_PWM(PWM_CHANNEL_11_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t set_hardware_pwm(uint8_t ch, float freq, float duty)
|
||||
{
|
||||
if (pwm_initialized == false)
|
||||
{
|
||||
init_pwm();
|
||||
pwm_initialized = true;
|
||||
}
|
||||
|
||||
const uint8_t pins[] = {PWM_CHANNEL_0_PIN, PWM_CHANNEL_1_PIN, PWM_CHANNEL_2_PIN, PWM_CHANNEL_3_PIN, PWM_CHANNEL_4_PIN, PWM_CHANNEL_5_PIN,
|
||||
PWM_CHANNEL_6_PIN, PWM_CHANNEL_7_PIN, PWM_CHANNEL_8_PIN, PWM_CHANNEL_9_PIN, PWM_CHANNEL_10_PIN, PWM_CHANNEL_11_PIN};
|
||||
|
||||
if (ch >= NUM_OF_PWM_PINS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PWM_Instance[ch]->setPWM(pins[ch], freq, duty))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
|
466
editor/arduino/src/arduino_builder.py
Normal file → Executable file
466
editor/arduino/src/arduino_builder.py
Normal file → Executable file
@ -1,233 +1,233 @@
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
|
||||
if (len(sys.argv) < 3):
|
||||
print("Usage: python arduino_builder.py <st_file> <platform> [com_port]")
|
||||
quit()
|
||||
|
||||
st_file = sys.argv[1]
|
||||
platform = sys.argv[2]
|
||||
port = None
|
||||
if (len(sys.argv) > 3):
|
||||
port = sys.argv[3]
|
||||
|
||||
if (os.path.exists("../bin/iec2c") or os.path.exists("../bin/iec2c.exe")):
|
||||
#remove old files first
|
||||
if os.path.exists('POUS.c'):
|
||||
os.remove('POUS.c')
|
||||
if os.path.exists('POUS.h'):
|
||||
os.remove('POUS.h')
|
||||
if os.path.exists('LOCATED_VARIABLES.h'):
|
||||
os.remove('LOCATED_VARIABLES.h')
|
||||
if os.path.exists('VARIABLES.csv'):
|
||||
os.remove('VARIABLES.csv')
|
||||
if os.path.exists('Config0.c'):
|
||||
os.remove('Config0.c')
|
||||
if os.path.exists('Config0.h'):
|
||||
os.remove('Config0.h')
|
||||
if os.path.exists('Res0.c'):
|
||||
os.remove('Res0.c')
|
||||
else:
|
||||
print("Error: iec2c compiler not found!")
|
||||
quit()
|
||||
|
||||
#Setup environment
|
||||
print("Configuring environment...")
|
||||
if (os.name == 'nt'):
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 core install arduino:avr')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 core install arduino:samd')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 core install arduino:megaavr')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 core install arduino:mbed_portenta')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 lib install ArduinoModbus')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 lib install Arduino_MachineControl')
|
||||
print(env_setup.read())
|
||||
|
||||
else:
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 core install arduino:avr')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 core install arduino:samd')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 core install arduino:megaavr')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 core install arduino:mbed_portenta')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 lib install ArduinoModbus')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 lib install Arduino_MachineControl')
|
||||
print(env_setup.read())
|
||||
|
||||
|
||||
#Generate C files
|
||||
print("Compiling .st file...")
|
||||
if (os.name == 'nt'):
|
||||
compilation = os.popen('..\\bin\\iec2c.exe ' + st_file)
|
||||
else:
|
||||
compilation = os.popen('../bin/iec2c ' + st_file)
|
||||
print(compilation.read())
|
||||
|
||||
#Generate glueVars.c
|
||||
if not (os.path.exists("LOCATED_VARIABLES.h")):
|
||||
print("Error: Couldn't find LOCATED_VARIABLES.h. Check iec2c compiler output for more information")
|
||||
quit()
|
||||
|
||||
located_vars_file = open('LOCATED_VARIABLES.h', 'r')
|
||||
located_vars = located_vars_file.readlines()
|
||||
|
||||
glueVars = """
|
||||
#include "iec_std_lib.h"
|
||||
|
||||
#define __LOCATED_VAR(type, name, ...) type __##name;
|
||||
#include "LOCATED_VARIABLES.h"
|
||||
#undef __LOCATED_VAR
|
||||
#define __LOCATED_VAR(type, name, ...) type* name = &__##name;
|
||||
#include "LOCATED_VARIABLES.h"
|
||||
#undef __LOCATED_VAR
|
||||
|
||||
TIME __CURRENT_TIME;
|
||||
extern unsigned long long common_ticktime__;
|
||||
|
||||
//OpenPLC Buffers
|
||||
//Booleans
|
||||
IEC_BOOL *bool_input[2][8];
|
||||
IEC_BOOL *bool_output[2][8];
|
||||
IEC_UINT *int_input[16];
|
||||
IEC_UINT *int_output[16];
|
||||
void glueVars()
|
||||
{
|
||||
"""
|
||||
|
||||
for located_var in located_vars:
|
||||
#cleanup located var line
|
||||
if ('__LOCATED_VAR(' in located_var):
|
||||
located_var = located_var.split('(')[1].split(')')[0]
|
||||
var_data = located_var.split(',')
|
||||
if (len(var_data) < 5):
|
||||
print('Error processing located var line: ' + located_var)
|
||||
else:
|
||||
var_type = var_data[0]
|
||||
var_name = var_data[1]
|
||||
var_address = var_data[4]
|
||||
var_subaddress = '0'
|
||||
if (len(var_data) > 5):
|
||||
var_subaddress = var_data[5]
|
||||
|
||||
#check variable type and assign to correct buffer pointer
|
||||
if ('QX' in var_name):
|
||||
if (int(var_address) > 2 or int(var_subaddress) > 7):
|
||||
print('Error: wrong location for var ' + var_name)
|
||||
quit()
|
||||
glueVars += ' bool_output[' + var_address + '][' + var_subaddress + '] = ' + var_name + ';\n'
|
||||
elif ('IX' in var_name):
|
||||
if (int(var_address) > 2 or int(var_subaddress) > 7):
|
||||
print('Error: wrong location for var ' + var_name)
|
||||
quit()
|
||||
glueVars += ' bool_input[' + var_address + '][' + var_subaddress + '] = ' + var_name + ';\n'
|
||||
elif ('QW' in var_name):
|
||||
if (int(var_address) > 16):
|
||||
print('Error: wrong location for var ' + var_name)
|
||||
quit()
|
||||
glueVars += ' int_output[' + var_address + '] = ' + var_name + ';\n'
|
||||
elif ('IW' in var_name):
|
||||
if (int(var_address) > 16):
|
||||
print('Error: wrong location for var ' + var_name)
|
||||
quit()
|
||||
glueVars += ' int_input[' + var_address + '] = ' + var_name + ';\n'
|
||||
else:
|
||||
print('Could not process location "' + var_name + '" from line: ' + located_var)
|
||||
quit()
|
||||
|
||||
glueVars += """
|
||||
}
|
||||
|
||||
void updateTime()
|
||||
{
|
||||
__CURRENT_TIME.tv_nsec += common_ticktime__;
|
||||
|
||||
if (__CURRENT_TIME.tv_nsec >= 1000000000)
|
||||
{
|
||||
__CURRENT_TIME.tv_nsec -= 1000000000;
|
||||
__CURRENT_TIME.tv_sec += 1;
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
f = open('glueVars.c', 'w')
|
||||
f.write(glueVars)
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
time.sleep(2) #make sure glueVars.c was written to disk
|
||||
|
||||
# Patch POUS.c to include POUS.h
|
||||
f = open('POUS.c', 'r')
|
||||
pous_c = '#include "POUS.h"\n\n' + f.read()
|
||||
f.close()
|
||||
|
||||
f = open('POUS.c', 'w')
|
||||
f.write(pous_c)
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
# Patch Res0.c to include POUS.h instead of POUS.c
|
||||
f = open('Res0.c', 'r')
|
||||
res0_c = ''
|
||||
lines = f.readlines()
|
||||
for line in lines:
|
||||
if '#include "POUS.c"' in line:
|
||||
res0_c += '#include "POUS.h"\n'
|
||||
else:
|
||||
res0_c += line
|
||||
f.close()
|
||||
|
||||
f = open('Res0.c', 'w')
|
||||
f.write(res0_c)
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
#Generate .elf file
|
||||
print("Generating binary file...")
|
||||
if (os.name == 'nt'):
|
||||
compilation = os.popen('..\\bin\\arduino-cli-w32 compile -v --libraries=..\\..\\ --build-property compiler.c.extra_flags="-I..\\src\\lib" --build-property compiler.cpp.extra_flags="-I..\\src\\lib" --export-binaries -b ' + platform + ' ..\\examples\\Baremetal\\Baremetal.ino')
|
||||
else:
|
||||
compilation = os.popen('../bin/arduino-cli-l64 compile -v --libraries=../../ --build-property compiler.c.extra_flags="-I../src/lib" --build-property compiler.cpp.extra_flags="-I../src/lib" --export-binaries -b ' + platform + ' ../examples/Baremetal/Baremetal.ino')
|
||||
print(compilation.read())
|
||||
if (port != None):
|
||||
if (os.name == 'nt'):
|
||||
uploading = os.popen('..\\bin\\arduino-cli-w32 upload --port ' + port + ' --fqbn ' + platform + ' ..\\examples\\Baremetal/')
|
||||
else:
|
||||
uploading = os.popen('../bin/arduino-cli-l64 upload --port ' + port + ' --fqbn ' + platform + ' ../examples/Baremetal/')
|
||||
print(uploading.read())
|
||||
|
||||
#print("No clean up")
|
||||
#quit()
|
||||
|
||||
if (os.name != 'nt'):
|
||||
print("Cleaning up...")
|
||||
if os.path.exists('POUS.c'):
|
||||
os.remove('POUS.c')
|
||||
if os.path.exists('POUS.h'):
|
||||
os.remove('POUS.h')
|
||||
if os.path.exists('LOCATED_VARIABLES.h'):
|
||||
os.remove('LOCATED_VARIABLES.h')
|
||||
if os.path.exists('VARIABLES.csv'):
|
||||
os.remove('VARIABLES.csv')
|
||||
if os.path.exists('Config0.c'):
|
||||
os.remove('Config0.c')
|
||||
if os.path.exists('Config0.h'):
|
||||
os.remove('Config0.h')
|
||||
if os.path.exists('Config0.o'):
|
||||
os.remove('Config0.o')
|
||||
if os.path.exists('Res0.c'):
|
||||
os.remove('Res0.c')
|
||||
if os.path.exists('Res0.o'):
|
||||
os.remove('Res0.o')
|
||||
if os.path.exists('glueVars.c'):
|
||||
os.remove('glueVars.c')
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
|
||||
if (len(sys.argv) < 3):
|
||||
print("Usage: python arduino_builder.py <st_file> <platform> [com_port]")
|
||||
quit()
|
||||
|
||||
st_file = sys.argv[1]
|
||||
platform = sys.argv[2]
|
||||
port = None
|
||||
if (len(sys.argv) > 3):
|
||||
port = sys.argv[3]
|
||||
|
||||
if (os.path.exists("../bin/iec2c") or os.path.exists("../bin/iec2c.exe")):
|
||||
#remove old files first
|
||||
if os.path.exists('POUS.c'):
|
||||
os.remove('POUS.c')
|
||||
if os.path.exists('POUS.h'):
|
||||
os.remove('POUS.h')
|
||||
if os.path.exists('LOCATED_VARIABLES.h'):
|
||||
os.remove('LOCATED_VARIABLES.h')
|
||||
if os.path.exists('VARIABLES.csv'):
|
||||
os.remove('VARIABLES.csv')
|
||||
if os.path.exists('Config0.c'):
|
||||
os.remove('Config0.c')
|
||||
if os.path.exists('Config0.h'):
|
||||
os.remove('Config0.h')
|
||||
if os.path.exists('Res0.c'):
|
||||
os.remove('Res0.c')
|
||||
else:
|
||||
print("Error: iec2c compiler not found!")
|
||||
quit()
|
||||
|
||||
#Setup environment
|
||||
print("Configuring environment...")
|
||||
if (os.name == 'nt'):
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 core install arduino:avr')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 core install arduino:samd')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 core install arduino:megaavr')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 core install arduino:mbed_portenta')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 lib install ArduinoModbus')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('..\\bin\\arduino-cli-w32 lib install Arduino_MachineControl')
|
||||
print(env_setup.read())
|
||||
|
||||
else:
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 core install arduino:avr')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 core install arduino:samd')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 core install arduino:megaavr')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 core install arduino:mbed_portenta')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 lib install ArduinoModbus')
|
||||
print(env_setup.read())
|
||||
env_setup = os.popen('../bin/arduino-cli-l64 lib install Arduino_MachineControl')
|
||||
print(env_setup.read())
|
||||
|
||||
|
||||
#Generate C files
|
||||
print("Compiling .st file...")
|
||||
if (os.name == 'nt'):
|
||||
compilation = os.popen('..\\bin\\iec2c.exe ' + st_file)
|
||||
else:
|
||||
compilation = os.popen('../bin/iec2c ' + st_file)
|
||||
print(compilation.read())
|
||||
|
||||
#Generate glueVars.c
|
||||
if not (os.path.exists("LOCATED_VARIABLES.h")):
|
||||
print("Error: Couldn't find LOCATED_VARIABLES.h. Check iec2c compiler output for more information")
|
||||
quit()
|
||||
|
||||
located_vars_file = open('LOCATED_VARIABLES.h', 'r')
|
||||
located_vars = located_vars_file.readlines()
|
||||
|
||||
glueVars = """
|
||||
#include "iec_std_lib.h"
|
||||
|
||||
#define __LOCATED_VAR(type, name, ...) type __##name;
|
||||
#include "LOCATED_VARIABLES.h"
|
||||
#undef __LOCATED_VAR
|
||||
#define __LOCATED_VAR(type, name, ...) type* name = &__##name;
|
||||
#include "LOCATED_VARIABLES.h"
|
||||
#undef __LOCATED_VAR
|
||||
|
||||
TIME __CURRENT_TIME;
|
||||
extern unsigned long long common_ticktime__;
|
||||
|
||||
//OpenPLC Buffers
|
||||
//Booleans
|
||||
IEC_BOOL *bool_input[2][8];
|
||||
IEC_BOOL *bool_output[2][8];
|
||||
IEC_UINT *int_input[16];
|
||||
IEC_UINT *int_output[16];
|
||||
void glueVars()
|
||||
{
|
||||
"""
|
||||
|
||||
for located_var in located_vars:
|
||||
#cleanup located var line
|
||||
if ('__LOCATED_VAR(' in located_var):
|
||||
located_var = located_var.split('(')[1].split(')')[0]
|
||||
var_data = located_var.split(',')
|
||||
if (len(var_data) < 5):
|
||||
print('Error processing located var line: ' + located_var)
|
||||
else:
|
||||
var_type = var_data[0]
|
||||
var_name = var_data[1]
|
||||
var_address = var_data[4]
|
||||
var_subaddress = '0'
|
||||
if (len(var_data) > 5):
|
||||
var_subaddress = var_data[5]
|
||||
|
||||
#check variable type and assign to correct buffer pointer
|
||||
if ('QX' in var_name):
|
||||
if (int(var_address) > 2 or int(var_subaddress) > 7):
|
||||
print('Error: wrong location for var ' + var_name)
|
||||
quit()
|
||||
glueVars += ' bool_output[' + var_address + '][' + var_subaddress + '] = ' + var_name + ';\n'
|
||||
elif ('IX' in var_name):
|
||||
if (int(var_address) > 2 or int(var_subaddress) > 7):
|
||||
print('Error: wrong location for var ' + var_name)
|
||||
quit()
|
||||
glueVars += ' bool_input[' + var_address + '][' + var_subaddress + '] = ' + var_name + ';\n'
|
||||
elif ('QW' in var_name):
|
||||
if (int(var_address) > 16):
|
||||
print('Error: wrong location for var ' + var_name)
|
||||
quit()
|
||||
glueVars += ' int_output[' + var_address + '] = ' + var_name + ';\n'
|
||||
elif ('IW' in var_name):
|
||||
if (int(var_address) > 16):
|
||||
print('Error: wrong location for var ' + var_name)
|
||||
quit()
|
||||
glueVars += ' int_input[' + var_address + '] = ' + var_name + ';\n'
|
||||
else:
|
||||
print('Could not process location "' + var_name + '" from line: ' + located_var)
|
||||
quit()
|
||||
|
||||
glueVars += """
|
||||
}
|
||||
|
||||
void updateTime()
|
||||
{
|
||||
__CURRENT_TIME.tv_nsec += common_ticktime__;
|
||||
|
||||
if (__CURRENT_TIME.tv_nsec >= 1000000000)
|
||||
{
|
||||
__CURRENT_TIME.tv_nsec -= 1000000000;
|
||||
__CURRENT_TIME.tv_sec += 1;
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
f = open('glueVars.c', 'w')
|
||||
f.write(glueVars)
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
time.sleep(2) #make sure glueVars.c was written to disk
|
||||
|
||||
# Patch POUS.c to include POUS.h
|
||||
f = open('POUS.c', 'r')
|
||||
pous_c = '#include "POUS.h"\n\n' + f.read()
|
||||
f.close()
|
||||
|
||||
f = open('POUS.c', 'w')
|
||||
f.write(pous_c)
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
# Patch Res0.c to include POUS.h instead of POUS.c
|
||||
f = open('Res0.c', 'r')
|
||||
res0_c = ''
|
||||
lines = f.readlines()
|
||||
for line in lines:
|
||||
if '#include "POUS.c"' in line:
|
||||
res0_c += '#include "POUS.h"\n'
|
||||
else:
|
||||
res0_c += line
|
||||
f.close()
|
||||
|
||||
f = open('Res0.c', 'w')
|
||||
f.write(res0_c)
|
||||
f.flush()
|
||||
f.close()
|
||||
|
||||
#Generate .elf file
|
||||
print("Generating binary file...")
|
||||
if (os.name == 'nt'):
|
||||
compilation = os.popen('..\\bin\\arduino-cli-w32 compile -v --libraries=..\\..\\ --build-property compiler.c.extra_flags="-I..\\src\\lib" --build-property compiler.cpp.extra_flags="-I..\\src\\lib" --export-binaries -b ' + platform + ' ..\\examples\\Baremetal\\Baremetal.ino')
|
||||
else:
|
||||
compilation = os.popen('../bin/arduino-cli-l64 compile -v --libraries=../../ --build-property compiler.c.extra_flags="-I../src/lib" --build-property compiler.cpp.extra_flags="-I../src/lib" --export-binaries -b ' + platform + ' ../examples/Baremetal/Baremetal.ino')
|
||||
print(compilation.read())
|
||||
if (port != None):
|
||||
if (os.name == 'nt'):
|
||||
uploading = os.popen('..\\bin\\arduino-cli-w32 upload --port ' + port + ' --fqbn ' + platform + ' ..\\examples\\Baremetal/')
|
||||
else:
|
||||
uploading = os.popen('../bin/arduino-cli-l64 upload --port ' + port + ' --fqbn ' + platform + ' ../examples/Baremetal/')
|
||||
print(uploading.read())
|
||||
|
||||
#print("No clean up")
|
||||
#quit()
|
||||
|
||||
if (os.name != 'nt'):
|
||||
print("Cleaning up...")
|
||||
if os.path.exists('POUS.c'):
|
||||
os.remove('POUS.c')
|
||||
if os.path.exists('POUS.h'):
|
||||
os.remove('POUS.h')
|
||||
if os.path.exists('LOCATED_VARIABLES.h'):
|
||||
os.remove('LOCATED_VARIABLES.h')
|
||||
if os.path.exists('VARIABLES.csv'):
|
||||
os.remove('VARIABLES.csv')
|
||||
if os.path.exists('Config0.c'):
|
||||
os.remove('Config0.c')
|
||||
if os.path.exists('Config0.h'):
|
||||
os.remove('Config0.h')
|
||||
if os.path.exists('Config0.o'):
|
||||
os.remove('Config0.o')
|
||||
if os.path.exists('Res0.c'):
|
||||
os.remove('Res0.c')
|
||||
if os.path.exists('Res0.o'):
|
||||
os.remove('Res0.o')
|
||||
if os.path.exists('glueVars.c'):
|
||||
os.remove('glueVars.c')
|
||||
|
||||
|
||||
|
227
editor/arduino/src/debug.c
Executable file
227
editor/arduino/src/debug.c
Executable file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* This file is part of OpenPLC Runtime
|
||||
*
|
||||
* Copyright (C) 2023 Autonomy, GP Orcullo
|
||||
* Based on the work by GP Orcullo on Beremiz for uC
|
||||
*
|
||||
* 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
|
||||
* of the License, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "iec_types_all.h"
|
||||
#include "POUS.h"
|
||||
|
||||
#define SAME_ENDIANNESS 0
|
||||
#define REVERSE_ENDIANNESS 1
|
||||
|
||||
uint8_t endianness;
|
||||
|
||||
|
||||
extern PROGRAM0 RES0__INSTANCE0;
|
||||
|
||||
static const struct {
|
||||
void *ptr;
|
||||
__IEC_types_enum type;
|
||||
} debug_vars[] = {
|
||||
{&(RES0__INSTANCE0.BUTTON), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.TIMER_OUT), BOOL_O_ENUM},
|
||||
{&(RES0__INSTANCE0.COUNTER_VALUE), INT_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.EN), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.ENO), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.IN1), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.IN3), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.IN2), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.IN_TIME), TIME_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.OUT1), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.OUT2), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.OUT3), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.ERROR), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.STARTED_TIMER_1), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TIMER_1_INPUT), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.STARTED_TIMER_2), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TIMER_2_INPUT), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.EN), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.ENO), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.IN), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.PT), TIME_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.Q), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.ET), TIME_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.STATE), SINT_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.PREV_IN), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.CURRENT_TIME), TIME_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF1.START_TIME), TIME_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.EN), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.ENO), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.IN), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.PT), TIME_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.Q), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.ET), TIME_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.STATE), SINT_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.PREV_IN), BOOL_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.CURRENT_TIME), TIME_ENUM},
|
||||
{&(RES0__INSTANCE0.PT20.TOF2.START_TIME), TIME_ENUM},
|
||||
};
|
||||
|
||||
#define VAR_COUNT 37
|
||||
|
||||
uint16_t get_var_count(void)
|
||||
{
|
||||
return VAR_COUNT;
|
||||
}
|
||||
|
||||
size_t get_var_size(size_t idx)
|
||||
{
|
||||
switch (debug_vars[idx].type) {
|
||||
case BOOL_ENUM:
|
||||
case BOOL_O_ENUM:
|
||||
return sizeof(BOOL);
|
||||
case TIME_ENUM:
|
||||
return sizeof(TIME);
|
||||
case INT_ENUM:
|
||||
return sizeof(INT);
|
||||
case SINT_ENUM:
|
||||
return sizeof(SINT);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void *get_var_addr(size_t idx)
|
||||
{
|
||||
void *ptr = debug_vars[idx].ptr;
|
||||
|
||||
switch (debug_vars[idx].type) {
|
||||
case BOOL_ENUM:
|
||||
return (void *)&((__IEC_BOOL_t *) ptr)->value;
|
||||
case BOOL_O_ENUM:
|
||||
return (void *)((((__IEC_BOOL_p *) ptr)->flags & __IEC_FORCE_FLAG)
|
||||
? &(((__IEC_BOOL_p *) ptr)->fvalue)
|
||||
: ((__IEC_BOOL_p *) ptr)->value);
|
||||
case TIME_ENUM:
|
||||
return (void *)&((__IEC_TIME_t *) ptr)->value;
|
||||
case INT_ENUM:
|
||||
return (void *)&((__IEC_INT_t *) ptr)->value;
|
||||
case SINT_ENUM:
|
||||
return (void *)&((__IEC_SINT_t *) ptr)->value;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void force_var(size_t idx, bool forced, void *val)
|
||||
{
|
||||
void *ptr = debug_vars[idx].ptr;
|
||||
|
||||
if (forced) {
|
||||
size_t var_size = get_var_size(idx);
|
||||
switch (debug_vars[idx].type) {
|
||||
case BOOL_ENUM: {
|
||||
memcpy(&((__IEC_BOOL_t *) ptr)->value, val, var_size);
|
||||
//((__IEC_BOOL_t *) ptr)->value = *((BOOL *) val);
|
||||
((__IEC_BOOL_t *) ptr)->flags |= __IEC_FORCE_FLAG;
|
||||
break;
|
||||
}
|
||||
case BOOL_O_ENUM: {
|
||||
memcpy((((__IEC_BOOL_p *) ptr)->value), val, var_size);
|
||||
//*(((__IEC_BOOL_p *) ptr)->value) = *((BOOL *) val);
|
||||
((__IEC_BOOL_p *) ptr)->flags |= __IEC_FORCE_FLAG;
|
||||
break;
|
||||
}
|
||||
case TIME_ENUM: {
|
||||
memcpy(&((__IEC_TIME_t *) ptr)->value, val, var_size);
|
||||
//((__IEC_TIME_t *) ptr)->value = *((TIME *) val);
|
||||
((__IEC_TIME_t *) ptr)->flags |= __IEC_FORCE_FLAG;
|
||||
break;
|
||||
}
|
||||
case INT_ENUM: {
|
||||
memcpy(&((__IEC_INT_t *) ptr)->value, val, var_size);
|
||||
//((__IEC_INT_t *) ptr)->value = *((INT *) val);
|
||||
((__IEC_INT_t *) ptr)->flags |= __IEC_FORCE_FLAG;
|
||||
break;
|
||||
}
|
||||
case SINT_ENUM: {
|
||||
memcpy(&((__IEC_SINT_t *) ptr)->value, val, var_size);
|
||||
//((__IEC_SINT_t *) ptr)->value = *((SINT *) val);
|
||||
((__IEC_SINT_t *) ptr)->flags |= __IEC_FORCE_FLAG;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (debug_vars[idx].type) {
|
||||
case BOOL_ENUM:
|
||||
((__IEC_BOOL_t *) ptr)->flags &= ~__IEC_FORCE_FLAG;
|
||||
break;
|
||||
case BOOL_O_ENUM:
|
||||
((__IEC_BOOL_p *) ptr)->flags &= ~__IEC_FORCE_FLAG;
|
||||
break;
|
||||
case TIME_ENUM:
|
||||
((__IEC_TIME_t *) ptr)->flags &= ~__IEC_FORCE_FLAG;
|
||||
break;
|
||||
case INT_ENUM:
|
||||
((__IEC_INT_t *) ptr)->flags &= ~__IEC_FORCE_FLAG;
|
||||
break;
|
||||
case SINT_ENUM:
|
||||
((__IEC_SINT_t *) ptr)->flags &= ~__IEC_FORCE_FLAG;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void swap_bytes(void *ptr, size_t size)
|
||||
{
|
||||
uint8_t *bytePtr = (uint8_t *)ptr;
|
||||
size_t i;
|
||||
for (i = 0; i < size / 2; ++i)
|
||||
{
|
||||
uint8_t temp = bytePtr[i];
|
||||
bytePtr[i] = bytePtr[size - 1 - i];
|
||||
bytePtr[size - 1 - i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void trace_reset(void)
|
||||
{
|
||||
for (size_t i=0; i < VAR_COUNT; i++)
|
||||
{
|
||||
force_var(i, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void set_trace(size_t idx, bool forced, void *val)
|
||||
{
|
||||
if (idx >= 0 && idx < VAR_COUNT)
|
||||
{
|
||||
if (endianness == REVERSE_ENDIANNESS)
|
||||
{
|
||||
// Aaaaarghhhh... Stupid AVR is Big Endian.
|
||||
swap_bytes(val, get_var_size(idx));
|
||||
}
|
||||
|
||||
force_var(idx, forced, val);
|
||||
}
|
||||
}
|
||||
|
||||
void set_endianness(uint8_t value)
|
||||
{
|
||||
if (value == SAME_ENDIANNESS || value == REVERSE_ENDIANNESS)
|
||||
{
|
||||
endianness = value;
|
||||
}
|
||||
}
|
201
editor/arduino/src/debug.c.j2
Executable file
201
editor/arduino/src/debug.c.j2
Executable file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* This file is part of OpenPLC Runtime
|
||||
*
|
||||
* Copyright (C) 2023 Autonomy, GP Orcullo
|
||||
* Based on the work by GP Orcullo on Beremiz for uC
|
||||
*
|
||||
* 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
|
||||
* of the License, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "iec_types_all.h"
|
||||
#include "POUS.h"
|
||||
|
||||
#define SAME_ENDIANNESS 0
|
||||
#define REVERSE_ENDIANNESS 1
|
||||
|
||||
uint8_t endianness;
|
||||
|
||||
{% for v in debug.externs %}
|
||||
{{ v }}
|
||||
{%- endfor %}
|
||||
|
||||
static const struct {
|
||||
void *ptr;
|
||||
__IEC_types_enum type;
|
||||
} debug_vars[] = {
|
||||
{%- for v in debug.vars %}
|
||||
{{ v }},
|
||||
{%- endfor %}
|
||||
};
|
||||
|
||||
#define VAR_COUNT {{ debug.vars | length }}
|
||||
|
||||
uint16_t get_var_count(void)
|
||||
{
|
||||
return VAR_COUNT;
|
||||
}
|
||||
|
||||
size_t get_var_size(size_t idx)
|
||||
{
|
||||
switch (debug_vars[idx].type) {
|
||||
{%- for t in debug.types -%}
|
||||
{% if '{}_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_ENUM:
|
||||
{%- endif %}
|
||||
{%- if '{}_O_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_O_ENUM:
|
||||
{%- endif %}
|
||||
{%- if '{}_P_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_P_ENUM:
|
||||
{%- endif %}
|
||||
return sizeof({{ t }});
|
||||
{%- endfor %}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void *get_var_addr(size_t idx)
|
||||
{
|
||||
void *ptr = debug_vars[idx].ptr;
|
||||
|
||||
switch (debug_vars[idx].type) {
|
||||
{%- for t in debug.types -%}
|
||||
{% if '{}_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_ENUM:
|
||||
return (void *)&((__IEC_{{ t }}_t *) ptr)->value;
|
||||
{%- endif %}
|
||||
{%- if '{}_O_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_O_ENUM:
|
||||
{%- endif %}
|
||||
{%- if '{}_P_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_P_ENUM:
|
||||
{%- endif %}
|
||||
{%- if '{}_O_ENUM'.format(t) in debug.enums or '{}_P_ENUM'.format(t) in debug.enums %}
|
||||
return (void *)((((__IEC_{{ t }}_p *) ptr)->flags & __IEC_FORCE_FLAG)
|
||||
? &(((__IEC_{{ t }}_p *) ptr)->fvalue)
|
||||
: ((__IEC_{{ t }}_p *) ptr)->value);
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void force_var(size_t idx, bool forced, void *val)
|
||||
{
|
||||
void *ptr = debug_vars[idx].ptr;
|
||||
|
||||
if (forced) {
|
||||
size_t var_size = get_var_size(idx);
|
||||
switch (debug_vars[idx].type) {
|
||||
{%- for t in debug.types -%}
|
||||
{% if '{}_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_ENUM: {
|
||||
memcpy(&((__IEC_{{ t }}_t *) ptr)->value, val, var_size);
|
||||
//((__IEC_{{ t }}_t *) ptr)->value = *(({{ t }} *) val);
|
||||
((__IEC_{{ t }}_t *) ptr)->flags |= __IEC_FORCE_FLAG;
|
||||
break;
|
||||
}
|
||||
{%- endif %}
|
||||
{%- if '{}_O_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_O_ENUM: {
|
||||
memcpy((((__IEC_{{ t }}_p *) ptr)->value), val, var_size);
|
||||
//*(((__IEC_{{ t }}_p *) ptr)->value) = *(({{ t }} *) val);
|
||||
((__IEC_{{ t }}_p *) ptr)->flags |= __IEC_FORCE_FLAG;
|
||||
break;
|
||||
}
|
||||
{%- endif %}
|
||||
{%- if '{}_P_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_P_ENUM: {
|
||||
memcpy(&((__IEC_{{ t }}_p *) ptr)->fvalue, val, var_size);
|
||||
//((__IEC_{{ t }}_p *) ptr)->fvalue = *(({{ t }} *) val);
|
||||
((__IEC_{{ t }}_p *) ptr)->flags |= __IEC_FORCE_FLAG;
|
||||
break;
|
||||
}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (debug_vars[idx].type) {
|
||||
{%- for t in debug.types -%}
|
||||
{% if '{}_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_ENUM:
|
||||
((__IEC_{{ t }}_t *) ptr)->flags &= ~__IEC_FORCE_FLAG;
|
||||
break;
|
||||
{%- endif %}
|
||||
{%- if '{}_O_ENUM'.format(t) in debug.enums or '{}_P_ENUM'.format(t) in debug.enums %}
|
||||
{%- if '{}_O_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_O_ENUM:
|
||||
{%- endif %}
|
||||
{%- if '{}_P_ENUM'.format(t) in debug.enums %}
|
||||
case {{ t }}_P_ENUM:
|
||||
{%- endif %}
|
||||
((__IEC_{{ t }}_p *) ptr)->flags &= ~__IEC_FORCE_FLAG;
|
||||
break;
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void swap_bytes(void *ptr, size_t size)
|
||||
{
|
||||
uint8_t *bytePtr = (uint8_t *)ptr;
|
||||
size_t i;
|
||||
for (i = 0; i < size / 2; ++i)
|
||||
{
|
||||
uint8_t temp = bytePtr[i];
|
||||
bytePtr[i] = bytePtr[size - 1 - i];
|
||||
bytePtr[size - 1 - i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void trace_reset(void)
|
||||
{
|
||||
for (size_t i=0; i < VAR_COUNT; i++)
|
||||
{
|
||||
force_var(i, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void set_trace(size_t idx, bool forced, void *val)
|
||||
{
|
||||
if (idx >= 0 && idx < VAR_COUNT)
|
||||
{
|
||||
if (endianness == REVERSE_ENDIANNESS)
|
||||
{
|
||||
// Aaaaarghhhh... Stupid AVR is Big Endian.
|
||||
swap_bytes(val, get_var_size(idx));
|
||||
}
|
||||
|
||||
force_var(idx, forced, val);
|
||||
}
|
||||
}
|
||||
|
||||
void set_endianness(uint8_t value)
|
||||
{
|
||||
if (value == SAME_ENDIANNESS || value == REVERSE_ENDIANNESS)
|
||||
{
|
||||
endianness = value;
|
||||
}
|
||||
}
|
||||
|
23
editor/arduino/src/debug.h
Executable file
23
editor/arduino/src/debug.h
Executable file
@ -0,0 +1,23 @@
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
void set_endianness(uint8_t value);
|
||||
|
||||
uint16_t get_var_count(void);
|
||||
|
||||
//__attribute__((weak))
|
||||
size_t get_var_size(size_t);// {return 0;}
|
||||
|
||||
//__attribute__((weak))
|
||||
void *get_var_addr(size_t);// {return 0;}
|
||||
|
||||
//__attribute__((weak))
|
||||
void force_var(size_t, bool, void *);// {}
|
||||
|
||||
//__attribute__((weak))
|
||||
void set_trace(size_t, bool, void *);// {}
|
||||
|
||||
//__attribute__((weak))
|
||||
void trace_reset(void);// {}
|
||||
|
||||
#endif
|
1
editor/arduino/src/glueVars.c
Normal file → Executable file
1
editor/arduino/src/glueVars.c
Normal file → Executable file
@ -36,6 +36,7 @@ IEC_UINT *int_output[MAX_ANALOG_OUTPUT];
|
||||
|
||||
void glueVars()
|
||||
{
|
||||
bool_output[0][0] = __QX0_0;
|
||||
|
||||
}
|
||||
|
||||
|
0
editor/arduino/src/hal/arduino_opta.cpp
Normal file → Executable file
0
editor/arduino/src/hal/arduino_opta.cpp
Normal file → Executable file
0
editor/arduino/src/hal/controllino_maxi.cpp
Normal file → Executable file
0
editor/arduino/src/hal/controllino_maxi.cpp
Normal file → Executable file
8
editor/arduino/src/hal/controllino_maxi.hal
Normal file → Executable file
8
editor/arduino/src/hal/controllino_maxi.hal
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
CONTROLLINO MAXI, CONTROLLINO_Boards:avr:controllino_maxi
|
0
editor/arduino/src/hal/controllino_maxi_automation.cpp
Normal file → Executable file
0
editor/arduino/src/hal/controllino_maxi_automation.cpp
Normal file → Executable file
8
editor/arduino/src/hal/controllino_maxi_automation.hal
Normal file → Executable file
8
editor/arduino/src/hal/controllino_maxi_automation.hal
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
CONTROLLINO MAXI Automation, CONTROLLINO_Boards:avr:controllino_maxi_automation
|
0
editor/arduino/src/hal/controllino_mega.cpp
Normal file → Executable file
0
editor/arduino/src/hal/controllino_mega.cpp
Normal file → Executable file
8
editor/arduino/src/hal/controllino_mega.hal
Normal file → Executable file
8
editor/arduino/src/hal/controllino_mega.hal
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
CONTROLLINO MEGA, CONTROLLINO_Boards:avr:controllino_mega
|
0
editor/arduino/src/hal/controllino_mini.cpp
Normal file → Executable file
0
editor/arduino/src/hal/controllino_mini.cpp
Normal file → Executable file
8
editor/arduino/src/hal/controllino_mini.hal
Normal file → Executable file
8
editor/arduino/src/hal/controllino_mini.hal
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
CONTROLLINO MINI, CONTROLLINO_Boards:avr:controllino_mini
|
212
editor/arduino/src/hal/edge_control.cpp
Normal file → Executable file
212
editor/arduino/src/hal/edge_control.cpp
Normal file → Executable file
@ -1,106 +1,106 @@
|
||||
#include <stdlib.h>
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
}
|
||||
#include "Arduino.h"
|
||||
#include "../examples/Baremetal/defines.h"
|
||||
|
||||
#include <Arduino_EdgeControl.h>
|
||||
|
||||
//OpenPLC HAL for Arduino Edge Control
|
||||
|
||||
/******************PINOUT CONFIGURATION***********************
|
||||
Digital In: IRQ_CH1, IRQ_CH2, IRQ_CH3, IRQ_CH4, IRQ_CH5, IRQ_CH6 (%IX0.0 - %IX0.5)
|
||||
Digital Out: RELAY_CH01, RELAY_CH02, RELAY_CH03, RELAY_CH04 (%QX0.0 - %QX0.3)
|
||||
Analog In: INPUT_420mA_CH01, INPUT_420mA_CH02, INPUT_420mA_CH03, INPUT_420mA_CH04 (%IW0 - %IW3)
|
||||
INPUT_05V_CH01, INPUT_05V_CH02, INPUT_05V_CH03, INPUT_05V_CH04 (%IW4 - %IW7)
|
||||
INPUT_05V_CH05, INPUT_05V_CH06, INPUT_05V_CH07, INPUT_05V_CH08 (%IW8 - %IW11)
|
||||
Analog Out:
|
||||
**************************************************************/
|
||||
|
||||
//Create the I/O pin masks
|
||||
uint8_t pinMask_DIN[] = {PINMASK_DIN};
|
||||
uint8_t pinMask_AIN[] = {PINMASK_AIN};
|
||||
uint8_t pinMask_DOUT[] = {PINMASK_DOUT};
|
||||
uint8_t pinMask_AOUT[] = {PINMASK_AOUT};
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
EdgeControl.begin();
|
||||
//Enables Power
|
||||
Power.enable3V3();
|
||||
Power.enable5V();
|
||||
|
||||
//Start IO expansion
|
||||
//Wire.begin();
|
||||
//Expander.begin();
|
||||
//while (!Expander) {delay(1);}
|
||||
//Input.begin();
|
||||
//Input.enable();
|
||||
//analogReadResolution(12);
|
||||
Relay.begin();
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_DIN[i], INPUT);
|
||||
}
|
||||
|
||||
//for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
//{
|
||||
// pinMode(pinMask_AIN[i], INPUT);
|
||||
//}
|
||||
|
||||
//for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
//{
|
||||
// pinMode(pinMask_DOUT[i], OUTPUT);
|
||||
//}
|
||||
|
||||
//for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
//{
|
||||
// pinMode(pinMask_AOUT[i], OUTPUT);
|
||||
//}
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
if (bool_input[i/8][i%8] != NULL)
|
||||
*bool_input[i/8][i%8] = digitalRead(pinMask_DIN[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
if (int_input[i] != NULL)
|
||||
*int_input[i] = (Input.analogRead(pinMask_AIN[i]));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void updateOutputBuffers()
|
||||
{
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
if (bool_output[i/8][i%8] != NULL)
|
||||
{
|
||||
if (*bool_output[i/8][i%8])
|
||||
{
|
||||
Relay.on(pinMask_DOUT[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Relay.off(pinMask_DOUT[i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
if (int_output[i] != NULL)
|
||||
analogWrite(pinMask_AOUT[i], (*int_output[i] / 256));
|
||||
}
|
||||
*/
|
||||
}
|
||||
#include <stdlib.h>
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
}
|
||||
#include "Arduino.h"
|
||||
#include "../examples/Baremetal/defines.h"
|
||||
|
||||
#include <Arduino_EdgeControl.h>
|
||||
|
||||
//OpenPLC HAL for Arduino Edge Control
|
||||
|
||||
/******************PINOUT CONFIGURATION***********************
|
||||
Digital In: IRQ_CH1, IRQ_CH2, IRQ_CH3, IRQ_CH4, IRQ_CH5, IRQ_CH6 (%IX0.0 - %IX0.5)
|
||||
Digital Out: RELAY_CH01, RELAY_CH02, RELAY_CH03, RELAY_CH04 (%QX0.0 - %QX0.3)
|
||||
Analog In: INPUT_420mA_CH01, INPUT_420mA_CH02, INPUT_420mA_CH03, INPUT_420mA_CH04 (%IW0 - %IW3)
|
||||
INPUT_05V_CH01, INPUT_05V_CH02, INPUT_05V_CH03, INPUT_05V_CH04 (%IW4 - %IW7)
|
||||
INPUT_05V_CH05, INPUT_05V_CH06, INPUT_05V_CH07, INPUT_05V_CH08 (%IW8 - %IW11)
|
||||
Analog Out:
|
||||
**************************************************************/
|
||||
|
||||
//Create the I/O pin masks
|
||||
uint8_t pinMask_DIN[] = {PINMASK_DIN};
|
||||
uint8_t pinMask_AIN[] = {PINMASK_AIN};
|
||||
uint8_t pinMask_DOUT[] = {PINMASK_DOUT};
|
||||
uint8_t pinMask_AOUT[] = {PINMASK_AOUT};
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
EdgeControl.begin();
|
||||
//Enables Power
|
||||
Power.enable3V3();
|
||||
Power.enable5V();
|
||||
|
||||
//Start IO expansion
|
||||
//Wire.begin();
|
||||
//Expander.begin();
|
||||
//while (!Expander) {delay(1);}
|
||||
//Input.begin();
|
||||
//Input.enable();
|
||||
//analogReadResolution(12);
|
||||
Relay.begin();
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_DIN[i], INPUT);
|
||||
}
|
||||
|
||||
//for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
//{
|
||||
// pinMode(pinMask_AIN[i], INPUT);
|
||||
//}
|
||||
|
||||
//for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
//{
|
||||
// pinMode(pinMask_DOUT[i], OUTPUT);
|
||||
//}
|
||||
|
||||
//for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
//{
|
||||
// pinMode(pinMask_AOUT[i], OUTPUT);
|
||||
//}
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
if (bool_input[i/8][i%8] != NULL)
|
||||
*bool_input[i/8][i%8] = digitalRead(pinMask_DIN[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
if (int_input[i] != NULL)
|
||||
*int_input[i] = (Input.analogRead(pinMask_AIN[i]));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void updateOutputBuffers()
|
||||
{
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
if (bool_output[i/8][i%8] != NULL)
|
||||
{
|
||||
if (*bool_output[i/8][i%8])
|
||||
{
|
||||
Relay.on(pinMask_DOUT[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Relay.off(pinMask_DOUT[i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
if (int_output[i] != NULL)
|
||||
analogWrite(pinMask_AOUT[i], (*int_output[i] / 256));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
109
editor/arduino/src/hal/esp32.cpp
Normal file → Executable file
109
editor/arduino/src/hal/esp32.cpp
Normal file → Executable file
@ -1,10 +1,12 @@
|
||||
#include <stdlib.h>
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
#include "openplc.h"
|
||||
}
|
||||
#include "Arduino.h"
|
||||
#include "../examples/Baremetal/defines.h"
|
||||
|
||||
#include "ESP32_FastPWM.h"
|
||||
|
||||
//OpenPLC HAL for ESP32 boards
|
||||
|
||||
/******************PINOUT CONFIGURATION**************************
|
||||
@ -22,6 +24,43 @@ uint8_t pinMask_AIN[] = {PINMASK_AIN};
|
||||
uint8_t pinMask_DOUT[] = {PINMASK_DOUT};
|
||||
uint8_t pinMask_AOUT[] = {PINMASK_AOUT};
|
||||
|
||||
#define PWM_DEFAULT_FREQ 490
|
||||
|
||||
#define NUM_OF_PWM_PINS 8 //only 8 pins possible with independent frequency
|
||||
|
||||
#define PWM_CHANNEL_0_PIN 4
|
||||
#define PWM_CHANNEL_1_PIN 13
|
||||
#define PWM_CHANNEL_2_PIN 18
|
||||
#define PWM_CHANNEL_3_PIN 19
|
||||
#define PWM_CHANNEL_4_PIN 21
|
||||
#define PWM_CHANNEL_5_PIN 22
|
||||
#define PWM_CHANNEL_6_PIN 32
|
||||
#define PWM_CHANNEL_7_PIN 33
|
||||
|
||||
#define TIMER_CHANNEL_0 0
|
||||
#define TIMER_CHANNEL_1 2
|
||||
#define TIMER_CHANNEL_2 4
|
||||
#define TIMER_CHANNEL_3 6
|
||||
#define TIMER_CHANNEL_4 8
|
||||
#define TIMER_CHANNEL_5 10
|
||||
#define TIMER_CHANNEL_6 12
|
||||
#define TIMER_CHANNEL_7 14
|
||||
|
||||
#define PWM_RESOLUTION 12 //12-bit
|
||||
|
||||
|
||||
ESP32_FAST_PWM *PWM_Instance[NUM_OF_PWM_PINS];
|
||||
|
||||
const uint8_t pins[] = {PWM_CHANNEL_0_PIN, PWM_CHANNEL_1_PIN, PWM_CHANNEL_2_PIN, PWM_CHANNEL_3_PIN,
|
||||
PWM_CHANNEL_4_PIN, PWM_CHANNEL_5_PIN, PWM_CHANNEL_6_PIN, PWM_CHANNEL_7_PIN};
|
||||
|
||||
const uint8_t timers[] = {TIMER_CHANNEL_0, TIMER_CHANNEL_1, TIMER_CHANNEL_2, TIMER_CHANNEL_3,
|
||||
TIMER_CHANNEL_4, TIMER_CHANNEL_5, TIMER_CHANNEL_6, TIMER_CHANNEL_7};
|
||||
|
||||
extern "C" uint8_t set_hardware_pwm(uint8_t, float, float); //this call is required for the C-based PWM block on the Editor
|
||||
|
||||
bool pwm_initialized = false;
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
@ -45,6 +84,74 @@ void hardwareInit()
|
||||
}
|
||||
}
|
||||
|
||||
void init_pwm()
|
||||
{
|
||||
// Initialize PWM pins
|
||||
for (int i = 0; i < NUM_OF_PWM_PINS; i++)
|
||||
{
|
||||
PWM_Instance[i] = new ESP32_FAST_PWM(pins[i], PWM_DEFAULT_FREQ, 0, timers[i], PWM_RESOLUTION); //12 bit resolution
|
||||
|
||||
// disable digital in pins if PWM_CONTROLLER block is being used
|
||||
for (int j = 0; j < NUM_DISCRETE_INPUT; j++)
|
||||
{
|
||||
if (pinMask_DIN[j] == pins[i])
|
||||
{
|
||||
pinMask_DIN[j] = 255; //disable pin
|
||||
}
|
||||
}
|
||||
|
||||
// disable digital out pins if PWM_CONTROLLER block is being used
|
||||
for (int j = 0; j < NUM_DISCRETE_OUTPUT; j++)
|
||||
{
|
||||
if (pinMask_DOUT[j] == pins[i])
|
||||
{
|
||||
pinMask_DOUT[j] = 255; //disable pin
|
||||
}
|
||||
}
|
||||
|
||||
// disable analog in pins if PWM_CONTROLLER block is being used
|
||||
for (int j = 0; j < NUM_ANALOG_INPUT; j++)
|
||||
{
|
||||
if (pinMask_AIN[j] == pins[i])
|
||||
{
|
||||
pinMask_AIN[j] = 255; //disable pin
|
||||
}
|
||||
}
|
||||
|
||||
// disable analog out pins if PWM_CONTROLLER block is being used
|
||||
for (int j = 0; j < NUM_ANALOG_OUTPUT; j++)
|
||||
{
|
||||
if (pinMask_AOUT[j] == pins[i])
|
||||
{
|
||||
pinMask_AOUT[j] = 255; //disable pin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t set_hardware_pwm(uint8_t ch, float freq, float duty)
|
||||
{
|
||||
|
||||
if (pwm_initialized == false)
|
||||
{
|
||||
init_pwm();
|
||||
pwm_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
if (ch >= NUM_OF_PWM_PINS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PWM_Instance[ch]->setPWM(pins[ch], freq, duty))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
|
16
editor/arduino/src/hal/esp32.hal
Normal file → Executable file
16
editor/arduino/src/hal/esp32.hal
Normal file → Executable file
@ -1,8 +1,8 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN, BOARD definition (optional)
|
||||
|
||||
ESP32, esp32:esp32:esp32, BOARD_ESP32
|
||||
ESP32-S2, esp32:esp32:esp32s2, BOARD_ESP32
|
||||
ESP32-C3, esp32:esp32:esp32c3, BOARD_ESP32
|
||||
ESP32-DOIT DEVKIT V1, esp32:esp32:esp32doit-devkit-v1, BOARD_ESP32
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN, BOARD definition (optional)
|
||||
|
||||
ESP32, esp32:esp32:esp32, BOARD_ESP32
|
||||
ESP32-S2, esp32:esp32:esp32s2, BOARD_ESP32
|
||||
ESP32-C3, esp32:esp32:esp32c3, BOARD_ESP32
|
||||
ESP32-DOIT DEVKIT V1, esp32:esp32:esp32doit-devkit-v1, BOARD_ESP32
|
||||
|
0
editor/arduino/src/hal/esp8266.cpp
Normal file → Executable file
0
editor/arduino/src/hal/esp8266.cpp
Normal file → Executable file
12
editor/arduino/src/hal/esp8266.hal
Normal file → Executable file
12
editor/arduino/src/hal/esp8266.hal
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
ESP8266 NodeMCU, esp8266:esp8266:nodemcuv2, BOARD_ESP8266
|
||||
ESP8266 D1-mini, esp8266:esp8266:d1_mini, BOARD_ESP8266
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
ESP8266 NodeMCU, esp8266:esp8266:nodemcuv2, BOARD_ESP8266
|
||||
ESP8266 D1-mini, esp8266:esp8266:d1_mini, BOARD_ESP8266
|
||||
|
0
editor/arduino/src/hal/fx3u-14.cpp
Normal file → Executable file
0
editor/arduino/src/hal/fx3u-14.cpp
Normal file → Executable file
75
editor/arduino/src/hal/iruinoVEA.cpp
Executable file
75
editor/arduino/src/hal/iruinoVEA.cpp
Executable file
@ -0,0 +1,75 @@
|
||||
#include <stdlib.h>
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
}
|
||||
#include "Arduino.h"
|
||||
#include "../examples/Baremetal/defines.h"
|
||||
#include "Display.h"
|
||||
|
||||
//OpenPLC HAL for Iruino boards
|
||||
|
||||
/******************PINOUT CONFIGURATION**************************
|
||||
Digital In: I0, I1, I2, I3, I4, I5, I6, I7 (%IX0.0 - %IX0.7)
|
||||
Digital Out: O0, O1, O2, O3, O4, O5, O6, O7 (%QX0.0 - %QX0.7)
|
||||
|
||||
Analog In: A0, A1 (%IW0 - %IW1)
|
||||
Analog Out:
|
||||
*****************************************************************/
|
||||
|
||||
//Create the I/O pin masks
|
||||
uint8_t pinMask_DIN[] = {PINMASK_DIN};
|
||||
uint8_t pinMask_AIN[] = {PINMASK_AIN};
|
||||
uint8_t pinMask_DOUT[] = {PINMASK_DOUT};
|
||||
uint8_t pinMask_AOUT[] = {PINMASK_AOUT};
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_DIN[i], INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_AIN[i], INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_DOUT[i], OUTPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_AOUT[i], OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
if (bool_input[i/8][i%8] != NULL)
|
||||
*bool_input[i/8][i%8] = digitalRead(pinMask_DIN[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
if (int_input[i] != NULL)
|
||||
*int_input[i] = (analogRead(pinMask_AIN[i]) * 10.0 / 4095.0 * 1000.0);
|
||||
}
|
||||
}
|
||||
|
||||
void updateOutputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
if (bool_output[i/8][i%8] != NULL)
|
||||
digitalWrite(pinMask_DOUT[i], *bool_output[i/8][i%8]);
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
if (int_output[i] != NULL)
|
||||
dacWrite(pinMask_AOUT[i], (*int_output[i] / 256));
|
||||
}
|
||||
}
|
5
editor/arduino/src/hal/iruinoVEA.hal
Executable file
5
editor/arduino/src/hal/iruinoVEA.hal
Executable file
@ -0,0 +1,5 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN, BOARD definition (optional)
|
||||
|
||||
Iruino VEA, vea:esp32:iruino, BOARD_ESP32
|
0
editor/arduino/src/hal/jaguar.cpp
Normal file → Executable file
0
editor/arduino/src/hal/jaguar.cpp
Normal file → Executable file
0
editor/arduino/src/hal/machine_control.cpp
Normal file → Executable file
0
editor/arduino/src/hal/machine_control.cpp
Normal file → Executable file
18
editor/arduino/src/hal/machine_control.hal
Normal file → Executable file
18
editor/arduino/src/hal/machine_control.hal
Normal file → Executable file
@ -1,9 +1,9 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Portenta Machine Control H7, arduino:mbed_portenta:envie_m7
|
||||
|
||||
|
||||
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Portenta Machine Control H7, arduino:mbed_portenta:envie_m7
|
||||
|
||||
|
||||
|
||||
|
||||
|
118
editor/arduino/src/hal/mega_due.cpp
Normal file → Executable file
118
editor/arduino/src/hal/mega_due.cpp
Normal file → Executable file
@ -5,6 +5,12 @@ extern "C" {
|
||||
#include "Arduino.h"
|
||||
#include "../examples/Baremetal/defines.h"
|
||||
|
||||
#if defined(__AVR__)
|
||||
#include "AVR_PWM.h"
|
||||
#else
|
||||
#include "SAMDUE_PWM.h"
|
||||
#endif
|
||||
|
||||
//OpenPLC HAL for Arduino Mega and Arduino Due
|
||||
|
||||
/************************PINOUT CONFIGURATION*************************
|
||||
@ -29,6 +35,47 @@ uint8_t pinMask_AIN[] = {PINMASK_AIN};
|
||||
uint8_t pinMask_DOUT[] = {PINMASK_DOUT};
|
||||
uint8_t pinMask_AOUT[] = {PINMASK_AOUT};
|
||||
|
||||
#define NUM_OF_PWM_PINS 12
|
||||
#define PWM_DEFAULT_FREQ 490
|
||||
|
||||
#if defined(__AVR__)
|
||||
#define PWM_CHANNEL_0_PIN 2
|
||||
#define PWM_CHANNEL_1_PIN 3
|
||||
#define PWM_CHANNEL_2_PIN 255 // disable pin 4 as it uses TIMER0
|
||||
#define PWM_CHANNEL_3_PIN 5
|
||||
#define PWM_CHANNEL_4_PIN 6
|
||||
#define PWM_CHANNEL_5_PIN 7
|
||||
#define PWM_CHANNEL_6_PIN 8
|
||||
#define PWM_CHANNEL_7_PIN 9
|
||||
#define PWM_CHANNEL_8_PIN 10
|
||||
#define PWM_CHANNEL_9_PIN 11
|
||||
#define PWM_CHANNEL_10_PIN 12
|
||||
#define PWM_CHANNEL_11_PIN 255 // disable pin 13 as it uses TIMER0
|
||||
#else
|
||||
#define PWM_CHANNEL_0_PIN 2
|
||||
#define PWM_CHANNEL_1_PIN 3
|
||||
#define PWM_CHANNEL_2_PIN 4
|
||||
#define PWM_CHANNEL_3_PIN 5
|
||||
#define PWM_CHANNEL_4_PIN 6
|
||||
#define PWM_CHANNEL_5_PIN 7
|
||||
#define PWM_CHANNEL_6_PIN 8
|
||||
#define PWM_CHANNEL_7_PIN 9
|
||||
#define PWM_CHANNEL_8_PIN 10
|
||||
#define PWM_CHANNEL_9_PIN 11
|
||||
#define PWM_CHANNEL_10_PIN 12
|
||||
#define PWM_CHANNEL_11_PIN 13
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__AVR__)
|
||||
AVR_PWM *PWM_Instance[NUM_OF_PWM_PINS];
|
||||
#else
|
||||
SAMDUE_PWM *PWM_Instance[NUM_OF_PWM_PINS];
|
||||
#endif
|
||||
|
||||
extern "C" uint8_t set_hardware_pwm(uint8_t, float, float); //this call is required for the C-based PWM block on the Editor
|
||||
|
||||
bool pwm_initialized = false;
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
@ -57,6 +104,77 @@ void hardwareInit()
|
||||
}
|
||||
}
|
||||
|
||||
void init_pwm()
|
||||
{
|
||||
// If PWM_CONTROLLER block is being used, disable pins from regular analogWrite
|
||||
const uint8_t pins[] = {PWM_CHANNEL_0_PIN, PWM_CHANNEL_1_PIN, PWM_CHANNEL_2_PIN, PWM_CHANNEL_3_PIN, PWM_CHANNEL_4_PIN, PWM_CHANNEL_5_PIN,
|
||||
PWM_CHANNEL_6_PIN, PWM_CHANNEL_7_PIN, PWM_CHANNEL_8_PIN, PWM_CHANNEL_9_PIN, PWM_CHANNEL_10_PIN, PWM_CHANNEL_11_PIN};
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
for (int j = 0; j < NUM_OF_PWM_PINS; j++)
|
||||
{
|
||||
if (pinMask_AOUT[i] == pins[j])
|
||||
{
|
||||
pinMask_AOUT[i] = 255; //disable pin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize PWM pins
|
||||
#if defined(__AVR__)
|
||||
PWM_Instance[0] = new AVR_PWM(PWM_CHANNEL_0_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[1] = new AVR_PWM(PWM_CHANNEL_1_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[2] = new AVR_PWM(PWM_CHANNEL_2_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[3] = new AVR_PWM(PWM_CHANNEL_3_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[4] = new AVR_PWM(PWM_CHANNEL_4_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[5] = new AVR_PWM(PWM_CHANNEL_5_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[6] = new AVR_PWM(PWM_CHANNEL_6_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[7] = new AVR_PWM(PWM_CHANNEL_7_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[8] = new AVR_PWM(PWM_CHANNEL_8_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[9] = new AVR_PWM(PWM_CHANNEL_9_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[10] = new AVR_PWM(PWM_CHANNEL_10_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[11] = new AVR_PWM(PWM_CHANNEL_11_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
#else
|
||||
PWM_Instance[0] = new SAMDUE_PWM(PWM_CHANNEL_0_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[1] = new SAMDUE_PWM(PWM_CHANNEL_1_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[2] = new SAMDUE_PWM(PWM_CHANNEL_2_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[3] = new SAMDUE_PWM(PWM_CHANNEL_3_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[4] = new SAMDUE_PWM(PWM_CHANNEL_4_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[5] = new SAMDUE_PWM(PWM_CHANNEL_5_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[6] = new SAMDUE_PWM(PWM_CHANNEL_6_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[7] = new SAMDUE_PWM(PWM_CHANNEL_7_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[8] = new SAMDUE_PWM(PWM_CHANNEL_8_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[9] = new SAMDUE_PWM(PWM_CHANNEL_9_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[10] = new SAMDUE_PWM(PWM_CHANNEL_10_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[11] = new SAMDUE_PWM(PWM_CHANNEL_11_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t set_hardware_pwm(uint8_t ch, float freq, float duty)
|
||||
{
|
||||
if (pwm_initialized == false)
|
||||
{
|
||||
init_pwm();
|
||||
pwm_initialized = true;
|
||||
}
|
||||
|
||||
const uint8_t pins[] = {PWM_CHANNEL_0_PIN, PWM_CHANNEL_1_PIN, PWM_CHANNEL_2_PIN, PWM_CHANNEL_3_PIN, PWM_CHANNEL_4_PIN, PWM_CHANNEL_5_PIN,
|
||||
PWM_CHANNEL_6_PIN, PWM_CHANNEL_7_PIN, PWM_CHANNEL_8_PIN, PWM_CHANNEL_9_PIN, PWM_CHANNEL_10_PIN, PWM_CHANNEL_11_PIN};
|
||||
|
||||
if (ch >= NUM_OF_PWM_PINS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PWM_Instance[ch]->setPWM(pins[ch], freq, duty))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
|
16
editor/arduino/src/hal/mega_due.hal
Normal file → Executable file
16
editor/arduino/src/hal/mega_due.hal
Normal file → Executable file
@ -1,8 +1,8 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Arduino Mega, arduino:avr:mega
|
||||
Arduino Due (native USB port), arduino:sam:arduino_due_x
|
||||
Arduino Due (programming port), arduino:sam:arduino_due_x_dbg
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Arduino Mega, arduino:avr:mega
|
||||
Arduino Due (native USB port), arduino:sam:arduino_due_x
|
||||
Arduino Due (programming port), arduino:sam:arduino_due_x_dbg
|
||||
|
||||
|
244
editor/arduino/src/hal/mega_due_bkp.cpp
Normal file → Executable file
244
editor/arduino/src/hal/mega_due_bkp.cpp
Normal file → Executable file
@ -1,122 +1,122 @@
|
||||
#include <stdlib.h>
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
}
|
||||
#include "Arduino.h"
|
||||
|
||||
//OpenPLC HAL for Arduino Mega and Arduino Due
|
||||
|
||||
/************************PINOUT CONFIGURATION*************************
|
||||
Digital In: 62, 63, 64, 65, 66, 67, 68, 69 (%IX0.0 - %IX0.7)
|
||||
22, 24, 26, 28, 30, 32, 34, 36 (%IX1.0 - %IX1.7)
|
||||
38, 40, 42, 44, 46, 48, 50, 52 (%IX2.0 - %IX2.7)
|
||||
|
||||
Digital Out: 14, 15, 16, 17, 18, 19, 20, 21 (%QX0.0 - %QX0.7)
|
||||
23, 25, 27, 29, 31, 33, 35, 37 (%QX1.0 - %QX1.7)
|
||||
39, 41, 43, 45, 47, 49, 51, 53 (%QX2.0 - %QX2.7)
|
||||
|
||||
Analog In: A0, A1, A2, A3, A4, A5, A6, A7 (%IW0 - %IW7)
|
||||
|
||||
Analog Out: 2, 3, 4, 5, 6, 7, 8, 9 (%QW0 - %QW7)
|
||||
10, 11, 12, 13 (%QW8 - %QW11)
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
//Define the number of inputs and outputs for this board (mapping for the Arduino Mega)
|
||||
#define NUM_DISCRETE_INPUT 24
|
||||
#define NUM_ANALOG_INPUT 8
|
||||
#define NUM_DISCRETE_OUTPUT 24
|
||||
#define NUM_ANALOG_OUTPUT 12
|
||||
|
||||
//Create the I/O pin masks
|
||||
//const PROGMEM uint8_t pinMask_DIN[] = {62, 63, 64, 65, 66, 67, 68, 69, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52};
|
||||
const PROGMEM uint8_t pinMask_DIN[] = {62, 63, 64, 65, 66, 67, 68, 69, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52};
|
||||
const PROGMEM uint8_t pinMask_AIN[] = {A0, A1, A2, A3, A4, A5, A6, A7};
|
||||
const PROGMEM uint8_t pinMask_DOUT[] = {14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53};
|
||||
const PROGMEM uint8_t pinMask_AOUT[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
|
||||
|
||||
extern uint8_t disabled_pins[11];
|
||||
|
||||
bool checkPin(uint8_t pin)
|
||||
{
|
||||
for (int i = 1; i < disabled_pins[0]; i++)
|
||||
{
|
||||
if (pin == disabled_pins[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_DIN + i);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_AIN + i);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_DOUT + i);
|
||||
pinMode(pin, OUTPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_AOUT + i);
|
||||
pinMode(pin, OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_DIN + i);
|
||||
if (checkPin(pin))
|
||||
{
|
||||
if (bool_input[i/8][i%8] != NULL)
|
||||
*bool_input[i/8][i%8] = digitalRead(pin);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_AIN + i);
|
||||
if (checkPin(pin))
|
||||
{
|
||||
if (int_input[i] != NULL)
|
||||
*int_input[i] = (analogRead(pin) * 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateOutputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_DOUT + i);
|
||||
if (checkPin(pin))
|
||||
{
|
||||
if (bool_output[i/8][i%8] != NULL)
|
||||
digitalWrite(pin, *bool_output[i/8][i%8]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_AOUT + i);
|
||||
if (checkPin(pin))
|
||||
{
|
||||
if (int_output[i] != NULL)
|
||||
analogWrite(pin, (*int_output[i] / 256));
|
||||
}
|
||||
}
|
||||
}
|
||||
#include <stdlib.h>
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
}
|
||||
#include "Arduino.h"
|
||||
|
||||
//OpenPLC HAL for Arduino Mega and Arduino Due
|
||||
|
||||
/************************PINOUT CONFIGURATION*************************
|
||||
Digital In: 62, 63, 64, 65, 66, 67, 68, 69 (%IX0.0 - %IX0.7)
|
||||
22, 24, 26, 28, 30, 32, 34, 36 (%IX1.0 - %IX1.7)
|
||||
38, 40, 42, 44, 46, 48, 50, 52 (%IX2.0 - %IX2.7)
|
||||
|
||||
Digital Out: 14, 15, 16, 17, 18, 19, 20, 21 (%QX0.0 - %QX0.7)
|
||||
23, 25, 27, 29, 31, 33, 35, 37 (%QX1.0 - %QX1.7)
|
||||
39, 41, 43, 45, 47, 49, 51, 53 (%QX2.0 - %QX2.7)
|
||||
|
||||
Analog In: A0, A1, A2, A3, A4, A5, A6, A7 (%IW0 - %IW7)
|
||||
|
||||
Analog Out: 2, 3, 4, 5, 6, 7, 8, 9 (%QW0 - %QW7)
|
||||
10, 11, 12, 13 (%QW8 - %QW11)
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
//Define the number of inputs and outputs for this board (mapping for the Arduino Mega)
|
||||
#define NUM_DISCRETE_INPUT 24
|
||||
#define NUM_ANALOG_INPUT 8
|
||||
#define NUM_DISCRETE_OUTPUT 24
|
||||
#define NUM_ANALOG_OUTPUT 12
|
||||
|
||||
//Create the I/O pin masks
|
||||
//const PROGMEM uint8_t pinMask_DIN[] = {62, 63, 64, 65, 66, 67, 68, 69, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52};
|
||||
const PROGMEM uint8_t pinMask_DIN[] = {62, 63, 64, 65, 66, 67, 68, 69, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52};
|
||||
const PROGMEM uint8_t pinMask_AIN[] = {A0, A1, A2, A3, A4, A5, A6, A7};
|
||||
const PROGMEM uint8_t pinMask_DOUT[] = {14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53};
|
||||
const PROGMEM uint8_t pinMask_AOUT[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
|
||||
|
||||
extern uint8_t disabled_pins[11];
|
||||
|
||||
bool checkPin(uint8_t pin)
|
||||
{
|
||||
for (int i = 1; i < disabled_pins[0]; i++)
|
||||
{
|
||||
if (pin == disabled_pins[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_DIN + i);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_AIN + i);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_DOUT + i);
|
||||
pinMode(pin, OUTPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_AOUT + i);
|
||||
pinMode(pin, OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_DIN + i);
|
||||
if (checkPin(pin))
|
||||
{
|
||||
if (bool_input[i/8][i%8] != NULL)
|
||||
*bool_input[i/8][i%8] = digitalRead(pin);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_AIN + i);
|
||||
if (checkPin(pin))
|
||||
{
|
||||
if (int_input[i] != NULL)
|
||||
*int_input[i] = (analogRead(pin) * 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateOutputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_DOUT + i);
|
||||
if (checkPin(pin))
|
||||
{
|
||||
if (bool_output[i/8][i%8] != NULL)
|
||||
digitalWrite(pin, *bool_output[i/8][i%8]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pgm_read_byte(pinMask_AOUT + i);
|
||||
if (checkPin(pin))
|
||||
{
|
||||
if (int_output[i] != NULL)
|
||||
analogWrite(pin, (*int_output[i] / 256));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
0
editor/arduino/src/hal/mkr.cpp
Normal file → Executable file
0
editor/arduino/src/hal/mkr.cpp
Normal file → Executable file
16
editor/arduino/src/hal/mkr.hal
Normal file → Executable file
16
editor/arduino/src/hal/mkr.hal
Normal file → Executable file
@ -1,8 +1,8 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Mkr Zero, arduino:samd:mkrzero
|
||||
Mkr WiFi, arduino:samd:mkrwifi1010, BOARD_WIFININA
|
||||
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Mkr Zero, arduino:samd:mkrzero
|
||||
Mkr WiFi, arduino:samd:mkrwifi1010, BOARD_WIFININA
|
||||
|
||||
|
||||
|
0
editor/arduino/src/hal/nano_every.cpp
Normal file → Executable file
0
editor/arduino/src/hal/nano_every.cpp
Normal file → Executable file
16
editor/arduino/src/hal/nano_every.hal
Normal file → Executable file
16
editor/arduino/src/hal/nano_every.hal
Normal file → Executable file
@ -1,8 +1,8 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Nano Every, arduino:megaavr:nona4809
|
||||
Nano 33 IoT, arduino:samd:nano_33_iot, BOARD_WIFININA
|
||||
Nano 33 BLE, arduino:mbed_nano:nano33ble
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Nano Every, arduino:megaavr:nona4809
|
||||
Nano 33 IoT, arduino:samd:nano_33_iot, BOARD_WIFININA
|
||||
Nano 33 BLE, arduino:mbed_nano:nano33ble
|
||||
|
||||
|
0
editor/arduino/src/hal/p1am.cpp
Normal file → Executable file
0
editor/arduino/src/hal/p1am.cpp
Normal file → Executable file
12
editor/arduino/src/hal/p1am.hal
Normal file → Executable file
12
editor/arduino/src/hal/p1am.hal
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
P1AM-100, arduino:samd:mkrzero
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
P1AM-100, arduino:samd:mkrzero
|
||||
|
||||
|
0
editor/arduino/src/hal/rp2040.cpp
Normal file → Executable file
0
editor/arduino/src/hal/rp2040.cpp
Normal file → Executable file
12
editor/arduino/src/hal/rp2040.hal
Normal file → Executable file
12
editor/arduino/src/hal/rp2040.hal
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Nano RP2040 Connect, arduino:mbed_nano:nanorp2040connect, BOARD_WIFININA
|
||||
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Nano RP2040 Connect, arduino:mbed_nano:nanorp2040connect, BOARD_WIFININA
|
||||
|
||||
|
0
editor/arduino/src/hal/rp2040pico.cpp
Normal file → Executable file
0
editor/arduino/src/hal/rp2040pico.cpp
Normal file → Executable file
12
editor/arduino/src/hal/rp2040pico.hal
Normal file → Executable file
12
editor/arduino/src/hal/rp2040pico.hal
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Raspberry Pico, arduino:mbed_rp2040:pico
|
||||
Raspberry Pico W, arduino:mbed_rp2040:pico
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
|
||||
Raspberry Pico, arduino:mbed_rp2040:pico
|
||||
Raspberry Pico W, arduino:mbed_rp2040:pico
|
||||
|
146
editor/arduino/src/hal/sequent_esp32.cpp
Normal file → Executable file
146
editor/arduino/src/hal/sequent_esp32.cpp
Normal file → Executable file
@ -1,73 +1,73 @@
|
||||
#include <stdlib.h>
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
}
|
||||
#include "Arduino.h"
|
||||
#include "../examples/Baremetal/defines.h"
|
||||
|
||||
//OpenPLC HAL for SEQUENT MICROSYSTEMS ESP32-PI boards
|
||||
|
||||
/******************PINOUT CONFIGURATION**************************
|
||||
Digital In: 27, 32 (%IX0.0 - %IX0.1)
|
||||
Digital Out: 12, 13, 14, 15 (%QX0.0 - %QX0.3)
|
||||
Analog In: 34, 35 (%IW0 - %IW1)
|
||||
Analog Out: 25 (%QW0 )
|
||||
*****************************************************************/
|
||||
|
||||
//Create the I/O pin masks
|
||||
uint8_t pinMask_DIN[] = {PINMASK_DIN};
|
||||
uint8_t pinMask_AIN[] = {PINMASK_AIN};
|
||||
uint8_t pinMask_DOUT[] = {PINMASK_DOUT};
|
||||
uint8_t pinMask_AOUT[] = {PINMASK_AOUT};
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_DIN[i], INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_AIN[i], INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_DOUT[i], OUTPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_AOUT[i], OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
if (bool_input[i/8][i%8] != NULL)
|
||||
*bool_input[i/8][i%8] = digitalRead(pinMask_DIN[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
if (int_input[i] != NULL)
|
||||
*int_input[i] = (analogRead(pinMask_AIN[i]) * 16);
|
||||
}
|
||||
}
|
||||
|
||||
void updateOutputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
if (bool_output[i/8][i%8] != NULL)
|
||||
digitalWrite(pinMask_DOUT[i], *bool_output[i/8][i%8]);
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
if (int_output[i] != NULL)
|
||||
dacWrite(pinMask_AOUT[i], (*int_output[i] / 256));
|
||||
}
|
||||
}
|
||||
#include <stdlib.h>
|
||||
extern "C" {
|
||||
#include "openplc.h"
|
||||
}
|
||||
#include "Arduino.h"
|
||||
#include "../examples/Baremetal/defines.h"
|
||||
|
||||
//OpenPLC HAL for SEQUENT MICROSYSTEMS ESP32-PI boards
|
||||
|
||||
/******************PINOUT CONFIGURATION**************************
|
||||
Digital In: 27, 32 (%IX0.0 - %IX0.1)
|
||||
Digital Out: 12, 13, 14, 15 (%QX0.0 - %QX0.3)
|
||||
Analog In: 34, 35 (%IW0 - %IW1)
|
||||
Analog Out: 25 (%QW0 )
|
||||
*****************************************************************/
|
||||
|
||||
//Create the I/O pin masks
|
||||
uint8_t pinMask_DIN[] = {PINMASK_DIN};
|
||||
uint8_t pinMask_AIN[] = {PINMASK_AIN};
|
||||
uint8_t pinMask_DOUT[] = {PINMASK_DOUT};
|
||||
uint8_t pinMask_AOUT[] = {PINMASK_AOUT};
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_DIN[i], INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_AIN[i], INPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_DOUT[i], OUTPUT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
pinMode(pinMask_AOUT[i], OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
if (bool_input[i/8][i%8] != NULL)
|
||||
*bool_input[i/8][i%8] = digitalRead(pinMask_DIN[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
if (int_input[i] != NULL)
|
||||
*int_input[i] = (analogRead(pinMask_AIN[i]) * 16);
|
||||
}
|
||||
}
|
||||
|
||||
void updateOutputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
if (bool_output[i/8][i%8] != NULL)
|
||||
digitalWrite(pinMask_DOUT[i], *bool_output[i/8][i%8]);
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
if (int_output[i] != NULL)
|
||||
dacWrite(pinMask_AOUT[i], (*int_output[i] / 256));
|
||||
}
|
||||
}
|
||||
|
0
editor/arduino/src/hal/stm32_f103cb.cpp
Normal file → Executable file
0
editor/arduino/src/hal/stm32_f103cb.cpp
Normal file → Executable file
10
editor/arduino/src/hal/stm32_f103cb.hal
Normal file → Executable file
10
editor/arduino/src/hal/stm32_f103cb.hal
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN, BOARD definition (optional)
|
||||
|
||||
STM32-F103CB (Bluepill), STM32:stm32:GenF1:pnum=BLUEPILL_F103C8, BOARD_STM32_F103CB
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN, BOARD definition (optional)
|
||||
|
||||
STM32-F103CB (Bluepill), STM32:stm32:GenF1:pnum=BLUEPILL_F103C8, BOARD_STM32_F103CB
|
||||
|
0
editor/arduino/src/hal/stm32_f411ce.cpp
Normal file → Executable file
0
editor/arduino/src/hal/stm32_f411ce.cpp
Normal file → Executable file
10
editor/arduino/src/hal/stm32_f411ce.hal
Normal file → Executable file
10
editor/arduino/src/hal/stm32_f411ce.hal
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN, BOARD definition (optional)
|
||||
|
||||
STM32-F411CE (Blackpill), STM32:stm32:GenF4:pnum=BLACKPILL_F411CE, BOARD_STM32_F411CE
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN, BOARD definition (optional)
|
||||
|
||||
STM32-F411CE (Blackpill), STM32:stm32:GenF4:pnum=BLACKPILL_F411CE, BOARD_STM32_F411CE
|
||||
|
100
editor/arduino/src/hal/uno_leonardo_nano_micro_zero.cpp
Normal file → Executable file
100
editor/arduino/src/hal/uno_leonardo_nano_micro_zero.cpp
Normal file → Executable file
@ -5,6 +5,12 @@ extern "C" {
|
||||
#include "Arduino.h"
|
||||
#include "../examples/Baremetal/defines.h"
|
||||
|
||||
#if defined(__SAM3X8E__) || defined(__SAMD21G18A__)
|
||||
#include "SAMD_PWM.h"
|
||||
#else
|
||||
#include "AVR_PWM.h"
|
||||
#endif
|
||||
|
||||
//OpenPLC HAL for Arduino Uno and Arduino Nano (old) form factor (Uno, Leonardo, Nano, Micro and Zero)
|
||||
|
||||
/******************PINOUT CONFIGURATION*******************
|
||||
@ -20,6 +26,28 @@ uint8_t pinMask_AIN[] = {PINMASK_AIN};
|
||||
uint8_t pinMask_DOUT[] = {PINMASK_DOUT};
|
||||
uint8_t pinMask_AOUT[] = {PINMASK_AOUT};
|
||||
|
||||
#define PWM_DEFAULT_FREQ 490
|
||||
#define PWM_CHANNEL_0_PIN 9
|
||||
#define PWM_CHANNEL_1_PIN 10
|
||||
|
||||
#ifdef __AVR_ATmega32U4__
|
||||
#define NUM_OF_PWM_PINS 2
|
||||
#else
|
||||
#define NUM_OF_PWM_PINS 3
|
||||
#define PWM_CHANNEL_2_PIN 11
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__SAM3X8E__) || defined(__SAMD21G18A__)
|
||||
SAMD_PWM *PWM_Instance[NUM_OF_PWM_PINS];
|
||||
#else
|
||||
AVR_PWM *PWM_Instance[NUM_OF_PWM_PINS];
|
||||
#endif
|
||||
|
||||
extern "C" uint8_t set_hardware_pwm(uint8_t, float, float); //this call is required for the C-based PWM block on the Editor
|
||||
|
||||
bool pwm_initialized = false;
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
@ -47,18 +75,82 @@ void hardwareInit()
|
||||
}
|
||||
}
|
||||
|
||||
void init_pwm()
|
||||
{
|
||||
// If PWM_CONTROLLER block is being used, disable pins from regular analogWrite
|
||||
#ifdef __AVR_ATmega32U4__
|
||||
const uint8_t pins[] = {PWM_CHANNEL_0_PIN, PWM_CHANNEL_1_PIN};
|
||||
#else
|
||||
const uint8_t pins[] = {PWM_CHANNEL_0_PIN, PWM_CHANNEL_1_PIN, PWM_CHANNEL_2_PIN};
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
for (int j = 0; j < NUM_OF_PWM_PINS; j++)
|
||||
{
|
||||
if (pinMask_AOUT[i] == pins[j])
|
||||
{
|
||||
pinMask_AOUT[i] = 255; //disable pin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize PWM pins
|
||||
#if defined(__SAM3X8E__) || defined(__SAMD21G18A__)
|
||||
PWM_Instance[0] = new SAMD_PWM(PWM_CHANNEL_0_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[1] = new SAMD_PWM(PWM_CHANNEL_1_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[2] = new SAMD_PWM(PWM_CHANNEL_2_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
#else
|
||||
#ifdef __AVR_ATmega32U4__
|
||||
PWM_Instance[0] = new AVR_PWM(PWM_CHANNEL_0_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[1] = new AVR_PWM(PWM_CHANNEL_1_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
#else
|
||||
PWM_Instance[0] = new AVR_PWM(PWM_CHANNEL_0_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[1] = new AVR_PWM(PWM_CHANNEL_1_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
PWM_Instance[2] = new AVR_PWM(PWM_CHANNEL_2_PIN, PWM_DEFAULT_FREQ, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t set_hardware_pwm(uint8_t ch, float freq, float duty)
|
||||
{
|
||||
if (pwm_initialized == false)
|
||||
{
|
||||
init_pwm();
|
||||
pwm_initialized = true;
|
||||
}
|
||||
|
||||
#ifdef __AVR_ATmega32U4__
|
||||
const uint8_t pins[] = {PWM_CHANNEL_0_PIN, PWM_CHANNEL_1_PIN};
|
||||
#else
|
||||
const uint8_t pins[] = {PWM_CHANNEL_0_PIN, PWM_CHANNEL_1_PIN, PWM_CHANNEL_2_PIN};
|
||||
#endif
|
||||
|
||||
if (ch >= NUM_OF_PWM_PINS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PWM_Instance[ch]->setPWM(pins[ch], freq, duty))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void updateInputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pinMask_DIN[i];
|
||||
uint8_t pin = pinMask_DIN[i];
|
||||
if (bool_input[i/8][i%8] != NULL)
|
||||
*bool_input[i/8][i%8] = digitalRead(pin);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_ANALOG_INPUT; i++)
|
||||
{
|
||||
uint8_t pin = pinMask_AIN[i];
|
||||
uint8_t pin = pinMask_AIN[i];
|
||||
if (int_input[i] != NULL)
|
||||
*int_input[i] = (analogRead(pin) * 64);
|
||||
}
|
||||
@ -68,13 +160,13 @@ void updateOutputBuffers()
|
||||
{
|
||||
for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pinMask_DOUT[i];
|
||||
uint8_t pin = pinMask_DOUT[i];
|
||||
if (bool_output[i/8][i%8] != NULL)
|
||||
digitalWrite(pin, *bool_output[i/8][i%8]);
|
||||
}
|
||||
for (int i = 0; i < NUM_ANALOG_OUTPUT; i++)
|
||||
{
|
||||
uint8_t pin = pinMask_AOUT[i];
|
||||
uint8_t pin = pinMask_AOUT[i];
|
||||
if (int_output[i] != NULL)
|
||||
analogWrite(pin, (*int_output[i] / 256));
|
||||
}
|
||||
|
18
editor/arduino/src/hal/uno_leonardo_nano_micro_zero.hal
Normal file → Executable file
18
editor/arduino/src/hal/uno_leonardo_nano_micro_zero.hal
Normal file → Executable file
@ -1,9 +1,9 @@
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
Arduino Uno, arduino:avr:uno
|
||||
Arduino Nano, arduino:avr:nano
|
||||
Arduino Leonardo, arduino:avr:leonardo
|
||||
Arduino Micro, arduino:avr:micro
|
||||
Arduino Zero (native USB port), arduino:samd:arduino_zero_native
|
||||
Arduino Zero (programming port), arduino:samd:arduino_zero_edbg
|
||||
# HAL configuration
|
||||
# Format :
|
||||
# Board type, FQBN
|
||||
Arduino Uno, arduino:avr:uno
|
||||
Arduino Nano, arduino:avr:nano
|
||||
Arduino Leonardo, arduino:avr:leonardo
|
||||
Arduino Micro, arduino:avr:micro
|
||||
Arduino Zero (native USB port), arduino:samd:arduino_zero_native
|
||||
Arduino Zero (programming port), arduino:samd:arduino_zero_edbg
|
||||
|
330
editor/arduino/src/lib/COPYING.LESSER
Normal file → Executable file
330
editor/arduino/src/lib/COPYING.LESSER
Normal file → Executable file
@ -1,165 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
|
864
editor/arduino/src/lib/MQTT.h
Normal file → Executable file
864
editor/arduino/src/lib/MQTT.h
Normal file → Executable file
@ -1,432 +1,432 @@
|
||||
|
||||
// FUNCTION_BLOCK MQTT_RECEIVE
|
||||
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,RECEIVE)
|
||||
__DECLARE_VAR(STRING,TOPIC)
|
||||
__DECLARE_VAR(BOOL,RECEIVED)
|
||||
__DECLARE_VAR(STRING,MESSAGE)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_RECEIVE;
|
||||
|
||||
static void MQTT_RECEIVE_init__(MQTT_RECEIVE *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_RECEIVE_body__(MQTT_RECEIVE *data__);
|
||||
// FUNCTION_BLOCK MQTT_SEND
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,SEND)
|
||||
__DECLARE_VAR(STRING,TOPIC)
|
||||
__DECLARE_VAR(STRING,MESSAGE)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_SEND;
|
||||
|
||||
static void MQTT_SEND_init__(MQTT_SEND *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_SEND_body__(MQTT_SEND *data__);
|
||||
// FUNCTION_BLOCK MQTT_CONNECT
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,CONNECT)
|
||||
__DECLARE_VAR(STRING,BROKER)
|
||||
__DECLARE_VAR(UINT,PORT)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_CONNECT;
|
||||
|
||||
static void MQTT_CONNECT_init__(MQTT_CONNECT *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_CONNECT_body__(MQTT_CONNECT *data__);
|
||||
// FUNCTION_BLOCK MQTT_CONNECT_AUTH
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,CONNECT)
|
||||
__DECLARE_VAR(STRING,BROKER)
|
||||
__DECLARE_VAR(UINT,PORT)
|
||||
__DECLARE_VAR(STRING,USER)
|
||||
__DECLARE_VAR(STRING,PASSWORD)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_CONNECT_AUTH;
|
||||
|
||||
static void MQTT_CONNECT_AUTH_init__(MQTT_CONNECT_AUTH *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_CONNECT_AUTH_body__(MQTT_CONNECT_AUTH *data__);
|
||||
// FUNCTION_BLOCK MQTT_SUBSCRIBE
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,SUBSCRIBE)
|
||||
__DECLARE_VAR(STRING,TOPIC)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_SUBSCRIBE;
|
||||
|
||||
static void MQTT_SUBSCRIBE_init__(MQTT_SUBSCRIBE *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_SUBSCRIBE_body__(MQTT_SUBSCRIBE *data__);
|
||||
// FUNCTION_BLOCK MQTT_UNSUBSCRIBE
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,UNSUBSCRIBE)
|
||||
__DECLARE_VAR(STRING,TOPIC)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_UNSUBSCRIBE;
|
||||
|
||||
static void MQTT_UNSUBSCRIBE_init__(MQTT_UNSUBSCRIBE *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_UNSUBSCRIBE_body__(MQTT_UNSUBSCRIBE *data__);
|
||||
// FUNCTION_BLOCK MQTT_DISCONNECT
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,DISCONNECT)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_DISCONNECT;
|
||||
|
||||
static void MQTT_DISCONNECT_init__(MQTT_DISCONNECT *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_DISCONNECT_body__(MQTT_DISCONNECT *data__);
|
||||
|
||||
|
||||
// External C Functions
|
||||
uint8_t connect_mqtt(char *broker, uint16_t port);
|
||||
uint8_t connect_mqtt_auth(char *broker, uint16_t port, char *user, char *password);
|
||||
uint8_t mqtt_send(char *topic, char *message);
|
||||
void mqtt_loop();
|
||||
uint8_t mqtt_receive(char *topic, char *message);
|
||||
uint8_t mqtt_subscribe(char *topic);
|
||||
uint8_t mqtt_unsubscribe(char *topic);
|
||||
uint8_t mqtt_disconnect();
|
||||
|
||||
|
||||
static void MQTT_RECEIVE_init__(MQTT_RECEIVE *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->RECEIVE,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->TOPIC,__STRING_LITERAL(0,""),retain)
|
||||
__INIT_VAR(data__->RECEIVED,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->MESSAGE,__STRING_LITERAL(0,""),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_RECEIVE_body__(MQTT_RECEIVE *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
|
||||
if (__GET_VAR(data__->RECEIVE))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->TOPIC).body[__GET_VAR(data__->TOPIC).len] = '\0';
|
||||
|
||||
__GET_VAR(data__->MESSAGE).len = mqtt_receive(__GET_VAR(data__->TOPIC).body, __GET_VAR(data__->MESSAGE).body);
|
||||
if (__GET_VAR(data__->MESSAGE).len > 0)
|
||||
{
|
||||
__SET_VAR(data__->,RECEIVED,,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
__SET_VAR(data__->,RECEIVED,,0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__SET_VAR(data__->,RECEIVED,,0);
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_RECEIVE_body__()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void MQTT_SEND_init__(MQTT_SEND *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->SEND,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->TOPIC,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->MESSAGE,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_SEND_body__(MQTT_SEND *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
uint8_t message_sent = 0;
|
||||
|
||||
if (__GET_VAR(data__->SEND))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->TOPIC).body[__GET_VAR(data__->TOPIC).len] = '\0';
|
||||
__GET_VAR(data__->MESSAGE).body[__GET_VAR(data__->MESSAGE).len] = '\0';
|
||||
|
||||
message_sent = mqtt_send(__GET_VAR(data__->TOPIC).body, __GET_VAR(data__->MESSAGE).body);
|
||||
}
|
||||
|
||||
__SET_VAR(data__->,SUCCESS,,message_sent);
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_SEND_body__()
|
||||
|
||||
|
||||
|
||||
static void MQTT_CONNECT_init__(MQTT_CONNECT *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->CONNECT,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->BROKER,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->PORT,0,retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_CONNECT_body__(MQTT_CONNECT *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->CONNECT))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->BROKER).body[__GET_VAR(data__->BROKER).len] = '\0';
|
||||
|
||||
uint8_t mqtt_connected = connect_mqtt(__GET_VAR(data__->BROKER).body, __GET_VAR(data__->PORT));
|
||||
__SET_VAR(data__->,SUCCESS,,mqtt_connected);
|
||||
}
|
||||
|
||||
// Call MQTT loop every scan cycle after a successfull connection
|
||||
if (__GET_VAR(data__->SUCCESS))
|
||||
{
|
||||
mqtt_loop();
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_CONNECT_body__()
|
||||
|
||||
|
||||
|
||||
static void MQTT_CONNECT_AUTH_init__(MQTT_CONNECT_AUTH *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->CONNECT,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->BROKER,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->PORT,0,retain)
|
||||
__INIT_VAR(data__->USER,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->PASSWORD,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_CONNECT_AUTH_body__(MQTT_CONNECT_AUTH *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->CONNECT))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->BROKER).body[__GET_VAR(data__->BROKER).len] = '\0';
|
||||
__GET_VAR(data__->BROKER).body[__GET_VAR(data__->USER).len] = '\0';
|
||||
__GET_VAR(data__->BROKER).body[__GET_VAR(data__->PASSWORD).len] = '\0';
|
||||
|
||||
uint8_t mqtt_connected = connect_mqtt_auth(__GET_VAR(data__->BROKER).body, __GET_VAR(data__->PORT), __GET_VAR(data__->USER).body, __GET_VAR(data__->PASSWORD).body);
|
||||
__SET_VAR(data__->,SUCCESS,,mqtt_connected);
|
||||
}
|
||||
|
||||
// Call MQTT loop every scan cycle after a successfull connection
|
||||
if (__GET_VAR(data__->SUCCESS))
|
||||
{
|
||||
mqtt_loop();
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_CONNECT_AUTH_body__()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void MQTT_SUBSCRIBE_init__(MQTT_SUBSCRIBE *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->SUBSCRIBE,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->TOPIC,__STRING_LITERAL(0,""),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_SUBSCRIBE_body__(MQTT_SUBSCRIBE *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->SUBSCRIBE))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->TOPIC).body[__GET_VAR(data__->TOPIC).len] = '\0';
|
||||
|
||||
uint8_t topic_subscribed = mqtt_subscribe(__GET_VAR(data__->TOPIC).body);
|
||||
__SET_VAR(data__->,SUCCESS,,topic_subscribed);
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_SUBSCRIBE_body__()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void MQTT_UNSUBSCRIBE_init__(MQTT_UNSUBSCRIBE *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->UNSUBSCRIBE,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->TOPIC,__STRING_LITERAL(0,""),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_UNSUBSCRIBE_body__(MQTT_UNSUBSCRIBE *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->UNSUBSCRIBE))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->TOPIC).body[__GET_VAR(data__->TOPIC).len] = '\0';
|
||||
|
||||
uint8_t topic_unsubscribed = mqtt_unsubscribe(__GET_VAR(data__->TOPIC).body);
|
||||
__SET_VAR(data__->,SUCCESS,,topic_unsubscribed);
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_UNSUBSCRIBE_body__()
|
||||
|
||||
|
||||
|
||||
|
||||
static void MQTT_DISCONNECT_init__(MQTT_DISCONNECT *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->DISCONNECT,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_DISCONNECT_body__(MQTT_DISCONNECT *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->DISCONNECT))
|
||||
{
|
||||
uint8_t broker_disconnected = mqtt_disconnect();
|
||||
__SET_VAR(data__->,SUCCESS,,broker_disconnected);
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_DISCONNECT_body__()
|
||||
|
||||
// FUNCTION_BLOCK MQTT_RECEIVE
|
||||
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,RECEIVE)
|
||||
__DECLARE_VAR(STRING,TOPIC)
|
||||
__DECLARE_VAR(BOOL,RECEIVED)
|
||||
__DECLARE_VAR(STRING,MESSAGE)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_RECEIVE;
|
||||
|
||||
static void MQTT_RECEIVE_init__(MQTT_RECEIVE *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_RECEIVE_body__(MQTT_RECEIVE *data__);
|
||||
// FUNCTION_BLOCK MQTT_SEND
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,SEND)
|
||||
__DECLARE_VAR(STRING,TOPIC)
|
||||
__DECLARE_VAR(STRING,MESSAGE)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_SEND;
|
||||
|
||||
static void MQTT_SEND_init__(MQTT_SEND *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_SEND_body__(MQTT_SEND *data__);
|
||||
// FUNCTION_BLOCK MQTT_CONNECT
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,CONNECT)
|
||||
__DECLARE_VAR(STRING,BROKER)
|
||||
__DECLARE_VAR(UINT,PORT)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_CONNECT;
|
||||
|
||||
static void MQTT_CONNECT_init__(MQTT_CONNECT *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_CONNECT_body__(MQTT_CONNECT *data__);
|
||||
// FUNCTION_BLOCK MQTT_CONNECT_AUTH
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,CONNECT)
|
||||
__DECLARE_VAR(STRING,BROKER)
|
||||
__DECLARE_VAR(UINT,PORT)
|
||||
__DECLARE_VAR(STRING,USER)
|
||||
__DECLARE_VAR(STRING,PASSWORD)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_CONNECT_AUTH;
|
||||
|
||||
static void MQTT_CONNECT_AUTH_init__(MQTT_CONNECT_AUTH *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_CONNECT_AUTH_body__(MQTT_CONNECT_AUTH *data__);
|
||||
// FUNCTION_BLOCK MQTT_SUBSCRIBE
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,SUBSCRIBE)
|
||||
__DECLARE_VAR(STRING,TOPIC)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_SUBSCRIBE;
|
||||
|
||||
static void MQTT_SUBSCRIBE_init__(MQTT_SUBSCRIBE *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_SUBSCRIBE_body__(MQTT_SUBSCRIBE *data__);
|
||||
// FUNCTION_BLOCK MQTT_UNSUBSCRIBE
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,UNSUBSCRIBE)
|
||||
__DECLARE_VAR(STRING,TOPIC)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_UNSUBSCRIBE;
|
||||
|
||||
static void MQTT_UNSUBSCRIBE_init__(MQTT_UNSUBSCRIBE *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_UNSUBSCRIBE_body__(MQTT_UNSUBSCRIBE *data__);
|
||||
// FUNCTION_BLOCK MQTT_DISCONNECT
|
||||
// Data part
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,DISCONNECT)
|
||||
__DECLARE_VAR(BOOL,SUCCESS)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
|
||||
} MQTT_DISCONNECT;
|
||||
|
||||
static void MQTT_DISCONNECT_init__(MQTT_DISCONNECT *data__, BOOL retain);
|
||||
// Code part
|
||||
static void MQTT_DISCONNECT_body__(MQTT_DISCONNECT *data__);
|
||||
|
||||
|
||||
// External C Functions
|
||||
uint8_t connect_mqtt(char *broker, uint16_t port);
|
||||
uint8_t connect_mqtt_auth(char *broker, uint16_t port, char *user, char *password);
|
||||
uint8_t mqtt_send(char *topic, char *message);
|
||||
void mqtt_loop();
|
||||
uint8_t mqtt_receive(char *topic, char *message);
|
||||
uint8_t mqtt_subscribe(char *topic);
|
||||
uint8_t mqtt_unsubscribe(char *topic);
|
||||
uint8_t mqtt_disconnect();
|
||||
|
||||
|
||||
static void MQTT_RECEIVE_init__(MQTT_RECEIVE *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->RECEIVE,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->TOPIC,__STRING_LITERAL(0,""),retain)
|
||||
__INIT_VAR(data__->RECEIVED,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->MESSAGE,__STRING_LITERAL(0,""),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_RECEIVE_body__(MQTT_RECEIVE *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
|
||||
if (__GET_VAR(data__->RECEIVE))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->TOPIC).body[__GET_VAR(data__->TOPIC).len] = '\0';
|
||||
|
||||
__GET_VAR(data__->MESSAGE).len = mqtt_receive(__GET_VAR(data__->TOPIC).body, __GET_VAR(data__->MESSAGE).body);
|
||||
if (__GET_VAR(data__->MESSAGE).len > 0)
|
||||
{
|
||||
__SET_VAR(data__->,RECEIVED,,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
__SET_VAR(data__->,RECEIVED,,0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__SET_VAR(data__->,RECEIVED,,0);
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_RECEIVE_body__()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void MQTT_SEND_init__(MQTT_SEND *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->SEND,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->TOPIC,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->MESSAGE,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_SEND_body__(MQTT_SEND *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
uint8_t message_sent = 0;
|
||||
|
||||
if (__GET_VAR(data__->SEND))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->TOPIC).body[__GET_VAR(data__->TOPIC).len] = '\0';
|
||||
__GET_VAR(data__->MESSAGE).body[__GET_VAR(data__->MESSAGE).len] = '\0';
|
||||
|
||||
message_sent = mqtt_send(__GET_VAR(data__->TOPIC).body, __GET_VAR(data__->MESSAGE).body);
|
||||
}
|
||||
|
||||
__SET_VAR(data__->,SUCCESS,,message_sent);
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_SEND_body__()
|
||||
|
||||
|
||||
|
||||
static void MQTT_CONNECT_init__(MQTT_CONNECT *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->CONNECT,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->BROKER,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->PORT,0,retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_CONNECT_body__(MQTT_CONNECT *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->CONNECT))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->BROKER).body[__GET_VAR(data__->BROKER).len] = '\0';
|
||||
|
||||
uint8_t mqtt_connected = connect_mqtt(__GET_VAR(data__->BROKER).body, __GET_VAR(data__->PORT));
|
||||
__SET_VAR(data__->,SUCCESS,,mqtt_connected);
|
||||
}
|
||||
|
||||
// Call MQTT loop every scan cycle after a successfull connection
|
||||
if (__GET_VAR(data__->SUCCESS))
|
||||
{
|
||||
mqtt_loop();
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_CONNECT_body__()
|
||||
|
||||
|
||||
|
||||
static void MQTT_CONNECT_AUTH_init__(MQTT_CONNECT_AUTH *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->CONNECT,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->BROKER,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->PORT,0,retain)
|
||||
__INIT_VAR(data__->USER,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->PASSWORD,__STRING_LITERAL(1,"\0"),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_CONNECT_AUTH_body__(MQTT_CONNECT_AUTH *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->CONNECT))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->BROKER).body[__GET_VAR(data__->BROKER).len] = '\0';
|
||||
__GET_VAR(data__->USER).body[__GET_VAR(data__->USER).len] = '\0';
|
||||
__GET_VAR(data__->PASSWORD).body[__GET_VAR(data__->PASSWORD).len] = '\0';
|
||||
|
||||
uint8_t mqtt_connected = connect_mqtt_auth(__GET_VAR(data__->BROKER).body, __GET_VAR(data__->PORT), __GET_VAR(data__->USER).body, __GET_VAR(data__->PASSWORD).body);
|
||||
__SET_VAR(data__->,SUCCESS,,mqtt_connected);
|
||||
}
|
||||
|
||||
// Call MQTT loop every scan cycle after a successfull connection
|
||||
if (__GET_VAR(data__->SUCCESS))
|
||||
{
|
||||
mqtt_loop();
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_CONNECT_AUTH_body__()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void MQTT_SUBSCRIBE_init__(MQTT_SUBSCRIBE *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->SUBSCRIBE,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->TOPIC,__STRING_LITERAL(0,""),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_SUBSCRIBE_body__(MQTT_SUBSCRIBE *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->SUBSCRIBE))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->TOPIC).body[__GET_VAR(data__->TOPIC).len] = '\0';
|
||||
|
||||
uint8_t topic_subscribed = mqtt_subscribe(__GET_VAR(data__->TOPIC).body);
|
||||
__SET_VAR(data__->,SUCCESS,,topic_subscribed);
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_SUBSCRIBE_body__()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void MQTT_UNSUBSCRIBE_init__(MQTT_UNSUBSCRIBE *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->UNSUBSCRIBE,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->TOPIC,__STRING_LITERAL(0,""),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_UNSUBSCRIBE_body__(MQTT_UNSUBSCRIBE *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->UNSUBSCRIBE))
|
||||
{
|
||||
// Make sure strings are NULL terminated
|
||||
__GET_VAR(data__->TOPIC).body[__GET_VAR(data__->TOPIC).len] = '\0';
|
||||
|
||||
uint8_t topic_unsubscribed = mqtt_unsubscribe(__GET_VAR(data__->TOPIC).body);
|
||||
__SET_VAR(data__->,SUCCESS,,topic_unsubscribed);
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_UNSUBSCRIBE_body__()
|
||||
|
||||
|
||||
|
||||
|
||||
static void MQTT_DISCONNECT_init__(MQTT_DISCONNECT *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->DISCONNECT,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->SUCCESS,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void MQTT_DISCONNECT_body__(MQTT_DISCONNECT *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// Initialise TEMP variables
|
||||
|
||||
if (__GET_VAR(data__->DISCONNECT))
|
||||
{
|
||||
uint8_t broker_disconnected = mqtt_disconnect();
|
||||
__SET_VAR(data__->,SUCCESS,,broker_disconnected);
|
||||
}
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
} // MQTT_DISCONNECT_body__()
|
||||
|
192
editor/arduino/src/lib/MQTT.txt
Normal file → Executable file
192
editor/arduino/src/lib/MQTT.txt
Normal file → Executable file
@ -1,96 +1,96 @@
|
||||
FUNCTION_BLOCK MQTT_RECEIVE
|
||||
VAR_INPUT
|
||||
RECEIVE : BOOL;
|
||||
TOPIC : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
RECEIVED : BOOL;
|
||||
MESSAGE : STRING;
|
||||
END_VAR
|
||||
|
||||
RECEIVED := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_SEND
|
||||
VAR_INPUT
|
||||
SEND : BOOL;
|
||||
TOPIC : STRING;
|
||||
MESSAGE : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_CONNECT
|
||||
VAR_INPUT
|
||||
CONNECT : BOOL;
|
||||
BROKER : STRING;
|
||||
PORT : UINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_CONNECT_AUTH
|
||||
VAR_INPUT
|
||||
CONNECT : BOOL;
|
||||
BROKER : STRING;
|
||||
PORT : UINT;
|
||||
USER : STRING;
|
||||
PASSWORD : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_SUBSCRIBE
|
||||
VAR_INPUT
|
||||
SUBSCRIBE : BOOL;
|
||||
TOPIC : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_UNSUBSCRIBE
|
||||
VAR_INPUT
|
||||
UNSUBSCRIBE : BOOL;
|
||||
TOPIC : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_DISCONNECT
|
||||
VAR_INPUT
|
||||
DISCONNECT : BOOL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_RECEIVE
|
||||
VAR_INPUT
|
||||
RECEIVE : BOOL;
|
||||
TOPIC : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
RECEIVED : BOOL;
|
||||
MESSAGE : STRING;
|
||||
END_VAR
|
||||
|
||||
RECEIVED := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_SEND
|
||||
VAR_INPUT
|
||||
SEND : BOOL;
|
||||
TOPIC : STRING;
|
||||
MESSAGE : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_CONNECT
|
||||
VAR_INPUT
|
||||
CONNECT : BOOL;
|
||||
BROKER : STRING;
|
||||
PORT : UINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_CONNECT_AUTH
|
||||
VAR_INPUT
|
||||
CONNECT : BOOL;
|
||||
BROKER : STRING;
|
||||
PORT : UINT;
|
||||
USER : STRING;
|
||||
PASSWORD : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_SUBSCRIBE
|
||||
VAR_INPUT
|
||||
SUBSCRIBE : BOOL;
|
||||
TOPIC : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_UNSUBSCRIBE
|
||||
VAR_INPUT
|
||||
UNSUBSCRIBE : BOOL;
|
||||
TOPIC : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK MQTT_DISCONNECT
|
||||
VAR_INPUT
|
||||
DISCONNECT : BOOL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
|
||||
SUCCESS := 0;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
272
editor/arduino/src/lib/accessor.h
Normal file → Executable file
272
editor/arduino/src/lib/accessor.h
Normal file → Executable file
@ -1,136 +1,136 @@
|
||||
#ifndef __ACCESSOR_H
|
||||
#define __ACCESSOR_H
|
||||
|
||||
#define __INITIAL_VALUE(...) __VA_ARGS__
|
||||
|
||||
// variable declaration macros
|
||||
#define __DECLARE_VAR(type, name)\
|
||||
__IEC_##type##_t name;
|
||||
#define __DECLARE_GLOBAL(type, domain, name)\
|
||||
__IEC_##type##_t domain##__##name;\
|
||||
static __IEC_##type##_t *GLOBAL__##name = &(domain##__##name);\
|
||||
void __INIT_GLOBAL_##name(type value) {\
|
||||
(*GLOBAL__##name).value = value;\
|
||||
}\
|
||||
IEC_BYTE __IS_GLOBAL_##name##_FORCED(void) {\
|
||||
return (*GLOBAL__##name).flags & __IEC_FORCE_FLAG;\
|
||||
}\
|
||||
type* __GET_GLOBAL_##name(void) {\
|
||||
return &((*GLOBAL__##name).value);\
|
||||
}
|
||||
#define __DECLARE_GLOBAL_FB(type, domain, name)\
|
||||
type domain##__##name;\
|
||||
static type *GLOBAL__##name = &(domain##__##name);\
|
||||
type* __GET_GLOBAL_##name(void) {\
|
||||
return &(*GLOBAL__##name);\
|
||||
}\
|
||||
extern void type##_init__(type* data__, BOOL retain);
|
||||
#define __DECLARE_GLOBAL_LOCATION(type, location)\
|
||||
extern type *location;
|
||||
#define __DECLARE_GLOBAL_LOCATED(type, resource, name)\
|
||||
__IEC_##type##_p resource##__##name;\
|
||||
static __IEC_##type##_p *GLOBAL__##name = &(resource##__##name);\
|
||||
void __INIT_GLOBAL_##name(type value) {\
|
||||
*((*GLOBAL__##name).value) = value;\
|
||||
}\
|
||||
IEC_BYTE __IS_GLOBAL_##name##_FORCED(void) {\
|
||||
return (*GLOBAL__##name).flags & __IEC_FORCE_FLAG;\
|
||||
}\
|
||||
type* __GET_GLOBAL_##name(void) {\
|
||||
return (*GLOBAL__##name).value;\
|
||||
}
|
||||
#define __DECLARE_GLOBAL_PROTOTYPE(type, name)\
|
||||
extern type* __GET_GLOBAL_##name(void);
|
||||
#define __DECLARE_EXTERNAL(type, name)\
|
||||
__IEC_##type##_p name;
|
||||
#define __DECLARE_EXTERNAL_FB(type, name)\
|
||||
type* name;
|
||||
#define __DECLARE_LOCATED(type, name)\
|
||||
__IEC_##type##_p name;
|
||||
|
||||
|
||||
// variable initialization macros
|
||||
#define __INIT_RETAIN(name, retained)\
|
||||
name.flags |= retained?__IEC_RETAIN_FLAG:0;
|
||||
#define __INIT_VAR(name, initial, retained)\
|
||||
name.value = initial;\
|
||||
__INIT_RETAIN(name, retained)
|
||||
#define __INIT_GLOBAL(type, name, initial, retained)\
|
||||
{\
|
||||
static const type temp = initial;\
|
||||
__INIT_GLOBAL_##name(temp);\
|
||||
__INIT_RETAIN((*GLOBAL__##name), retained)\
|
||||
}
|
||||
#define __INIT_GLOBAL_FB(type, name, retained)\
|
||||
type##_init__(&(*GLOBAL__##name), retained);
|
||||
#define __INIT_GLOBAL_LOCATED(domain, name, location, retained)\
|
||||
domain##__##name.value = location;\
|
||||
__INIT_RETAIN(domain##__##name, retained)
|
||||
#define __INIT_EXTERNAL(type, global, name, retained)\
|
||||
{\
|
||||
name.value = __GET_GLOBAL_##global();\
|
||||
__INIT_RETAIN(name, retained)\
|
||||
}
|
||||
#define __INIT_EXTERNAL_FB(type, global, name, retained)\
|
||||
name = __GET_GLOBAL_##global();
|
||||
#define __INIT_LOCATED(type, location, name, retained)\
|
||||
{\
|
||||
extern type *location;\
|
||||
name.value = location;\
|
||||
__INIT_RETAIN(name, retained)\
|
||||
}
|
||||
#define __INIT_LOCATED_VALUE(name, initial)\
|
||||
*(name.value) = initial;
|
||||
|
||||
|
||||
// variable getting macros
|
||||
#define __GET_VAR(name, ...)\
|
||||
name.value __VA_ARGS__
|
||||
#define __GET_EXTERNAL(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : (*(name.value)) __VA_ARGS__)
|
||||
#define __GET_EXTERNAL_FB(name, ...)\
|
||||
__GET_VAR(((*name) __VA_ARGS__))
|
||||
#define __GET_LOCATED(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : (*(name.value)) __VA_ARGS__)
|
||||
|
||||
#define __GET_VAR_BY_REF(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &(name.value __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_BY_REF(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &((*(name.value)) __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_FB_BY_REF(name, ...)\
|
||||
__GET_EXTERNAL_BY_REF(((*name) __VA_ARGS__))
|
||||
#define __GET_LOCATED_BY_REF(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &((*(name.value)) __VA_ARGS__))
|
||||
|
||||
#define __GET_VAR_REF(name, ...)\
|
||||
(&(name.value __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_REF(name, ...)\
|
||||
(&((*(name.value)) __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_FB_REF(name, ...)\
|
||||
(&(__GET_VAR(((*name) __VA_ARGS__))))
|
||||
#define __GET_LOCATED_REF(name, ...)\
|
||||
(&((*(name.value)) __VA_ARGS__))
|
||||
|
||||
#define __GET_VAR_DREF(name, ...)\
|
||||
(*(name.value __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_DREF(name, ...)\
|
||||
(*((*(name.value)) __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_FB_DREF(name, ...)\
|
||||
(*(__GET_VAR(((*name) __VA_ARGS__))))
|
||||
#define __GET_LOCATED_DREF(name, ...)\
|
||||
(*((*(name.value)) __VA_ARGS__))
|
||||
|
||||
|
||||
// variable setting macros
|
||||
#define __SET_VAR(prefix, name, suffix, new_value)\
|
||||
if (!(prefix name.flags & __IEC_FORCE_FLAG)) prefix name.value suffix = new_value
|
||||
#define __SET_EXTERNAL(prefix, name, suffix, new_value)\
|
||||
{extern IEC_BYTE __IS_GLOBAL_##name##_FORCED();\
|
||||
if (!(prefix name.flags & __IEC_FORCE_FLAG || __IS_GLOBAL_##name##_FORCED()))\
|
||||
(*(prefix name.value)) suffix = new_value;}
|
||||
#define __SET_EXTERNAL_FB(prefix, name, suffix, new_value)\
|
||||
__SET_VAR((*(prefix name)), suffix, new_value)
|
||||
#define __SET_LOCATED(prefix, name, suffix, new_value)\
|
||||
if (!(prefix name.flags & __IEC_FORCE_FLAG)) *(prefix name.value) suffix = new_value
|
||||
|
||||
#endif //__ACCESSOR_H
|
||||
#ifndef __ACCESSOR_H
|
||||
#define __ACCESSOR_H
|
||||
|
||||
#define __INITIAL_VALUE(...) __VA_ARGS__
|
||||
|
||||
// variable declaration macros
|
||||
#define __DECLARE_VAR(type, name)\
|
||||
__IEC_##type##_t name;
|
||||
#define __DECLARE_GLOBAL(type, domain, name)\
|
||||
__IEC_##type##_t domain##__##name;\
|
||||
static __IEC_##type##_t *GLOBAL__##name = &(domain##__##name);\
|
||||
void __INIT_GLOBAL_##name(type value) {\
|
||||
(*GLOBAL__##name).value = value;\
|
||||
}\
|
||||
IEC_BYTE __IS_GLOBAL_##name##_FORCED(void) {\
|
||||
return (*GLOBAL__##name).flags & __IEC_FORCE_FLAG;\
|
||||
}\
|
||||
type* __GET_GLOBAL_##name(void) {\
|
||||
return &((*GLOBAL__##name).value);\
|
||||
}
|
||||
#define __DECLARE_GLOBAL_FB(type, domain, name)\
|
||||
type domain##__##name;\
|
||||
static type *GLOBAL__##name = &(domain##__##name);\
|
||||
type* __GET_GLOBAL_##name(void) {\
|
||||
return &(*GLOBAL__##name);\
|
||||
}\
|
||||
extern void type##_init__(type* data__, BOOL retain);
|
||||
#define __DECLARE_GLOBAL_LOCATION(type, location)\
|
||||
extern type *location;
|
||||
#define __DECLARE_GLOBAL_LOCATED(type, resource, name)\
|
||||
__IEC_##type##_p resource##__##name;\
|
||||
static __IEC_##type##_p *GLOBAL__##name = &(resource##__##name);\
|
||||
void __INIT_GLOBAL_##name(type value) {\
|
||||
*((*GLOBAL__##name).value) = value;\
|
||||
}\
|
||||
IEC_BYTE __IS_GLOBAL_##name##_FORCED(void) {\
|
||||
return (*GLOBAL__##name).flags & __IEC_FORCE_FLAG;\
|
||||
}\
|
||||
type* __GET_GLOBAL_##name(void) {\
|
||||
return (*GLOBAL__##name).value;\
|
||||
}
|
||||
#define __DECLARE_GLOBAL_PROTOTYPE(type, name)\
|
||||
extern type* __GET_GLOBAL_##name(void);
|
||||
#define __DECLARE_EXTERNAL(type, name)\
|
||||
__IEC_##type##_p name;
|
||||
#define __DECLARE_EXTERNAL_FB(type, name)\
|
||||
type* name;
|
||||
#define __DECLARE_LOCATED(type, name)\
|
||||
__IEC_##type##_p name;
|
||||
|
||||
|
||||
// variable initialization macros
|
||||
#define __INIT_RETAIN(name, retained)\
|
||||
name.flags |= retained?__IEC_RETAIN_FLAG:0;
|
||||
#define __INIT_VAR(name, initial, retained)\
|
||||
name.value = initial;\
|
||||
__INIT_RETAIN(name, retained)
|
||||
#define __INIT_GLOBAL(type, name, initial, retained)\
|
||||
{\
|
||||
static const type temp = initial;\
|
||||
__INIT_GLOBAL_##name(temp);\
|
||||
__INIT_RETAIN((*GLOBAL__##name), retained)\
|
||||
}
|
||||
#define __INIT_GLOBAL_FB(type, name, retained)\
|
||||
type##_init__(&(*GLOBAL__##name), retained);
|
||||
#define __INIT_GLOBAL_LOCATED(domain, name, location, retained)\
|
||||
domain##__##name.value = location;\
|
||||
__INIT_RETAIN(domain##__##name, retained)
|
||||
#define __INIT_EXTERNAL(type, global, name, retained)\
|
||||
{\
|
||||
name.value = __GET_GLOBAL_##global();\
|
||||
__INIT_RETAIN(name, retained)\
|
||||
}
|
||||
#define __INIT_EXTERNAL_FB(type, global, name, retained)\
|
||||
name = __GET_GLOBAL_##global();
|
||||
#define __INIT_LOCATED(type, location, name, retained)\
|
||||
{\
|
||||
extern type *location;\
|
||||
name.value = location;\
|
||||
__INIT_RETAIN(name, retained)\
|
||||
}
|
||||
#define __INIT_LOCATED_VALUE(name, initial)\
|
||||
*(name.value) = initial;
|
||||
|
||||
|
||||
// variable getting macros
|
||||
#define __GET_VAR(name, ...)\
|
||||
name.value __VA_ARGS__
|
||||
#define __GET_EXTERNAL(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : (*(name.value)) __VA_ARGS__)
|
||||
#define __GET_EXTERNAL_FB(name, ...)\
|
||||
__GET_VAR(((*name) __VA_ARGS__))
|
||||
#define __GET_LOCATED(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : (*(name.value)) __VA_ARGS__)
|
||||
|
||||
#define __GET_VAR_BY_REF(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &(name.value __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_BY_REF(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &((*(name.value)) __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_FB_BY_REF(name, ...)\
|
||||
__GET_EXTERNAL_BY_REF(((*name) __VA_ARGS__))
|
||||
#define __GET_LOCATED_BY_REF(name, ...)\
|
||||
((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &((*(name.value)) __VA_ARGS__))
|
||||
|
||||
#define __GET_VAR_REF(name, ...)\
|
||||
(&(name.value __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_REF(name, ...)\
|
||||
(&((*(name.value)) __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_FB_REF(name, ...)\
|
||||
(&(__GET_VAR(((*name) __VA_ARGS__))))
|
||||
#define __GET_LOCATED_REF(name, ...)\
|
||||
(&((*(name.value)) __VA_ARGS__))
|
||||
|
||||
#define __GET_VAR_DREF(name, ...)\
|
||||
(*(name.value __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_DREF(name, ...)\
|
||||
(*((*(name.value)) __VA_ARGS__))
|
||||
#define __GET_EXTERNAL_FB_DREF(name, ...)\
|
||||
(*(__GET_VAR(((*name) __VA_ARGS__))))
|
||||
#define __GET_LOCATED_DREF(name, ...)\
|
||||
(*((*(name.value)) __VA_ARGS__))
|
||||
|
||||
|
||||
// variable setting macros
|
||||
#define __SET_VAR(prefix, name, suffix, new_value)\
|
||||
if (!(prefix name.flags & __IEC_FORCE_FLAG)) prefix name.value suffix = new_value
|
||||
#define __SET_EXTERNAL(prefix, name, suffix, new_value)\
|
||||
{extern IEC_BYTE __IS_GLOBAL_##name##_FORCED();\
|
||||
if (!(prefix name.flags & __IEC_FORCE_FLAG || __IS_GLOBAL_##name##_FORCED()))\
|
||||
(*(prefix name.value)) suffix = new_value;}
|
||||
#define __SET_EXTERNAL_FB(prefix, name, suffix, new_value)\
|
||||
__SET_VAR((*(prefix name)), suffix, new_value)
|
||||
#define __SET_LOCATED(prefix, name, suffix, new_value)\
|
||||
if (!(prefix name.flags & __IEC_FORCE_FLAG)) *(prefix name.value) suffix = new_value
|
||||
|
||||
#endif //__ACCESSOR_H
|
||||
|
436
editor/arduino/src/lib/arduino.txt
Normal file → Executable file
436
editor/arduino/src/lib/arduino.txt
Normal file → Executable file
@ -1,194 +1,242 @@
|
||||
(*
|
||||
* This file is part of OpenPLC - an open source Programmable
|
||||
* Logic Controller compliant with IEC 61131-3
|
||||
*
|
||||
* Copyright (C) 2021 Thiago Alves
|
||||
*
|
||||
* See COPYING and COPYING.LESSER files for copyright details.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
* This code is made available on the understanding that it will not be
|
||||
* used in safety-critical situations without a full and competent review.
|
||||
*)
|
||||
|
||||
|
||||
|
||||
(*
|
||||
* An IEC 61131-3 compiler.
|
||||
*
|
||||
* Based on the
|
||||
* FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
(*
|
||||
* This is a dummy implementation of this block since
|
||||
* its code is actually written in C, not ST
|
||||
*
|
||||
* READ_DS18B20
|
||||
* -------------
|
||||
*)
|
||||
|
||||
FUNCTION_BLOCK DS18B20
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT : REAL;
|
||||
END_VAR
|
||||
OUT := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK DS18B20_2_OUT
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT_0 : REAL;
|
||||
OUT_1 : REAL;
|
||||
END_VAR
|
||||
OUT_0 := 0.0;
|
||||
OUT_1 := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK DS18B20_3_OUT
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT_0 : REAL;
|
||||
OUT_1 : REAL;
|
||||
OUT_2 : REAL;
|
||||
END_VAR
|
||||
OUT_0 := 0.0;
|
||||
OUT_1 := 0.0;
|
||||
OUT_2 := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK DS18B20_4_OUT
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT_0 : REAL;
|
||||
OUT_1 : REAL;
|
||||
OUT_2 : REAL;
|
||||
OUT_3 : REAL;
|
||||
END_VAR
|
||||
OUT_0 := 0.0;
|
||||
OUT_1 := 0.0;
|
||||
OUT_2 := 0.0;
|
||||
OUT_3 := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK DS18B20_5_OUT
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT_0 : REAL;
|
||||
OUT_1 : REAL;
|
||||
OUT_2 : REAL;
|
||||
OUT_3 : REAL;
|
||||
OUT_4 : REAL;
|
||||
END_VAR
|
||||
OUT_0 := 0.0;
|
||||
OUT_1 := 0.0;
|
||||
OUT_2 := 0.0;
|
||||
OUT_3 := 0.0;
|
||||
OUT_4 := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
(*
|
||||
* This is a dummy implementation of this block since
|
||||
* its code is actually written in C, not ST
|
||||
*
|
||||
* CLOUD_xxx
|
||||
* -------------
|
||||
*)
|
||||
|
||||
FUNCTION_BLOCK CLOUD_ADD_BOOL
|
||||
VAR_INPUT
|
||||
VAR_NAME : STRING;
|
||||
BOOL_VAR : BOOL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
SUCCESS := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK CLOUD_ADD_DINT
|
||||
VAR_INPUT
|
||||
VAR_NAME : STRING;
|
||||
DINT_VAR : DINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
SUCCESS := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK CLOUD_ADD_REAL
|
||||
VAR_INPUT
|
||||
VAR_NAME : STRING;
|
||||
REAL_VAR : REAL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
SUCCESS := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK CLOUD_BEGIN
|
||||
VAR_INPUT
|
||||
THING_ID : STRING;
|
||||
SSID : STRING;
|
||||
PASS : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
SUCCESS := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK PWM_CONTROLLER
|
||||
VAR_INPUT
|
||||
CHANNEL : SINT;
|
||||
FREQ : REAL;
|
||||
DUTY : REAL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
VAR
|
||||
internal_ch : SINT;
|
||||
internal_freq : REAL;
|
||||
internal_duty : REAL;
|
||||
END_VAR
|
||||
|
||||
IF CHANNEL < 1 THEN
|
||||
SUCCESS := FALSE;
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
|
||||
IF (CHANNEL <> internal_ch) OR (FREQ <> internal_freq) OR (DUTY <> internal_duty) THEN
|
||||
SUCCESS := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
(*
|
||||
* This file is part of OpenPLC - an open source Programmable
|
||||
* Logic Controller compliant with IEC 61131-3
|
||||
*
|
||||
* Copyright (C) 2021 Thiago Alves
|
||||
*
|
||||
* See COPYING and COPYING.LESSER files for copyright details.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
* This code is made available on the understanding that it will not be
|
||||
* used in safety-critical situations without a full and competent review.
|
||||
*)
|
||||
|
||||
|
||||
|
||||
(*
|
||||
* An IEC 61131-3 compiler.
|
||||
*
|
||||
* Based on the
|
||||
* FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
(*
|
||||
* This is a dummy implementation of this block since
|
||||
* its code is actually written in C, not ST
|
||||
*
|
||||
* READ_DS18B20
|
||||
* -------------
|
||||
*)
|
||||
|
||||
FUNCTION_BLOCK DS18B20
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT : REAL;
|
||||
END_VAR
|
||||
OUT := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK DS18B20_2_OUT
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT_0 : REAL;
|
||||
OUT_1 : REAL;
|
||||
END_VAR
|
||||
OUT_0 := 0.0;
|
||||
OUT_1 := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK DS18B20_3_OUT
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT_0 : REAL;
|
||||
OUT_1 : REAL;
|
||||
OUT_2 : REAL;
|
||||
END_VAR
|
||||
OUT_0 := 0.0;
|
||||
OUT_1 := 0.0;
|
||||
OUT_2 := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK DS18B20_4_OUT
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT_0 : REAL;
|
||||
OUT_1 : REAL;
|
||||
OUT_2 : REAL;
|
||||
OUT_3 : REAL;
|
||||
END_VAR
|
||||
OUT_0 := 0.0;
|
||||
OUT_1 := 0.0;
|
||||
OUT_2 := 0.0;
|
||||
OUT_3 := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK DS18B20_5_OUT
|
||||
VAR_INPUT
|
||||
PIN : SINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
OUT_0 : REAL;
|
||||
OUT_1 : REAL;
|
||||
OUT_2 : REAL;
|
||||
OUT_3 : REAL;
|
||||
OUT_4 : REAL;
|
||||
END_VAR
|
||||
OUT_0 := 0.0;
|
||||
OUT_1 := 0.0;
|
||||
OUT_2 := 0.0;
|
||||
OUT_3 := 0.0;
|
||||
OUT_4 := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
(*
|
||||
* This is a dummy implementation of this block since
|
||||
* its code is actually written in C, not ST
|
||||
*
|
||||
* CLOUD_xxx
|
||||
* -------------
|
||||
*)
|
||||
|
||||
FUNCTION_BLOCK CLOUD_ADD_BOOL
|
||||
VAR_INPUT
|
||||
VAR_NAME : STRING;
|
||||
BOOL_VAR : BOOL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
SUCCESS := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK CLOUD_ADD_DINT
|
||||
VAR_INPUT
|
||||
VAR_NAME : STRING;
|
||||
DINT_VAR : DINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
SUCCESS := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK CLOUD_ADD_REAL
|
||||
VAR_INPUT
|
||||
VAR_NAME : STRING;
|
||||
REAL_VAR : REAL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
SUCCESS := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK CLOUD_BEGIN
|
||||
VAR_INPUT
|
||||
THING_ID : STRING;
|
||||
SSID : STRING;
|
||||
PASS : STRING;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
SUCCESS := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK PWM_CONTROLLER
|
||||
VAR_INPUT
|
||||
CHANNEL : SINT;
|
||||
FREQ : REAL;
|
||||
DUTY : REAL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
SUCCESS : BOOL;
|
||||
END_VAR
|
||||
VAR
|
||||
internal_ch : SINT;
|
||||
internal_freq : REAL;
|
||||
internal_duty : REAL;
|
||||
END_VAR
|
||||
|
||||
IF CHANNEL < 1 THEN
|
||||
SUCCESS := FALSE;
|
||||
RETURN;
|
||||
END_IF;
|
||||
|
||||
|
||||
IF (CHANNEL <> internal_ch) OR (FREQ <> internal_freq) OR (DUTY <> internal_duty) THEN
|
||||
SUCCESS := TRUE;
|
||||
END_IF;
|
||||
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK ARDUINOCAN_CONF
|
||||
VAR_INPUT
|
||||
EN_PIN : SINT;
|
||||
BR : LINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
DONE : BOOL;
|
||||
END_VAR
|
||||
DONE := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK ARDUINOCAN_WRITE
|
||||
VAR_INPUT
|
||||
ID : DWORD;
|
||||
D0 : USINT;
|
||||
D1 : USINT;
|
||||
D2 : USINT;
|
||||
D3 : USINT;
|
||||
D4 : USINT;
|
||||
D5 : USINT;
|
||||
D6 : USINT;
|
||||
D7 : USINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
DONE : BOOL;
|
||||
END_VAR
|
||||
DONE := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
FUNCTION_BLOCK ARDUINOCAN_WRITE_WORD
|
||||
VAR_INPUT
|
||||
ID : DWORD;
|
||||
DATA :LWORD;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
DONE : BOOL;
|
||||
END_VAR
|
||||
DONE := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK ARDUINOCAN_READ
|
||||
VAR_OUTPUT
|
||||
DATA : LWORD;
|
||||
END_VAR
|
||||
DATA := 0;
|
||||
END_FUNCTION_BLOCK
|
||||
|
188
editor/arduino/src/lib/arduino_lib_FB.h
Normal file → Executable file
188
editor/arduino/src/lib/arduino_lib_FB.h
Normal file → Executable file
@ -127,6 +127,59 @@ typedef struct {
|
||||
|
||||
} CLOUD_BEGIN;
|
||||
|
||||
// ARDUINOCAN_STRUCTURE
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,SETUP_BLOCK)
|
||||
__DECLARE_VAR(SINT,EN_PIN)
|
||||
__DECLARE_VAR(LINT,BR)
|
||||
__DECLARE_VAR(BOOL,DONE)
|
||||
// FB private variables - TEMP, private and located variables
|
||||
} ARDUINOCAN_CONF;
|
||||
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,SETUP_BLOCK)
|
||||
__DECLARE_VAR(DWORD,ID)
|
||||
__DECLARE_VAR(USINT,D0)
|
||||
__DECLARE_VAR(USINT,D1)
|
||||
__DECLARE_VAR(USINT,D2)
|
||||
__DECLARE_VAR(USINT,D3)
|
||||
__DECLARE_VAR(USINT,D4)
|
||||
__DECLARE_VAR(USINT,D5)
|
||||
__DECLARE_VAR(USINT,D6)
|
||||
__DECLARE_VAR(USINT,D7)
|
||||
__DECLARE_VAR(BOOL,DONE)
|
||||
// FB private variables - TEMP, private and located variables
|
||||
} ARDUINOCAN_WRITE;
|
||||
|
||||
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,SETUP_BLOCK)
|
||||
__DECLARE_VAR(DWORD,ID)
|
||||
__DECLARE_VAR(LWORD,DATA)
|
||||
__DECLARE_VAR(BOOL,DONE)
|
||||
// FB private variables - TEMP, private and located variables
|
||||
} ARDUINOCAN_WRITE_WORD;
|
||||
|
||||
|
||||
typedef struct {
|
||||
// FB Interface - IN, OUT, IN_OUT variables
|
||||
__DECLARE_VAR(BOOL,EN)
|
||||
__DECLARE_VAR(BOOL,ENO)
|
||||
__DECLARE_VAR(BOOL,SETUP_BLOCK)
|
||||
__DECLARE_VAR(LWORD,DATA)
|
||||
|
||||
// FB private variables - TEMP, private and located variables
|
||||
} ARDUINOCAN_READ;
|
||||
|
||||
/************************************************************************
|
||||
* END OF ARDUINO LIB BLOCKS *
|
||||
************************************************************************/
|
||||
@ -533,6 +586,141 @@ __end:
|
||||
return;
|
||||
} // PWM_CONTROLLER_body__()
|
||||
|
||||
#include <stdbool.h>
|
||||
void *init_arduinocan(uint8_t, int);
|
||||
bool write_arduinocan(uint32_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t,uint8_t);
|
||||
bool write_arduinocan_word(uint32_t, uint64_t);
|
||||
uint64_t read_arduinocan();
|
||||
|
||||
//Init
|
||||
//definition of blocks
|
||||
static void ARDUINOCAN_CONF_init__(ARDUINOCAN_CONF *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->SETUP_BLOCK,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->EN_PIN,0,retain)
|
||||
__INIT_VAR(data__->BR,250000,retain)
|
||||
__INIT_VAR(data__->DONE,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void ARDUINOCAN_CONF_body__(ARDUINOCAN_CONF *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
// // Initialise TEMP variables
|
||||
if (!__GET_VAR(data__->SETUP_BLOCK)) {
|
||||
init_arduinocan((uint8_t)__GET_VAR(data__->EN_PIN),(int)__GET_VAR(data__->BR));
|
||||
__SET_VAR(data__->,SETUP_BLOCK,,__BOOL_LITERAL(TRUE));
|
||||
__SET_VAR(data__->,DONE,,__BOOL_LITERAL(TRUE));
|
||||
|
||||
}
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
}
|
||||
|
||||
// write single byte
|
||||
//definition of blocks
|
||||
static void ARDUINOCAN_WRITE_init__(ARDUINOCAN_WRITE *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ID,0,retain)
|
||||
__INIT_VAR(data__->D0,0,retain)
|
||||
__INIT_VAR(data__->D1,0,retain)
|
||||
__INIT_VAR(data__->D2,0,retain)
|
||||
__INIT_VAR(data__->D3,0,retain)
|
||||
__INIT_VAR(data__->D4,0,retain)
|
||||
__INIT_VAR(data__->D5,0,retain)
|
||||
__INIT_VAR(data__->D6,0,retain)
|
||||
__INIT_VAR(data__->D7,0,retain)
|
||||
__INIT_VAR(data__->DONE,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void ARDUINOCAN_WRITE_body__(ARDUINOCAN_WRITE *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
|
||||
__SET_VAR(data__->,DONE,,__BOOL_LITERAL(write_arduinocan((uint32_t)__GET_VAR(data__->ID),(uint8_t)__GET_VAR(data__->D0),
|
||||
(uint8_t)__GET_VAR(data__->D1), (uint8_t)__GET_VAR(data__->D2),(uint8_t)__GET_VAR(data__->D3),
|
||||
(uint8_t)__GET_VAR(data__->D4), (uint8_t)__GET_VAR(data__->D5),(uint8_t)__GET_VAR(data__->D6),
|
||||
(uint8_t)__GET_VAR(data__->D7))));
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// write paylod in word
|
||||
//definition of blocks
|
||||
static void ARDUINOCAN_WRITE_WORD_init__(ARDUINOCAN_WRITE_WORD *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ID,0,retain)
|
||||
__INIT_VAR(data__->DATA,0,retain)
|
||||
__INIT_VAR(data__->DONE,__BOOL_LITERAL(FALSE),retain)
|
||||
}
|
||||
|
||||
// Code part
|
||||
static void ARDUINOCAN_WRITE_WORD_body__(ARDUINOCAN_WRITE_WORD *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
|
||||
|
||||
__SET_VAR(data__->,DONE,,__BOOL_LITERAL(write_arduinocan_word(__GET_VAR(data__->ID),
|
||||
__GET_VAR(data__->DATA))));
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
}
|
||||
|
||||
//definition of blocks
|
||||
static void ARDUINOCAN_READ_init__(ARDUINOCAN_READ *data__, BOOL retain) {
|
||||
__INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
|
||||
__INIT_VAR(data__->SETUP_BLOCK,__BOOL_LITERAL(FALSE),retain)
|
||||
__INIT_VAR(data__->DATA,0,retain)
|
||||
}
|
||||
// Code part
|
||||
static void ARDUINOCAN_READ_body__(ARDUINOCAN_READ *data__) {
|
||||
// Control execution
|
||||
if (!__GET_VAR(data__->EN)) {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
__SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
|
||||
}
|
||||
|
||||
__SET_VAR(data__->,DATA,,read_arduinocan());
|
||||
|
||||
goto __end;
|
||||
|
||||
__end:
|
||||
return;
|
||||
}
|
||||
/************************************************************************
|
||||
* END OF ARDUINO LIB BLOCKS *
|
||||
************************************************************************/
|
||||
|
168
editor/arduino/src/lib/bistable.txt
Normal file → Executable file
168
editor/arduino/src/lib/bistable.txt
Normal file → Executable file
@ -1,84 +1,84 @@
|
||||
(*
|
||||
* This file is part of matiec - a compiler for the programming
|
||||
* languages defined in IEC 61131-3
|
||||
*
|
||||
* Copyright (C) 2011 Mario de Sousa (msousa@fe.up.pt)
|
||||
*
|
||||
* See COPYING and COPYING.LESSER files for copyright details.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
* This code is made available on the understanding that it will not be
|
||||
* used in safety-critical situations without a full and competent review.
|
||||
*)
|
||||
|
||||
|
||||
|
||||
(*
|
||||
* An IEC 61131-3 compiler.
|
||||
*
|
||||
* Based on the
|
||||
* FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
(*
|
||||
* This is part of the library conatining the functions
|
||||
* and function blocks defined in the standard.
|
||||
*
|
||||
* SR and RS function blocks
|
||||
* -------------------------
|
||||
*)
|
||||
|
||||
(* The standard defines the SR FB thus:
|
||||
|
||||
+-----+
|
||||
S1----------------| >=1 |---Q1
|
||||
+---+ | |
|
||||
R------O| & |----| |
|
||||
Q1------| | | |
|
||||
+---+ +-----+
|
||||
*)
|
||||
|
||||
FUNCTION_BLOCK SR
|
||||
VAR_INPUT
|
||||
S1, R : BOOL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q1 : BOOL;
|
||||
END_VAR
|
||||
Q1 := S1 OR ((NOT R) AND Q1);
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
(* The standard defines the RS FB thus:
|
||||
+---+
|
||||
R1----------------O| & |---Q1
|
||||
+-----+ | |
|
||||
S-------| >=1 |----| |
|
||||
Q1------| | | |
|
||||
+-----+ +---+
|
||||
*)
|
||||
|
||||
FUNCTION_BLOCK RS
|
||||
VAR_INPUT
|
||||
S, R1 : BOOL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q1 : BOOL;
|
||||
END_VAR
|
||||
Q1 := (NOT R1) AND (S OR Q1);
|
||||
END_FUNCTION_BLOCK
|
||||
(*
|
||||
* This file is part of matiec - a compiler for the programming
|
||||
* languages defined in IEC 61131-3
|
||||
*
|
||||
* Copyright (C) 2011 Mario de Sousa (msousa@fe.up.pt)
|
||||
*
|
||||
* See COPYING and COPYING.LESSER files for copyright details.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
* This code is made available on the understanding that it will not be
|
||||
* used in safety-critical situations without a full and competent review.
|
||||
*)
|
||||
|
||||
|
||||
|
||||
(*
|
||||
* An IEC 61131-3 compiler.
|
||||
*
|
||||
* Based on the
|
||||
* FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
(*
|
||||
* This is part of the library conatining the functions
|
||||
* and function blocks defined in the standard.
|
||||
*
|
||||
* SR and RS function blocks
|
||||
* -------------------------
|
||||
*)
|
||||
|
||||
(* The standard defines the SR FB thus:
|
||||
|
||||
+-----+
|
||||
S1----------------| >=1 |---Q1
|
||||
+---+ | |
|
||||
R------O| & |----| |
|
||||
Q1------| | | |
|
||||
+---+ +-----+
|
||||
*)
|
||||
|
||||
FUNCTION_BLOCK SR
|
||||
VAR_INPUT
|
||||
S1, R : BOOL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q1 : BOOL;
|
||||
END_VAR
|
||||
Q1 := S1 OR ((NOT R) AND Q1);
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
(* The standard defines the RS FB thus:
|
||||
+---+
|
||||
R1----------------O| & |---Q1
|
||||
+-----+ | |
|
||||
S-------| >=1 |----| |
|
||||
Q1------| | | |
|
||||
+-----+ +---+
|
||||
*)
|
||||
|
||||
FUNCTION_BLOCK RS
|
||||
VAR_INPUT
|
||||
S, R1 : BOOL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q1 : BOOL;
|
||||
END_VAR
|
||||
Q1 := (NOT R1) AND (S OR Q1);
|
||||
END_FUNCTION_BLOCK
|
||||
|
920
editor/arduino/src/lib/counter.txt
Normal file → Executable file
920
editor/arduino/src/lib/counter.txt
Normal file → Executable file
@ -1,460 +1,460 @@
|
||||
(* Following taken directly from the IEC 61131.3 draft standard *)
|
||||
|
||||
(*
|
||||
* An IEC 61131-3 IL and ST compiler.
|
||||
*
|
||||
* Based on the
|
||||
* FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
(*
|
||||
* This is part of the library conatining the functions
|
||||
* and function blocks defined in the standard.
|
||||
*
|
||||
* Counter function blocks
|
||||
* -----------------------
|
||||
*)
|
||||
|
||||
|
||||
|
||||
(******************)
|
||||
(* *)
|
||||
(* C T U *)
|
||||
(* *)
|
||||
(******************)
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : INT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : INT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU_DINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : DINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : DINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU_LINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : LINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : LINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU_UDINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : UDINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : UDINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU_ULINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : ULINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : ULINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(******************)
|
||||
(* *)
|
||||
(* C T D *)
|
||||
(* *)
|
||||
(******************)
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : INT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : INT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD_DINT
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : DINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : DINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD_LINT
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : LINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : LINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD_UDINT
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : UDINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : UDINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD_ULINT
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : ULINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : ULINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
(********************)
|
||||
(* *)
|
||||
(* C T U D *)
|
||||
(* *)
|
||||
(********************)
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : INT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : INT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD_DINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : DINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : DINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD_LINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : LINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : LINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD_UDINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : UDINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : UDINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD_ULINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : ULINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : ULINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
(* Following taken directly from the IEC 61131.3 draft standard *)
|
||||
|
||||
(*
|
||||
* An IEC 61131-3 IL and ST compiler.
|
||||
*
|
||||
* Based on the
|
||||
* FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
|
||||
*
|
||||
*)
|
||||
|
||||
|
||||
(*
|
||||
* This is part of the library conatining the functions
|
||||
* and function blocks defined in the standard.
|
||||
*
|
||||
* Counter function blocks
|
||||
* -----------------------
|
||||
*)
|
||||
|
||||
|
||||
|
||||
(******************)
|
||||
(* *)
|
||||
(* C T U *)
|
||||
(* *)
|
||||
(******************)
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : INT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : INT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU_DINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : DINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : DINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU_LINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : LINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : LINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU_UDINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : UDINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : UDINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTU_ULINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
R : BOOL;
|
||||
PV : ULINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : ULINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CU_T(CU);
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
END_IF ;
|
||||
Q := (CV >= PV) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(******************)
|
||||
(* *)
|
||||
(* C T D *)
|
||||
(* *)
|
||||
(******************)
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : INT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : INT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD_DINT
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : DINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : DINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD_LINT
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : LINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : LINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD_UDINT
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : UDINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : UDINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTD_ULINT
|
||||
VAR_INPUT
|
||||
CD : BOOL;
|
||||
LD : BOOL;
|
||||
PV : ULINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Q : BOOL;
|
||||
CV : ULINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
IF LD THEN CV := PV ;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF ;
|
||||
Q := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
(********************)
|
||||
(* *)
|
||||
(* C T U D *)
|
||||
(* *)
|
||||
(********************)
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : INT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : INT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD_DINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : DINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : DINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD_LINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : LINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : LINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD_UDINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : UDINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : UDINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
||||
|
||||
FUNCTION_BLOCK CTUD_ULINT
|
||||
VAR_INPUT
|
||||
CU : BOOL;
|
||||
CD : BOOL;
|
||||
R : BOOL;
|
||||
LD : BOOL;
|
||||
PV : ULINT;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
QU : BOOL;
|
||||
QD : BOOL;
|
||||
CV : ULINT;
|
||||
END_VAR
|
||||
VAR
|
||||
CD_T: R_TRIG;
|
||||
CU_T: R_TRIG;
|
||||
END_VAR
|
||||
|
||||
CD_T(CD);
|
||||
CU_T(CU);
|
||||
|
||||
IF R THEN CV := 0 ;
|
||||
ELSIF LD THEN CV := PV ;
|
||||
ELSE
|
||||
IF NOT (CU_T.Q AND CD_T.Q) THEN
|
||||
IF CU_T.Q AND (CV < PV)
|
||||
THEN CV := CV+1;
|
||||
ELSIF CD_T.Q AND (CV > 0)
|
||||
THEN CV := CV-1;
|
||||
END_IF;
|
||||
END_IF;
|
||||
END_IF ;
|
||||
QU := (CV >= PV) ;
|
||||
QD := (CV <= 0) ;
|
||||
END_FUNCTION_BLOCK
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user