Brought changes from Beremiz up until commit 24768ad on branch python3. Added live monitoring support from OpenPLC master branch

This commit is contained in:
Autonomy Server 2023-11-15 21:15:00 -05:00
parent 35d7d079ec
commit baf70966a4
352 changed files with 39923 additions and 33360 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
editor/.DS_Store vendored

Binary file not shown.

View 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
View File

@ -0,0 +1,9 @@
*.pyc
**/__pycache__
.vscode
**/build/**
*.class
**/.svghmithumbs/**
**/my_*.der
**/my_*.pem
tests/tools/Docker/requirements.txt

View File

@ -1,6 +0,0 @@
repo: 215982c73cd664bf5b82a086a6bd0e75f8fe3d60
node: 8fb5c6eddc723baec392be98fe1969044539baee
branch: default
latesttag: null
latesttagdistance: 2129
changessincelatesttag: 2565

5
editor/.hgignore Executable file → Normal file
View 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
View File

View 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):

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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):

View File

@ -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]

View File

@ -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():

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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 = [

View File

@ -1,6 +1,7 @@
<!---
[![docs](https://readthedocs.org/projects/beremiz/badge/?version=latest)](https://beremiz.readthedocs.io)
-->
[![CI Automated testing](https://github.com/beremiz/beremiz/actions/workflows/run_tests_in_docker.yml/badge.svg?branch=python3)](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 :

Binary file not shown.

View File

@ -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"

Binary file not shown.

View File

@ -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
}
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View 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));
}

View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -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
View File

@ -1,3 +1,3 @@
extern "C" {
#include "openplc.h"
extern "C" {
#include "openplc.h"
}

View File

@ -0,0 +1 @@
__LOCATED_VAR(BOOL,__QX0_0,Q,X,0,0)

View File

@ -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__()

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

1 // Programs
2 0;CONFIG0.RES0.INSTANCE0;MQTT_EXAMPLE; 0;CONFIG0.RES0.INSTANCE0;PROGRAM0;
3 // Variables
4 0;FB;CONFIG0.RES0.INSTANCE0;CONFIG0.RES0.INSTANCE0;MQTT_EXAMPLE;; 0;FB;CONFIG0.RES0.INSTANCE0;CONFIG0.RES0.INSTANCE0;PROGRAM0;;
5 1;VAR;CONFIG0.RES0.INSTANCE0.BLINK_LED;CONFIG0.RES0.INSTANCE0.BLINK_LED;BOOL;BOOL; 1;VAR;CONFIG0.RES0.INSTANCE0.BUTTON;CONFIG0.RES0.INSTANCE0.BUTTON;BOOL;BOOL;
6 2;FB;CONFIG0.RES0.INSTANCE0.TON0;CONFIG0.RES0.INSTANCE0.TON0;TON;; 2;OUT;CONFIG0.RES0.INSTANCE0.TIMER_OUT;CONFIG0.RES0.INSTANCE0.TIMER_OUT;BOOL;BOOL;
7 3;VAR;CONFIG0.RES0.INSTANCE0.TON0.EN;CONFIG0.RES0.INSTANCE0.TON0.EN;BOOL;BOOL; 3;VAR;CONFIG0.RES0.INSTANCE0.COUNTER_VALUE;CONFIG0.RES0.INSTANCE0.COUNTER_VALUE;INT;INT;
8 4;VAR;CONFIG0.RES0.INSTANCE0.TON0.ENO;CONFIG0.RES0.INSTANCE0.TON0.ENO;BOOL;BOOL; 4;FB;CONFIG0.RES0.INSTANCE0.PT20;CONFIG0.RES0.INSTANCE0.PT20;PT2;;
9 5;VAR;CONFIG0.RES0.INSTANCE0.TON0.IN;CONFIG0.RES0.INSTANCE0.TON0.IN;BOOL;BOOL; 5;VAR;CONFIG0.RES0.INSTANCE0.PT20.EN;CONFIG0.RES0.INSTANCE0.PT20.EN;BOOL;BOOL;
10 6;VAR;CONFIG0.RES0.INSTANCE0.TON0.PT;CONFIG0.RES0.INSTANCE0.TON0.PT;TIME;TIME; 6;VAR;CONFIG0.RES0.INSTANCE0.PT20.ENO;CONFIG0.RES0.INSTANCE0.PT20.ENO;BOOL;BOOL;
11 7;VAR;CONFIG0.RES0.INSTANCE0.TON0.Q;CONFIG0.RES0.INSTANCE0.TON0.Q;BOOL;BOOL; 7;VAR;CONFIG0.RES0.INSTANCE0.PT20.IN1;CONFIG0.RES0.INSTANCE0.PT20.IN1;BOOL;BOOL;
12 8;VAR;CONFIG0.RES0.INSTANCE0.TON0.ET;CONFIG0.RES0.INSTANCE0.TON0.ET;TIME;TIME; 8;VAR;CONFIG0.RES0.INSTANCE0.PT20.IN3;CONFIG0.RES0.INSTANCE0.PT20.IN3;BOOL;BOOL;
13 9;VAR;CONFIG0.RES0.INSTANCE0.TON0.STATE;CONFIG0.RES0.INSTANCE0.TON0.STATE;SINT;SINT; 9;VAR;CONFIG0.RES0.INSTANCE0.PT20.IN2;CONFIG0.RES0.INSTANCE0.PT20.IN2;BOOL;BOOL;
14 10;VAR;CONFIG0.RES0.INSTANCE0.TON0.PREV_IN;CONFIG0.RES0.INSTANCE0.TON0.PREV_IN;BOOL;BOOL; 10;VAR;CONFIG0.RES0.INSTANCE0.PT20.IN_TIME;CONFIG0.RES0.INSTANCE0.PT20.IN_TIME;TIME;TIME;
15 11;VAR;CONFIG0.RES0.INSTANCE0.TON0.CURRENT_TIME;CONFIG0.RES0.INSTANCE0.TON0.CURRENT_TIME;TIME;TIME; 11;VAR;CONFIG0.RES0.INSTANCE0.PT20.OUT1;CONFIG0.RES0.INSTANCE0.PT20.OUT1;BOOL;BOOL;
16 12;VAR;CONFIG0.RES0.INSTANCE0.TON0.START_TIME;CONFIG0.RES0.INSTANCE0.TON0.START_TIME;TIME;TIME; 12;VAR;CONFIG0.RES0.INSTANCE0.PT20.OUT2;CONFIG0.RES0.INSTANCE0.PT20.OUT2;BOOL;BOOL;
17 13;FB;CONFIG0.RES0.INSTANCE0.TOF0;CONFIG0.RES0.INSTANCE0.TOF0;TOF;; 13;VAR;CONFIG0.RES0.INSTANCE0.PT20.OUT3;CONFIG0.RES0.INSTANCE0.PT20.OUT3;BOOL;BOOL;
18 14;VAR;CONFIG0.RES0.INSTANCE0.TOF0.EN;CONFIG0.RES0.INSTANCE0.TOF0.EN;BOOL;BOOL; 14;VAR;CONFIG0.RES0.INSTANCE0.PT20.ERROR;CONFIG0.RES0.INSTANCE0.PT20.ERROR;BOOL;BOOL;
19 15;VAR;CONFIG0.RES0.INSTANCE0.TOF0.ENO;CONFIG0.RES0.INSTANCE0.TOF0.ENO;BOOL;BOOL; 15;VAR;CONFIG0.RES0.INSTANCE0.PT20.STARTED_TIMER_1;CONFIG0.RES0.INSTANCE0.PT20.STARTED_TIMER_1;BOOL;BOOL;
20 16;VAR;CONFIG0.RES0.INSTANCE0.TOF0.IN;CONFIG0.RES0.INSTANCE0.TOF0.IN;BOOL;BOOL; 16;VAR;CONFIG0.RES0.INSTANCE0.PT20.TIMER_1_INPUT;CONFIG0.RES0.INSTANCE0.PT20.TIMER_1_INPUT;BOOL;BOOL;
21 17;VAR;CONFIG0.RES0.INSTANCE0.TOF0.PT;CONFIG0.RES0.INSTANCE0.TOF0.PT;TIME;TIME; 17;VAR;CONFIG0.RES0.INSTANCE0.PT20.STARTED_TIMER_2;CONFIG0.RES0.INSTANCE0.PT20.STARTED_TIMER_2;BOOL;BOOL;
22 18;VAR;CONFIG0.RES0.INSTANCE0.TOF0.Q;CONFIG0.RES0.INSTANCE0.TOF0.Q;BOOL;BOOL; 18;VAR;CONFIG0.RES0.INSTANCE0.PT20.TIMER_2_INPUT;CONFIG0.RES0.INSTANCE0.PT20.TIMER_2_INPUT;BOOL;BOOL;
23 19;VAR;CONFIG0.RES0.INSTANCE0.TOF0.ET;CONFIG0.RES0.INSTANCE0.TOF0.ET;TIME;TIME; 19;FB;CONFIG0.RES0.INSTANCE0.PT20.TOF1;CONFIG0.RES0.INSTANCE0.PT20.TOF1;TOF;;
24 20;VAR;CONFIG0.RES0.INSTANCE0.TOF0.STATE;CONFIG0.RES0.INSTANCE0.TOF0.STATE;SINT;SINT; 20;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.EN;CONFIG0.RES0.INSTANCE0.PT20.TOF1.EN;BOOL;BOOL;
25 21;VAR;CONFIG0.RES0.INSTANCE0.TOF0.PREV_IN;CONFIG0.RES0.INSTANCE0.TOF0.PREV_IN;BOOL;BOOL; 21;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.ENO;CONFIG0.RES0.INSTANCE0.PT20.TOF1.ENO;BOOL;BOOL;
26 22;VAR;CONFIG0.RES0.INSTANCE0.TOF0.CURRENT_TIME;CONFIG0.RES0.INSTANCE0.TOF0.CURRENT_TIME;TIME;TIME; 22;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.IN;CONFIG0.RES0.INSTANCE0.PT20.TOF1.IN;BOOL;BOOL;
27 23;VAR;CONFIG0.RES0.INSTANCE0.TOF0.START_TIME;CONFIG0.RES0.INSTANCE0.TOF0.START_TIME;TIME;TIME; 23;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.PT;CONFIG0.RES0.INSTANCE0.PT20.TOF1.PT;TIME;TIME;
28 24;FB;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0;MQTT_CONNECT;; 24;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.Q;CONFIG0.RES0.INSTANCE0.PT20.TOF1.Q;BOOL;BOOL;
29 25;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.EN;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.EN;BOOL;BOOL; 25;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.ET;CONFIG0.RES0.INSTANCE0.PT20.TOF1.ET;TIME;TIME;
30 26;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.ENO;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.ENO;BOOL;BOOL; 26;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.STATE;CONFIG0.RES0.INSTANCE0.PT20.TOF1.STATE;SINT;SINT;
31 27;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.CONNECT;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.CONNECT;BOOL;BOOL; 27;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.PREV_IN;CONFIG0.RES0.INSTANCE0.PT20.TOF1.PREV_IN;BOOL;BOOL;
32 28;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.BROKER;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.BROKER;STRING;STRING; 28;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.CURRENT_TIME;CONFIG0.RES0.INSTANCE0.PT20.TOF1.CURRENT_TIME;TIME;TIME;
33 29;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.PORT;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.PORT;UINT;UINT; 29;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF1.START_TIME;CONFIG0.RES0.INSTANCE0.PT20.TOF1.START_TIME;TIME;TIME;
34 30;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.SUCCESS;CONFIG0.RES0.INSTANCE0.MQTT_CONNECT0.SUCCESS;BOOL;BOOL; 30;FB;CONFIG0.RES0.INSTANCE0.PT20.TOF2;CONFIG0.RES0.INSTANCE0.PT20.TOF2;TOF;;
35 31;FB;CONFIG0.RES0.INSTANCE0.MQTT_SEND0;CONFIG0.RES0.INSTANCE0.MQTT_SEND0;MQTT_SEND;; 31;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.EN;CONFIG0.RES0.INSTANCE0.PT20.TOF2.EN;BOOL;BOOL;
36 32;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.EN;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.EN;BOOL;BOOL; 32;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.ENO;CONFIG0.RES0.INSTANCE0.PT20.TOF2.ENO;BOOL;BOOL;
37 33;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.ENO;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.ENO;BOOL;BOOL; 33;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.IN;CONFIG0.RES0.INSTANCE0.PT20.TOF2.IN;BOOL;BOOL;
38 34;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.SEND;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.SEND;BOOL;BOOL; 34;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.PT;CONFIG0.RES0.INSTANCE0.PT20.TOF2.PT;TIME;TIME;
39 35;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.TOPIC;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.TOPIC;STRING;STRING; 35;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.Q;CONFIG0.RES0.INSTANCE0.PT20.TOF2.Q;BOOL;BOOL;
40 36;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.MESSAGE;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.MESSAGE;STRING;STRING; 36;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.ET;CONFIG0.RES0.INSTANCE0.PT20.TOF2.ET;TIME;TIME;
41 37;VAR;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.SUCCESS;CONFIG0.RES0.INSTANCE0.MQTT_SEND0.SUCCESS;BOOL;BOOL; 37;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.STATE;CONFIG0.RES0.INSTANCE0.PT20.TOF2.STATE;SINT;SINT;
42 38;VAR;CONFIG0.RES0.INSTANCE0.MQTT_CONNECTED;CONFIG0.RES0.INSTANCE0.MQTT_CONNECTED;BOOL;BOOL; 38;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.PREV_IN;CONFIG0.RES0.INSTANCE0.PT20.TOF2.PREV_IN;BOOL;BOOL;
43 // Ticktime 39;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.CURRENT_TIME;CONFIG0.RES0.INSTANCE0.PT20.TOF2.CURRENT_TIME;TIME;TIME;
44 40;VAR;CONFIG0.RES0.INSTANCE0.PT20.TOF2.START_TIME;CONFIG0.RES0.INSTANCE0.PT20.TOF2.START_TIME;TIME;TIME;
45 // Ticktime
46 20000000
47
48

142
editor/arduino/src/arduino.cpp Normal file → Executable file
View 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
View 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
View 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
View 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
View 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
View 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
View File

0
editor/arduino/src/hal/controllino_maxi.cpp Normal file → Executable file
View File

8
editor/arduino/src/hal/controllino_maxi.hal Normal file → Executable file
View 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
View File

8
editor/arduino/src/hal/controllino_maxi_automation.hal Normal file → Executable file
View 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
View File

8
editor/arduino/src/hal/controllino_mega.hal Normal file → Executable file
View 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
View File

8
editor/arduino/src/hal/controllino_mini.hal Normal file → Executable file
View 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
View 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
View 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
View 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
View File

12
editor/arduino/src/hal/esp8266.hal Normal file → Executable file
View 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
View File

View 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));
}
}

View 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
View File

0
editor/arduino/src/hal/machine_control.cpp Normal file → Executable file
View File

18
editor/arduino/src/hal/machine_control.hal Normal file → Executable file
View 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
View 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
View 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
View 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
View File

16
editor/arduino/src/hal/mkr.hal Normal file → Executable file
View 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
View File

16
editor/arduino/src/hal/nano_every.hal Normal file → Executable file
View 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
View File

12
editor/arduino/src/hal/p1am.hal Normal file → Executable file
View 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
View File

12
editor/arduino/src/hal/rp2040.hal Normal file → Executable file
View 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
View File

12
editor/arduino/src/hal/rp2040pico.hal Normal file → Executable file
View 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
View 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
View File

10
editor/arduino/src/hal/stm32_f103cb.hal Normal file → Executable file
View 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
View File

10
editor/arduino/src/hal/stm32_f411ce.hal Normal file → Executable file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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