FPC on Rasp Pi, non Lazarus, use of GPIO. lazarus / 1-Linux ---------------------------------------------------------------------- AlanTheBeast · 2021-02-18 17:02 Hi, I don't need Laz for my Pi project.  But I do need access to the GPIO. How do I go about that?  Are there units I can DL for that?  Current v. is FPC 3.0.4 under 32b Rasp Pi OS. Thanks, Alan. ---------------------------------------------------------------------- ojz0r · 2021-02-18 17:36 Check out the wiki page: https://wiki.freepascal.org/Raspberry_Pi Thats a very good guide for gpio access. ---------------------------------------------------------------------- MarkMLl · 2021-02-18 17:52 In any event the GPIO bits are exposed via a standard API in the /sys tree, and I believe that there's also a newer (and higher performance) way of driving the bits by accessing /dev devices although I've not played with it yet. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-18 18:03 Thanks both MarkMLI and ojzOr - I hope to also be able to easily link assembly code.  But that is next week (waiting for the parts to come (GPS, Accel/gyro)). So, you send me a link that says:   "https://wiki.freepascal.org/Raspberry_Pi" And I end up on the page: "https://wiki.freepascal.org/Lazarus_on_Raspberry_Pi" Argghh ... Oh, well, it's a start!  I'll figure out (I hope) how to strip Laz out of that....  I really only want/need a CLI as the project will be headless in the end... ---------------------------------------------------------------------- ojz0r · 2021-02-18 18:16 Its not hard to strip the Lazarus part out,  if you get stuck t can send you an example based on that guide that im currently running on a RPi Zero W. ---------------------------------------------------------------------- AlanTheBeast · 2021-02-18 18:26 ojzOr - well don't delay, act now!  Thanks.  (Yes, I'm lazy!). Thanks I'll be doing a Pi zero eventually as a remote sensor with a LoRa ... maybe in a month... want to do some airborne experiments too ( carry on a drone ). ---------------------------------------------------------------------- MarkMLl · 2021-02-18 18:28 The RPi is a standard Linux-based computer, albeit a bit smaller than most and with not-quite-standard startup and video arrangement. Lazarus is an IDE that is entirely suitable for non-GUI development: scratch the surface and you'll find that many if not most of the FPC core developers use it to work on the compiler. If you don't want to use Lazarus then use some other editor and makefiles etc., but assume that much of the Lazarus (as distinct from LCL) documentation actually pertains to the underlying compiler. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-18 18:46 @Mark, I'm not familiar with Lazarus. OTOH, I'm quite happy to write Pascal in a basic text editor or lite IDE.  Indeed there's one I found with the Rasp OS distro called Geany that recognizes Pascal and invokes FPC.  I was surprised. The "overhead" of Lazarus, etc., just gets in the way of my project timewise - I don't want to invest much into it when I won't be implementing or using it.  A CLI is all I need to run, test and complete the work. I'm trying to avoid C because I despise C.  I'd rather write in assembler than C (but I don't know the ARM machine that well so another learning process to avoid...).  (I did an Arduino project in "C" (ish) which reminded me how bad it is...) Plain old Pascal is all I need (of the Turbo vein with units)... I'll even jump to Python 3 (spit!) if need be... That said, I'll install Lazarus on the Pi and try the demo at the linked page... you never know... I might succumb... Thanks! ---------------------------------------------------------------------- JuhaManninen · 2021-02-18 19:22 Quote from: AlanTheBeast on February 18, 2021, 07:46:38 pmThe "overhead" of Lazarus, etc., just gets in the way of my project timewise - I don't want to invest much into it when I won't be implementing or using it.  A CLI is all I need to run, test and complete the work. What overhead do you mean? How does it get in the way? In reality it is snappy. It does everything that Geany does + a lot more. Lazarus trunk is speed optimized recently. Especially startup in Unix related systems is faster now. Raspberry Pi users please test. The memory and HW requirements however remain the same because compilation and especially linking hog resources. ---------------------------------------------------------------------- MarkMLl · 2021-02-18 19:34 Quote from: AlanTheBeast on February 18, 2021, 07:46:38 pmThe "overhead" of Lazarus, etc., just gets in the way of my project timewise What overhead? It's a better-than-average text editor (not as good as Multi-Edit on DOS, but nothing is) with the major advantage of a properly-integrated debugger. I'm not sure that "underhead" is a word, but criticising it due to automatically assuming that it introduces an unacceptable amount of cruft is at best underhand :-) MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-18 20:25 I mean overhead in the code, generally.  Also the overhead of learning Lazarus when all I need is access to the GPIO pins. For example "https://wiki.freepascal.org/Lazarus_on_Raspberry_Pi#Switc hing_a_device_via_the_GPIO_port" uses a TForm ...  don't need that ... at all. In essence when someone wants access to the GPIO pins (or other h/w) then the abstraction should be about that w/o showing all the rest. I don't need "objects" to access a pin on a header. etc and so on ---------------------------------------------------------------------- MarkMLl · 2021-02-18 20:52 Lazarus is an IDE. The LCL is GUI stuff. Objects have their uses even if you aren't using GUI-oriented components. The first part of that example manipulates the GPIO bits via- AS I HAVE ALREADY SAID- the /sys tree. The GUI stuff is there entirely as eye-candy. The second part goes via /dev/mem (which is a non-standard RPi- specific interface)... again, the GUI-based stuff is completely irrelevant except that it's easier to drop a couple of buttons onto a form than to implement an interactive text-based demo (I'll leave you to work out how I know). The second part /does/ use a couple of classes to encapsulate functionality, I'm undecided as to whether that's justified without seeing a larger project that demonstrates the author's intent. If you cited an interface which was distributed as a Lazarus package and couldn't easily be unbundled from its visual component then your reservations would be justified. As it is, you are criticising from an uninformed position: AS I HAVE ALREADY SAID the Lazarus IDE is an exceptionally good development environment for character (console) based programs (and I've used- and sold- quite a few in my time). MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-18 21:47 I appreciate the help (and yes I realize that Laz is an IDE). However it seems like all examples around here must pass through the GUI stuff (Forms, etc). Why do I need objpascal?  Do I need objpascal?  (Certainly don't want it). I just want to know the very basic things I need to do to get at that h/w and would be much happier without all the cruft of forms, etc. I don't use object Pascal - so the purpose of (Sender: TOBject) is pretty opaque to me in the example.  Yes, I can figure it out or muddle my way through   I'd rather write (or use) a simple, clear, clean, fast, unit -no objects. So (IMO) when people make examples, they should make the simplest example possible w/o all the wrappers, bells and whistles that are not related to the specifics - to make things clearer. Sorry to vent when people are helping! Thanks! ---------------------------------------------------------------------- MarkMLl · 2021-02-18 22:04 Object Pascal is a somewhat extended variant of Turbo Pascal, which is a somewhat extended variant of J&W Pascal. You don't want me to start going on about the precursors or the politics that resulted in Pascal. Honest. If you don't want or need the OP extensions, then don't use them. Simple as that. If you feel like writing something that is text-menu based or has an internal command line then do so, but don't knock the efforts of people who've gone to the trouble of providing examples (e.g. of how to get at GPIO bits) and have chosen to save themself effort by using form-based GUI stuff as a wrapper. FFS, man, *READ* those examples and you'll see that by and large they show you how to do things like accessing the GPIO bits independent of the GUI wrapper. You asked for an example, somebody gave you one: study it. Now before you tax the community's patience any further, I strongly suggest that you install Lazarus and experiment with using it to develop and debug a couple of simple console-based ** application programs. If you don't like it that's fine, but don't go on to complain that the FP editor or some out-of-tree IDE has poor debugger support (unless, of course, you're prepared to contribute by improving it). ** Text-only. Non-GUI. No forms involved. Runs from the shell. etc. Start off with the canonical "Hello, World!". MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-18 22:58 Hi Mark, Don't assume I'm not reading. I'll be working on the project tomorrow. Cheers, Alan Where do I pay the back taxes? As to the history of Pascal, I do know that had attention been paid to rapidly adding to the initial Wirth version early and not kept ring fenced it would likely be a major language today.  Indeed, Ada could have been built around it as a core instead of merely inspired by it had such attention been paid earlier... ---------------------------------------------------------------------- MarkMLl · 2021-02-19 08:25 Quote from: AlanTheBeast on February 18, 2021, 11:58:19 pmDon't assume I'm not reading. I'll be working on the project tomorrow. :-) QuoteAs to the history of Pascal, I do know that had attention been paid to rapidly adding to the initial Wirth version early and not kept ring fenced it would likely be a major language today.  Indeed, Ada could have been built around it as a core instead of merely inspired by it had such attention been paid earlier... It's deeper than that: Pascal was the result of ALGOL-68 being sabotaged. And my major use for Ada is using it to point out that when the DoD was looking for a language base they didn't seriously consider Lisp, although I've seen other people revisiting it comparatively recently and being impressed https://www.revk.uk/2017/11/ada.html One thing I'd throw in about GPIO etc. is that you probably appreciate that in order to get /really/ high-speed access you'd need to get involved with a kernel module: I don't think there's a way to get a GPIO event to interrupt or signal a userspace program directly. And realistically, writing Linux kernel modules needs C. And of course, Linux is not a real-time OS (RTOS) so makes no promises about latency etc. Over the last few months I've been playing with a CH341 board as discussed at https://hackaday.com/2018/02/21/linux-adds-ch341-gpio/ I found that I had to tweak the module/driver slightly in order to get predictable kernel-generated names, but after that it behaved very much as would be expected on an RPi. I was using GPIO access via /sys, which is the "old" kernel standard, there's also a "new" kernel standard interface via /dev/gpiochip* which I've not yet played with, and the RPi-specific one via /dev/mem which I've /definitely/ not played with https://embeddedbits.org/new-linux-kernel-gpio-user-space- interface/ HTH MarkMLl ---------------------------------------------------------------------- ojz0r · 2021-02-19 09:39 First off I'd like to second that Lazarus is really light weight. However since I'm new to both Pascal and Lazarus I have not got around to do actual coding in Lazarus (its on my todo list). I've written everything in Nano and compiled with "fpc " directly on the RPi and launching with "./". Here are the units i have created to make my life easier. (It probably looks like crap to experienced programmers) You can use it as an example or straight up if you find it sufficient for your needs. Basically my example contains 3 units: - GVL.pas: "Global variable list", i use it in the program/sub-units to access the GPIO globaly with "GVL.GPIO[17]" for example. With this you need to call procedures "GVL.readInputs()" before using the inputs and "GVL.setOutputs()" to set the outputs. When terminating the application you would use the "GVL.unexportGPIO()" to restore the GPIO again. - iolist.pas: This is the I/O-list i use to map the individual GPIO's as input/output. This is the basis for the last module. - IO_GPIO.pas: This is the actual "driver" based on the /sys example in the wiki. This one contains procedures used by GVL.pas. Example how to use: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program main(input, output);{$mode objfpc}{$H+} uses        ..., GVL; begin      repeat                          // Loop        GVL.readInputs();             // Read the inputs defined in iolist.pas         if GVL.GPIO[17] then            // Use GPIO 17        begin              GVL.GPIO[18] := true;   // Set GPIO 18        end;         GVL.setOutputs();               // Set the output state of GPIO's defined in iolist.pas                until not GVL.GPIO[20]          // Escape loop         GVL.unexportGPIO();             // Unexport/free the GPIO from /sys upon program terminationend.  Edit: Spelling mistake. I forgot to mention: my setup is positive voltage to GPIO input = TRUE. Output TRUE = positive voltage on GPIO pin. This can be switched in the IO_GPIO.pas unit. ---------------------------------------------------------------------- MarkMLl · 2021-02-19 11:24 Quote from: ojz0r on February 19, 2021, 10:39:23 amFirst off I'd like to second that Lazarus is really light weight. However since I'm new to both Pascal and Lazarus I have not got around to do actual coding in Lazarus (its on my todo list). I've written everything in Nano and compiled with "fpc " directly on the RPi and launching with "./". Here are the units i have created to make my life easier. (It probably looks like crap to experienced programmers) You can use it as an example or straight up if you find it sufficient for your needs. Remember: you're writing /in/ Pascal, using the Lazarus IDE as a tool. If you want to use GUI facilities you will end up pulling in stuff from the LCL, otherwise you'll be using the FPC runtime library (RTL) and possibly stuff from the non-GUI FPC Class Library (FCL). I mention the distinction between RTL and FCL because of the documentation subtrees at https://www.freepascal.org/docs.html which are obviously distinct from https://lazarus- ccr.sourceforge.io/docs/lcl/ One thing I have to ask about your attachment: why are you importing the Crt unit? I'd also query why you've got those GPIO arrays in the interface unit: if you have to have that then put it in the implementation part and access it via a function (to read) or procedure (to write) so that you've got /some/ semblance of control over what can do what. MarkMLl ---------------------------------------------------------------------- ojz0r · 2021-02-19 11:44 Well the Crt part is a leftover from previous experimenting, i have yet to completely cleaned up all parts of my code. I did not attach all my code, maybe the complete project would give a hint at what i was aiming for putting the array in the interface part. Basically for (again) my use case, i would read the inputs at beginning of a loop and then do logic in between and then set the outputs at the end of the loop, ie i dont use the GPIO inputs in "real time" but an image of the status when entering the loop and writing outputs at the end. So by putting the array in the interface i can use the GPIO[n] freely within the programming without calling a procedure or function to return the instantaneous result. As i'm writing this i see that it comes of as niché, pascal is a hobby to me and my day job is programming industrial control systems (PLC/DCS) so the concept is to resemble that. I merely attached the units to give the OP some example based on the wiki /sys example without the form part. I'm not trying to step on anybodys toes, i know im fresh and not a software engineer, i just want to help. ---------------------------------------------------------------------- MarkMLl · 2021-02-19 12:14 Even if the GPIO array is only temporary, accepted practice would be to have it in one place with published/exported routines for getting and setting pins. You could also have a unit-level property to make it look like you were accessing a variable. That would have the undeniable advantage that you could put a breakpoint on the setter and see exactly what was happening, and any overhead that the compiler didn't optimise out would be miniscule compared with what the kernel was having to do to process your 0/1 character through the standard API, and then put it through a module/driver to access the physical bit. /However/, speaking as somebody else who is industrially-oriented and departing from accepted doctrine, I would not argue that it improved system robustness. Neither FPC nor the underlying OS, and for that matter not the hardware either, implements the sort of segmented architecture which would allow you to say "this physical access routine can only be called by this other part of the code". It is, at a pinch, possible to contrive schemes with access tokens etc. but without physical protection they can always be spoofed. Linux (in fact POSIX) does have a capabilities mechanism which means that control of the GPIO bits can be enabled or disabled on a per- process/program basis, but it doesn't provide any finer (e.g. per- thread) protection than that and once a handle has been granted I don't think it can be revoked. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-19 14:24 @Mark: re: Ada, I read part of the linked article.  One doesn't typically "do Ada" because "want to try using it".  One does Ada because they get hired by an aerospace or defence co. and the Booch is thrown on their desk, "to get familiar" before having some code thrown at them to change.   And here's the company style guide. And here's the flowed down B----g contract paragraph that says: "No recursion and no task rendez-vous".  Here's how you check out code.  Report before you leave for the day. (I actually had the benefit of an in-house class ... [funny moment: as I was coding an exercise the instructor commented: wouldn't it be nice if indenting was all you needed for a code block.  I chuckled.  Did he know about Python?]) re: real time:  I do hope to be able to set up a timer interrupt at 1 KHz, possibly 2 KHz.  That will be essential to sampling my sensors as well as running a Kalman-ish filter at 10 Hz.  Otherwise I'll have to turn the Pi into an embedded system w/o OS.  (I'd prefer that in some ways...) @ojzOr: thanks for the code - that's more my cuppa! EDIT: Forgot to mention, last night installed Laz on the Pi, and made the project from the Wiki, got it to build and run.  All I get is a blank form.  Not sure if I need to set up the hardware to 'drive' that, but should get to it sometime today. Laz is pretty clunky on the Pi (Pi 4 B (4 cores/1.5GHz) with 8 GB of ram). ---------------------------------------------------------------------- MarkMLl · 2021-02-19 14:35 Quote from: AlanTheBeast on February 19, 2021, 03:24:29 pm@Mark: re: Ada, I read part of the linked article.  One doesn't typically "do Ada" because "want to try using it".  One does Ada because they get hired by an aerospace or defence co. and the Booch is thrown on their desk, "to get familiar" before having some code thrown at them to change.   And here's the company style guide. And here's the flowed down B----g contract paragraph that says: "No recursion and no task rendez-vous".  Here's how you check out code.  Report before you leave for the day. You obviously aren't familiar with the author. He's ex-BigCorporate, designs and builds high-throughput Internet devices, and runs an ISP. The sort of ISP where one doesn't need any magic words to get through to somebody who knows what he's doing. https://xkcd.com/806/ https://hackaday.com/2017/12/14/adsl-robustness-verified-by-running- over-wet-string/ Not sure where you're going to be with a high-speed timer interrupt though. That's a very "non-unix" thing to ask... you might be able to do something with a looping thread and either fpSelect() or fpNanoSleep(), but by and large things that require that degree of aggression have specific kernel support. MarkMLl ---------------------------------------------------------------------- ojz0r · 2021-02-19 14:57 Quote from: MarkMLl on February 19, 2021, 01:14:57 pmEven if the GPIO array is only temporary, accepted practice would be to have it in one place with published/exported routines for getting and setting pins. You could also have a unit-level property to make it look like you were accessing a variable. That would have the undeniable advantage that you could put a breakpoint on the setter and see exactly what was happening, and any overhead that the compiler didn't optimise out would be miniscule compared with what the kernel was having to do to process your 0/1 character through the standard API, and then put it through a module/driver to access the physical bit. Sadly I don't have the experience/deep enough knowlage to relate to what you mean. I have an easier time learning by studying examples and trying it out. Do you have some kind of example of this method? Or a wiki page/tutorial link explaining? ---------------------------------------------------------------------- AlanTheBeast · 2021-02-19 15:03 Not impugning the guy, it's just that Ada is not something one does for fun.  It is the anti-C.  It's hard work (to do right) and usually because it is a requirement, not a desire.  That said, he can indeed do it for himself or co. if he seriously wants to build stronger, more reliable code.  But there is a cost to it in time.  I haven't touched it in decades (literally) and the only time my code was in production it was in 8086 assembler in a system that was otherwise almost 100% Ada (early 90's). Also, see my revised comment above ("EDIT"). As to real time, I do need a pretty crisp sampling rate and period.  I assumed that Linux' nous as an embedded system core would support that... ah well, if it comes to it I can go OS-less on the sensor end.  Heck, write in Ada.  (kidding). ---------------------------------------------------------------------- MarkMLl · 2021-02-19 15:15 Quote from: AlanTheBeast on February 19, 2021, 03:24:29 pmre: real time:  I do hope to be able to set up a timer interrupt at 1 KHz, possibly 2 KHz.  That will be essential to sampling my sensors as well as running a Kalman-ish filter at 10 Hz.  Otherwise I'll have to turn the Pi into an embedded system w/o OS.  (I'd prefer that in some ways...) Linux isn't an embedded OS. People try to use it as an embedded OS, just as they try to use Android as an embedded OS (e.g. in 4G USB sticks), but it's not an RTOS and generally speaking (I've not checked the specific GPIO case) it's not easy to hook an interrupt or bitbang. QuoteEDIT: Forgot to mention, last night installed Laz on the Pi, and made the project from the Wiki, got it to build and run.  All I get is a blank form.  Not sure if I need to set up the hardware to 'drive' that, but should get to it sometime today. In that case post your code so that we can take a look at it (having to be careful here since I don't currently have an RPi set up). ALWAYS be ready to post your code when complaining about a non-obvious problem. QuoteLaz is pretty clunky on the Pi (Pi 4 B (4 cores/1.5GHz) with 8 GB of ram). Shouldn't be. Are you using a direct keyboard/video connection or are you doing something like tunneling X11 over SSH? MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-19 15:33 I'll complete the h/w setup before coming back - and I'll open a new thread if it comes to it. I do notice, that although the code runs, during compilation there are crtbegin.o and crtend.o not found errors.  Surprised that it linked... FPC install error? Clunkiness is just v. my Mac (i7 4 HT cores, 3.4 GHz).  And yes I have a mouse/KB on the Pi (the Rasp foundation KB is pretty bad in itself, the mouse is good). And the general clunky feeling of Linux desktops generally. Further, I made the error of buying a 1080 p monitor for the project to save money.  Should have gone 4K. (I'm also VNCing in from the Mac and that is borderline unworkable for scrolling around code...) ---------------------------------------------------------------------- MarkMLl · 2021-02-19 15:58 Ignore the crtbegin/crtend error, it's one of a couple of benign linker errors. Normally VNC performs a bit better than X11-over-SSH, because of the implicit buffering/caching... I've seen a couple of apps behaving /very/ badly with remote X11 due AIUI to input device polling issues. However, that might depend on whether VNC is looking at the system's root window, or is set up to have a dedicated session. In the former case it effectively has to scrape the X11 buffer of the root (GUI console) session, while in the latter case it implements an X11 server for client apps (i.e. Lazarus, the desktop environment etc.) which it then sends over the LAN using its own protocol. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-19 16:20 @ojzOr well your code compiles ... But there was an error in there - a comma instead of a semicolon in GVL.pas in the code you sent w/o further units below. Testing me, eh? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i implementationuses        IO_GPIO,  edit: Then tried your test code (main) which was full of errors, but managed to fix those. Runs (and quits immediately) - I guess because I haven't wired it up yet... not sure why you're testing on GPIO 20, oh, well, I should be able to sort it out from here.... ---------------------------------------------------------------------- ojz0r · 2021-02-19 17:24 Quote from: AlanTheBeast on February 19, 2021, 05:20:25 pm@ojzOr well your code compiles ... But there was an error in there - a comma instead of a semicolon in GVL.pas in the code you sent w/o further units below. Testing me, eh? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i implementationuses        IO_GPIO,  edit: Then tried your test code (main) which was full of errors, but managed to fix those. Runs (and quits immediately) - I guess because I haven't wired it up yet... not sure why you're testing on GPIO 20, oh, well, I should be able to sort it out from here.... Oh yeah the units. I had to delete some other IO_ units, i had SPI "drivers" for some mcp's (adc & dac) also declared in the GVL unit. The code embedded was just a generic example how i use it. You have to declare the pins in the iolist. The pin 20 was just a random number i picked when writing the post. ---------------------------------------------------------------------- AlanTheBeast · 2021-02-19 17:28 QuoteOh yeah the units. I had to delete some other IO_ units, i had SPI "drivers" for some mcp's (adc & dac) also declared in the GVL unit. The code embedded was just a generic example how i use it. You have to declare the pins in the iolist. The pin 20 was just a random number i picked when writing the post. Ok!  If you have SPI code, please don't be shy.  My laziness is boundless! I notice 7 others have downloaded the .zip file you posted ... I guess laziness is fun for everyone! ---------------------------------------------------------------------- AlanTheBeast · 2021-02-19 18:54 First Success.  Using ojz0r (just realized that was a 0) 's code, managed to read an input and turn on a LED when the button was pushed. (Not using Laz, using Geany.  Less fuss). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program testGVL(input, output);(* {mode objfpc}{$H+} *) uses        GVL, IO_GPIO, sysutils;        const         SecPerDay = 86400;        var        i:longword=0;        make:boolean=false;        breaker: boolean = false;        time : TDateTime;        statechange: boolean;         begin        time := now;        repeat                          // Loop        GVL.readInput();               // Read the inputs defined in iolist.pas        StateChange := false;         if (not make) and (GVL.GPIO[17]) then            // Use GPIO 17        begin              GVL.GPIO[22] := false;   // Set GPIO 18                writeln ('up');                make := true;                breaker := false;                statechange := true;        end;        if (not breaker) and (not GVL.GPIO[17]) then        begin                writeln ('down');                GVL.GPIO[22] :=true;                breaker := true;                make := false;                statechange := true;                               end;         if statechange then              begin                        GVL.setOutput();             // Set the output state of GPIO's defined in iolist.pas                      inc(i);                end;        sleep(50);         until ((now - time) * SecPerDay) > 10;    // Escape loop         IO_GPIO.unexportGPIO();             // Unexport/free the GPIO from /sys upon program termination        writeln(i);end. ---------------------------------------------------------------------- ojz0r · 2021-02-19 19:10 Well the SPI part is also based on the wiki example, allthough i could not get it to work at first so i had to do alot of work arounds. The IO_MCPxxxx units are not so generic since i have hard coded the SPI request for each types control registers. Note that (atleast) the RPi Zero only have two chip select pins, be careful not to get that confused or weird stuff can happen. They are defined in the constants part. The chips are MCP3208 (8x 12-bit ADC) and MCP4922 (2x 12-bit DAC). I use the SPI I/O the same way as the GPIO: Read at beginning of cycle and write at the end. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i GVL.readInputs(); GVL.aoCH[0] := GVL.aiCH[0]; GVL.setOutputs();  One weird thing i had when terminating the program was that the analog output would assume a seemingly random value. To remedy that i added a "GVL.aoCH[n] := 0;" (followed by setOutputs procedure) right before the "end." outside the main loop. Again i suspect that the code continues the same newbie mistakes as the last attachment. Quote from: AlanTheBeast on February 19, 2021, 06:28:25 pmI notice 7 others have downloaded the .zip file you posted ... I guess laziness is fun for everyone! Thats probably curiosity. ---------------------------------------------------------------------- AlanTheBeast · 2021-02-19 19:28 Thanks ojz0r! ---------------------------------------------------------------------- MarkMLl · 2021-02-19 20:52 Quote from: MarkMLl on February 19, 2021, 09:25:50 amOver the last few months I've been playing with a CH341 board as discussed at https://hackaday.com/2018/02/21/linux-adds-ch341-gpio/ I found that I had to tweak the module/driver slightly in order to get predictable kernel-generated names, but after that it behaved very much as would be expected on an RPi. I was using GPIO access via /sys, which is the "old" kernel standard, there's also a "new" kernel standard interface via /dev/gpiochip* which I've not yet played with, and the RPi- specific one via /dev/mem which I've /definitely/ not played with https://embeddedbits.org/new-linux-kernel-gpio-user-space-interface/ The "new-style" (kernel 4.8 and newer) API appears to work- at least with a CH341 attached to a PC- without changes to the module/driver. The /dev/gpiochipX device is still root:root, I don't know whether there's a way to hotplug it into e.g. a gpio group to which users could be added. I've not investigated the API yet, but looking at the source of gpiomon suggests that it polls the device rather than using something like FAM to request that it be advised promptly by the kernel when something changes. Frankly I feel it's a bit /meh/... Somewhat later: there's a Java bug from 2015 which relates to the fact that creation of directories in /sys/class/gpiochip* isn't handled reliably by FAM, but that doesn't say anything about whether gpio*/value updates are detected... I suspect not but I might be tempted to investigate further. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-19 21:57 @Mark, I'll be looking at the /dev/gpio_____ methods tomorrow.  Glad for now that I have ojz0r's code compiled and running. Not much for me to do now ... I'm waiting for the GPS and Accel/Gyro to show up. ---------------------------------------------------------------------- MarkMLl · 2021-02-20 09:06 Quote from: AlanTheBeast on February 19, 2021, 10:57:15 pmI'll be looking at the /dev/gpio_____ methods tomorrow.  Glad for now that I have ojz0r's code compiled and running. That might need a Pascal binding to libgpiod and I'm not sure such a thing exists yet. I might have a chance to take a look over the weekend, I've had it pencilled in for a while. The API does have a "wait for change with timeout" function and I'd expect that to be far more responsive than going through /sys/class/gpio. Assuming that your RPi has kernel >= 4.8, what is the user:group ownership of your /dev/gpiochip* ? MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-20 13:47 Quote Assuming that your RPi has kernel >= 4.8, what is the user:group ownership of your /dev/gpiochip* ? Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i pi@raspberrypi:/dev $ uname -r5.10.11-v7l+pi@raspberrypi:/dev $ ls -al | grep gpiocrw-rw----   1 root gpio    254,   0 Feb 17 20:46 gpiochip0crw-rw----   1 root gpio    254,   1 Feb 17 20:46 gpiochip1crw-rw----   1 root gpio    246,   0 Feb 17 20:46 gpiomem ---------------------------------------------------------------------- MarkMLl · 2021-02-20 14:06 Quote from: AlanTheBeast on February 20, 2021, 02:47:08 pmQuote Assuming that your RPi has kernel >= 4.8, what is the user:group ownership of your /dev/gpiochip* ? Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i pi@raspberrypi:/dev $ uname -r5.10.11-v7l+pi@raspberrypi:/dev $ ls -al | grep gpiocrw-rw----   1 root gpio    254,   0 Feb 17 20:46 gpiochip0crw-rw----   1 root gpio    254,   1 Feb 17 20:46 gpiochip1crw-rw----   1 root gpio    246,   0 Feb 17 20:46 gpiomem Thanks for that, I suspected that the RPi people would have taken the trouble to make that (relatively) accessible. Don't try using it yet though, I don't think there's a Pascal binding to libgpiod or a unit for direct access to the kernel: stick to /sys/class/gpio for the moment. My development RPi uses the classic hack of an RPi kernel with standard Debian on top, but over the last few months the WiFi has stopped working for reasons that nobody seems to understand. Time for a "Delete all and insert", but I'll probably stick to Raspbian (or whatever it's called these days) since I don't have a user insisting on having three as desktop systems. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-20 14:16 QuoteI'll probably stick to Raspbian (or whatever it's called these days) They call it "Raspberry Pi OS". https://www.raspberrypi.org/software/ ---------------------------------------------------------------------- AlanTheBeast · 2021-02-20 18:39 QuoteAnd my major use for Ada is using it to point out that when the DoD was looking for a language base they didn't seriously consider Lisp, although I've seen other people revisiting it comparatively recently and being impressed https://www.revk.uk/2017/11/ada.html I just installed Ada on the Pi and tested it out. DL, install, write a program (HellWorld), make ... a few minutes. It used to take our 80186 cross compiler on the VAX 24 hours to compile and link about 5000 lines of code... ... astounding ... ---------------------------------------------------------------------- MarkMLl · 2021-02-20 19:05 Quote from: AlanTheBeast on February 20, 2021, 07:39:04 pmIt used to take our 80186 cross compiler on the VAX 24 hours to compile and link about 5000 lines of code... On the one hand, it's reasonable to assume that an RPi is more powerful- at least for single-user stuff- than a VAX. On the other hand, it's reasonable to assume that some of the paranoid checks that were in late-80s/early-90s Ada might have been omitted. There's certainly a lot of the workbench stuff that has been. The gripping hand is that there's probably also been a lot of changes in compiler technology, so even if the platform and facilities were identical speed might still be substantially improved. But we don't know for certain. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-20 20:13 Two labs began Ada at about the same time.  Each chose a different compiler vendor. Our lab had to meet US military s/w standards for avionics, they had to meet commercial.  (The US military generally uses commercial standards for s/w these days).  We were at similar criticality (about DO-160B level C). Both had to meet divisional standards for s/w (which was a melding of both to a large degree). Yes, the compiler was full compliance and that was a big part of the slowness.  Obviously we would avoid full builds as much as possible. Quoteit's reasonable to assume that an RPi is more powerful- at least for single-user stuff- than a VAX.But yes, a 4 core Pi at 1.5GHz could host many virtual VAX-785's (16 MHz IIRC) and 16 MB of RAM... https://www.linkedin.com/pulse/vaxcluster-raspberry-pi-wilm-boerhout The other lab's compiler seemed much faster though... another: https://www.askwoody.com/2020/ibm-system-370-on-a-raspberry-pi/ ---------------------------------------------------------------------- MarkMLl · 2021-02-20 20:32 Quote from: AlanTheBeast on February 20, 2021, 09:13:37 pmTwo labs began Ada at about the same time.  Each chose a different compiler vendor. Our lab had to meet US military s/w standards for avionics, they had to meet commercial.  (The US military generally uses commercial standards for s/w these days).  We were at similar criticality (about DO-160B level C). Both had to meet divisional standards for s/w (which was a melding of both to a large degree). Yes, the compiler was full compliance and that was a big part of the slowness.  Obviously we would avoid full builds as much as possible. I could tell you were an ex-Ada man. You're one of the minority who knows how to spell it... I seem to remember discussing it with a few people during my GM days in Devon, but I can't remember how many of those converted into sales (most customers went direct to Alsys). I do however recall that we sold a copy of Logitech Modula-2 on a QIC cartridge for a VAX... it's an extreme minority who remembers Logitech as a compiler supplier. QuoteQuoteit's reasonable to assume that an RPi is more powerful- at least for single-user stuff- than a VAX.But yes, a 4 core Pi at 1.5GHz could host many virtual VAX-785's (16 MHz IIRC) and 16 MB of RAM... https://www.linkedin.com/pulse/vaxcluster-raspberry-pi-wilm-boerhout The other lab's compiler seemed much faster though... another: https://www.askwoody.com/2020/ibm-system-370-on-a-raspberry-pi/ Yes. There's stuff in the FPC-distributed variant of Lnet specifically to support the x2741 terminal emulator that I use to talk to a VM/CMS guest system, although that terminal emulator's strength is actually APL. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-20 20:57 Revisiting the empty Tform ..... (see attached screen grab). Main: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i                                                                                                                      program io_test; {$mode objfpc}{$H+} uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Interfaces, // this includes the LCL widgetset  Forms, Unit1  { you can add units after this }; {$R *.res} begin  Application.Initialize;  Application.CreateForm(TForm1, Form1);  Application.Run;end. Unit Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {Demo application for GPIO on Raspberry Pi}{Inspired by the Python input/output demo application by Gareth Halfacree}{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5} {This application reads the status of a push-button} {$mode objfpc}{$H+} interface uses  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,  ButtonPanel, Unix, BaseUnix; type   { TForm1 }   TForm1 = class(TForm)    ApplicationProperties1: TApplicationProperties;    GPIO18CheckBox: TCheckBox;    LogMemo: TMemo;    procedure ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);    procedure FormActivate(Sender: TObject);    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);  private  { private declarations }  public    { public declarations }  end; const  PIN_18: PChar = '18';  IN_DIRECTION: PChar = 'in'; var  Form1: TForm1;  gReturnCode: longint; {stores the result of the IO operation} implementation {$R *.lfm} { TForm1 } procedure TForm1.FormActivate(Sender: TObject);var  fileDesc: integer;begin  { Prepare SoC pin 18 (pin 12 on GPIO port) for access: }  try    fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);    gReturnCode := fpwrite(fileDesc, PIN_18[0], 2);    LogMemo.Lines.Add(IntToStr(gReturnCode));  finally    gReturnCode := fpclose(fileDesc);    LogMemo.Lines.Add(IntToStr(gReturnCode));  end;  { Set SoC pin 18 as input: }  try    fileDesc := fpopen('/sys/class/gpio/gpio18/direction', O_WrOnly);    gReturnCode := fpwrite(fileDesc, IN_DIRECTION[0], 2);    LogMemo.Lines.Add(IntToStr(gReturnCode));  finally    gReturnCode := fpclose(fileDesc);    LogMemo.Lines.Add(IntToStr(gReturnCode));  end;end; procedure TForm1.ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);var  fileDesc: integer;  buttonStatus: string[1] = '1';begin  try    { Open SoC pin 18 (pin 12 on GPIO port) in read-only mode: }    fileDesc := fpopen('/sys/class/gpio/gpio18/value', O_RdOnly);    if fileDesc > 0 then    begin      { Read status of this pin (0: button pressed, 1: button released): }      gReturnCode := fpread(fileDesc, buttonStatus[1], 1);      LogMemo.Lines.Add(IntToStr(gReturnCode) + ': ' + buttonStatus);      LogMemo.SelStart := Length(LogMemo.Lines.Text) - 1;      if buttonStatus = '0' then        GPIO18CheckBox.Checked := true      else        GPIO18CheckBox.Checked := false;    end;  finally    { Close SoC pin 18 (pin 12 on GPIO port) }    gReturnCode := fpclose(fileDesc);    LogMemo.Lines.Add(IntToStr(gReturnCode));    LogMemo.SelStart := Length(LogMemo.Lines.Text) - 1;  end;end; procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);var  fileDesc: integer;begin  { Free SoC pin 18: }  try    fileDesc := fpopen('/sys/class/gpio/unexport', O_WrOnly);    gReturnCode := fpwrite(fileDesc, PIN_18[0], 2);    LogMemo.Lines.Add(IntToStr(gReturnCode));  finally    gReturnCode := fpclose(fileDesc);    LogMemo.Lines.Add(IntToStr(gReturnCode));  end;end; end. ---------------------------------------------------------------------- AlanTheBeast · 2021-02-20 21:30 QuoteI could tell you were an ex-Ada man. You're one of the minority who knows how to spell it... Well, I took a class at work (about 4 days, the instructor brought along a UNIX system with about 10 terminals - UNIX was not known to us much.  We were all assembler / FORTRAN / Pascal types (and most not even Pascal)).  2 people per terminal (teams).  I was paired with a Belgian engineer who though HOL's were an abomination to mankind. But I never wrote a line of production code in Ada - as I mentioned earlier - my contribution was a section in assembler to the system that was 98% in Ada 83.  I had moved to marketing by then and didn't want to waste time learning how to make it work in Ada and I wasn't confident in the timing issues (I was allocated 2ms per 40ms on a machine that had IIRC an 8 MHz clock).  So took the shortcut and banged it out in assembler and shaved weeks off the schedule...  I remember a very experienced and highly respected engineer say "Wow.  This record construct could be really useful!" ( I don't recall her ever doing anything other than assembler before that - HP-2100 ...) A few years ago, I requested here, that FPC be modified to allow undeclared counter/index vars in procedures and functions as in Ada.  People beat the crap out of me - you may have been one of them!  Still seems like a good idea to me! Quote I do however recall that we sold a copy of Logitech Modula-2 on a QIC cartridge for a VAX... it's an extreme minority who remembers Logitech as a compiler supplier. You're right.  Never thought of them at all like that. I did write some Modula-2 (Borland) back OUAT ... I seem to recall it was a university class for an easy A.  (I never went to class so I think I hit a B- on that...).  In those (DOS) days it was pretty tedious IIRC as one had to edit the unit interface file separately from the implementation.  So main, units (interface), units (implementation).  That was a loooong time ago though.  I might have preferred it over Pascal if editing wasn't so tedious.  Then TP 4 came out with Units and - wow! What an improvement. I believe, had Wirth simply extended Pascal with concepts from Modula-2, that Ada could have begun there... I do seem to recall buying stuff from Logitech and getting 'bonus packs' of s/w of all sorts... ---------------------------------------------------------------------- MarkMLl · 2021-02-20 21:33 Quote from: AlanTheBeast on February 20, 2021, 09:57:24 pmRevisiting the empty Tform ..... (see attached screen grab). Please zip or tarball the entire project, since without- in particular- the .lfm it's meaningless. MarkMLl ---------------------------------------------------------------------- MarkMLl · 2021-02-20 21:56 Quote from: AlanTheBeast on February 20, 2021, 10:30:35 pmI remember a very experienced and highly respected programmer say "Wow.  This record construct could be really useful!" ( I don't recall her ever doing anything other than assembler before that - HP-2100 ...) I've seen "systems programmers"- basically glorified operators- boggled by assembler. Until an older colleague pulled a reference card out of her drawer. QuoteA few years ago, I requested here, that FPC be modified to allow undeclared counter/index vars in procedures and functions as in Ada.  People beat the crap out of me - you may have been one of them!  Still seems like a good idea to me! Probably not me. (a) I've only been using the forum for a year, before that I used the mailing lists. (b) While I don't like undeclared variables, I believe that declaring the index variable inside a for..do would be an advance since the current situation where the index value is undefined on loop termination (unless by break) is most unpleasant. QuoteI did write some Modula-2 (Borland) back OUAT ... I seem to recall it was a university class for an easy A.  (I never went to class so I think I hit a B- on that...).  In those (DOS) days it was pretty tedious IIRC as one had to edit the unit interface file separately from the implementation.  So main, units (interface), units (implementation).  That was a loooong time ago though.  I might have preferred it over Pascal if editing wasn't so tedious.  Then TP 4 came out with Units and - wow! What an improvement. Borland Modula-2 became TopSpeed. There were various "goings on" that I can't discuss because if I get the details wrong they'd be libellous. Having separate definition files in M2 has the advantage that (a) they can be marked as read-only to all but senior staff and (b) they can be written as a "statement of fact" with no indication of implementation details... there's a legal storm brewing because C (etc.) specifically doesn't have that separation. QuoteI believe, had Wirth simply extended Pascal with concepts from Modula-2, that Ada could have begun there... Remember that Wirth was on one of the Ada teams or on the approvals committee, and eyebrows were raised since he was the only one being paid. There was a great deal of dodginess that led to Pascal, but basically I believe that Wirth rushed it out with the specific intention of breaking compatibility with ALGOL-60. It was completely unforgivable that Pascal had the "dangling else" problem when that was fixed in ALGOL-68, Wirth obviously fixed that in Modula-2 but Pascal was a rush job... look at Wirth's early coding style and you'd see why. QuoteI do seem to recall buying stuff from Logitech and getting 'bonus packs' of s/w of all sorts... Although the various addon packs sounds more like a TopSpeed thing, and they were of decidedly mixed quality. Logitech had a Mouse Programmer's Toolkit which effectively gave you a large chunk of a Windows-like OS as source, and they had a damn good debugger which was subsequently spun off as Multiscope. They also had their own share of scandals which I can't discuss. For a while I was their de-facto UK tech support. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-20 22:17 QuoteWhile I don't like undeclared variables, I believe that declaring the index variable inside a for..do would be an advance since the current situation where the index value is undefined on loop termination (unless by break) is most unpleasant. I seem to recall that everywhere (from class to code manuals) it was pretty clearly pointed out that the value of the index variable at the end of a for loop was undefined - so don't assume anything.  Further of course, if it compiles on one system with a behaviour it may do something else on another... in particular if the compiler writer is doing an efficient job by using registers for the index... QuotePlease zip or tarball the entire project, since without- in particular- the .lfm it's meaningless.I'll pack everything in a .zip asap - need to separate the project from all sorts of other files first. ---------------------------------------------------------------------- MarkMLl · 2021-02-20 22:31 Quote from: AlanTheBeast on February 20, 2021, 11:17:04 pmQuotePlease zip or tarball the entire project, since without- in particular- the .lfm it's meaningless.I'll pack everything in a .zip asap - need to separate the project from all sorts of other files first. Background: the main unit is the .lpr file. At the bottom of that you can see where the resources in the .lfm file(s) are parsed to create components of various types on the form(s). It's likely that the project you're using has lost a button or something comparable. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-20 22:44 QuotePlease zip or tarball the entire project, since without- in particular- the .lfm it's meaningless. attached Or find at: https://www.dropbox.com/s/ymtk3389e1jtr4g/unit1.pas.tar ---------------------------------------------------------------------- MarkMLl · 2021-02-21 10:38 Rule 1: don't believe everything you read on the Internet, particularly if somebody says "this is a working example" :-) I think your example was derived from https://wiki.freepascal.org/Raspberry_Pi_:_BerryClip but it had been copied around by various people and in the process had lost the contents of its form. That not only meant that there was nothing to display any output but- crucially- it meant that noting was generating events and passing them to the event handlers in your program. I've fixed up your example to the extent that you can single-step through it and see what's going on, I've not attempted to debug it against my own PC-based GPIO since I don't want to change your code more than necessary. What I have done is add several calls to Application.ProcessMessages (colloquially referred to as APM) to make sure that output to the memo on the form appears as early as possible. I've resisted the temptation of starting other methodical fixups since once one starts... Use Lazarus to open the .lpi, compile it and set breakpoints near the start of TForm1.FormActivate() and TForm1.ApplicationProperties1Idle(), then step through line-by line paying particular attention to the result of opening or accessing your /sys/class/gpio pseudo-files. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 12:51 The code I posted is that from https://wiki.freepascal.org/Lazarus_on_Raspberry_Pi - the first two code blocks beginning at: https://wiki.freepascal.org/Lazarus_on_Raspberry_Pi#Switching_a_device _via_the_GPIO_port The rest in the tarball was generated by the compiler. Thanks for the patch.  As soon as the coffee kicks in I'll get to it! ---------------------------------------------------------------------- MarkMLl · 2021-02-21 12:55 Quote from: AlanTheBeast on February 21, 2021, 01:51:51 pmThe code I posted is that from https://wiki.freepascal.org/Lazarus_on_Raspberry_Pi - the first two code blocks beginning at: https://wiki.freepascal.org/Lazarus_on_Raspberry_Pi#Switching_a_device _via_the_GPIO_port Yes, and that didn't include a form so was worthless. Wiki author's fault, not yours. See the link I gave you which is rather more comprehensive. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 13:05 @Mark, I believe you mentioned Devon earlier - England?  Is that where you are now? Closest I got to Devon was Yeovil... ---------------------------------------------------------------------- MarkMLl · 2021-02-21 13:21 Quote from: AlanTheBeast on February 21, 2021, 02:05:01 pm@Mark, I believe you mentioned Devon earlier - England?  Is that where you are now? Closest I got to Devon was Yeovil... Currently in Sussex which is the other side of the country. I mentioned Devon because at one time there was an importer of compilers etc. in a small town there, purveyors of quality development tools and libraries to just about everybody basically but the business wilted (at least in part because it supplied tools from all suppliers impartially, and they started looking for exclusive distributors). MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 13:29 OK - running.  Need to make some wiring changes to test that. WARNING: Rant follows. But, this illustrates exactly what I meant earlier about not wrapping a hardware demo in all the trappings of GUI. Discovery 1.  For this to work, the main program had be .lpi, not .pas.  (How would I have known that from the Wiki page). 2. I have no idea how the form got generated.  From the source code?  From the form file? 3. What happened to the main program? Ah well,  I'll plodge through it ... Thanks. ---------------------------------------------------------------------- MarkMLl · 2021-02-21 13:50 Quote from: AlanTheBeast on February 21, 2021, 02:29:48 pmOK - running.  Need to make some wiring changes to test that. WARNING: Rant follows. But, this illustrates exactly what I meant earlier about not wrapping a hardware demo in all the trappings of GUI. If you don't want the GUI stuff don't use it. As I've already said, there are lots of advantages to using Lazarus for the debugger etc. QuoteDiscovery 1.  For this to work, the main program had be .lpi, not .pas.  (How would I have known that from the Wiki page). No, the main program is the .lpr. The .lpi is the project information file that tells the development environment what units, forms etc. are in the overall scope of the project. Quote2. I have no idea how the form got generated.  From the source code?  From the form file? I answered that a couple of days before you asked. Quote3. What happened to the main program? Ah well,  I'll plodge through it ... Thanks. Stop complaining and fix the bugs. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 14:28 Well.  It works. And it's slow. And it misses button presses. I'll start stripping it down... Thanks. ---------------------------------------------------------------------- MarkMLl · 2021-02-21 14:42 Quote from: AlanTheBeast on February 21, 2021, 03:28:27 pmWell.  It works. And it's slow. And it misses button presses. I'll start stripping it down... My first suspect would be that all the processing is hung off an application idle event. I've not used it but I think that that's supposed to be the lowest priority possible, try putting a timer with a 10mSec repetition on it, or possibly an IdleTimer. I'm currently trying to look at the file alteration monitor stuff to see if that's operational inside /sys/class/gpio but I'm not very optimistic. The new (kernel >=4. API appears to have its own equivalent. Slightly later: I'm pretty sure the FAM stuff doesn't work in that context, so basically pins/bits have to be polled. I note that the driver for the CH341 chip talks about its being possible to put an interrupt on one pin at a time, but I haven't a clue how that translates to the user-accessible API. I've not investigated the speed, but I'd be disappointed if it couldn't handle of the order of 100 events a second... https://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio- speed/ suggests somewhat better. However as I've said before Linux isn't an RTOS, and this is reporting level rather than edge, so unless you're using an interlocked/acknowledged protocol (i.e. a bit like ye olde Centronics interface) you can expect dropped inputs and erratically-timed outputs on occasion. I'll try to put a bit of time into the new GPIO API over the next few days. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 15:11 Is there a description of that API anywhere?  I've searched and come up dry. Ah, you slipped in an edit.  Well, two can play at that! I look forward to your API! It occurs to me that a souped up Arduino could be my "sampler" (easy to program timer interrupts on that), compress the data and ship it to the Pi over serial (of some sort).  I'll look into that possibility too.  Not sure it could manage 1 Khz though.  I did have a main loop on the Arduino running 1300-1400 Hz (16 MHz clock) with all sorts of things going on.  Write tight and good things happen... I could also modify the Arduino to get 20 MHz ... though that's a little more complicated... ---------------------------------------------------------------------- MarkMLl · 2021-02-21 15:32 Quote from: AlanTheBeast on February 21, 2021, 04:11:31 pmIs there a description of that API anywhere?  I've searched and come up dry. gpiod QuoteIt occurs to me that a souped up Arduino could be my "sampler" (easy to program timer interrupts on that), compress the data and ship it to the Pi over serial (of some sort).  I'll look into that possibility too.  Not sure it could manage 1 Khz though.  I did have a main loop on the Arduino running 1300-1400 Hz (16 MHz clock) with all sorts of things going on.  Write tight and good things happen... I could also modify the Arduino to get 20 MHz ... though that's a little more complicated... https://rasp.io/duino/ is a good start, interfaced either serially or using I2C. Otherwise the Teensy is worth looking at, it has a rawhid interface over USB which should be fast *BUT* that would still leave you at the mercy of Linux and the non-deterministic USB protocol. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 15:49 QuoteQuoteQuote from: AlanTheBeast on Today at 04:11:31 pm Is there a description of that API anywhere?  I've searched and come up dry. gpiod https://youtu.be/OmBxVfQTuvI?t=15 ... what a difference a d makes .... Quotehttps://rasp.io/duino/ is a good start, Is too neat!  I'll keep that in mind just in case. ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 19:42 @ojz0r I've made some changes (as I was trying to understand it, these made sense to improve the speed). 1- Eliminated GVL. 2- Classless unit (removed try/finally) 3- Added a control array to speed evaluation This is tested with discrete I/O only. As I get into this I might tighten up more - TBD. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit IO_GPIO; (* Access GPIO on Raspberry PI 40-pin *) interface        procedure readInputs;        procedure setOutputs;        procedure unexportGPIO; var        GPIO: array [0..27] of boolean; implementatio nuses(**************************************************************** *****Uses system units************************************************ *********************)SysUtils,Unix,BaseUnix,Crt, (******************* **************************************************Uses user defined un its******************************************************************* **)iolist; type        Direction = (GPIO_input, GPIO_output,GPIO_NotUsed);var        aGPIO: array [0..27, 0..2] of string;        dGPIO: array [0..27] of Direction; (******************* **************************************************Open GPIO for access *********************************************************************) procedure gpioExport(pin, dir: string);var        fileDesc: integer;      gpioPinDirPath: string;        begin        (* Prepare SoC pin for access *)                fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);                fpwrite(fileDesc, pin[1], Length(pin));                fpclose(fileDesc);        (* Set SoC pin (in/out) direction *)              gpioPinDirPath := '/sys/class/gpio/'+'gpio'+pin+'/direction';              fileDesc := fpopen(gpioPinDirPath, O_WrOnly);              fpwrite(fileDesc, dir[1], Length(dir));                fpclose(file Desc);end; (********************************************************** ***********Read GPIO inputs******************************************* **************************)function input(pin, dir: string): boolean; var        fileDesc: integer;        gpioPinValuePath: string;        state: string = '0';begin        input := false;      gpioPinValuePath := '/sys/class/gpio/'+'gpio'+pin+'/value';        gpioExport(pin, dir);        (* Open SoC pin input read-only mode *)      fileDesc := fpopen(gpioPinValuePath, O_RdOnly);        if fileDesc > 0 then                begin                        (* Read status of input pin, return true if high *)                        fpread(fileDesc, state[1], 1);                        if state = '0' then                                input := false                      else                                input := true;                end;        (* Close SoC pin *)        fpclose(fileDesc);end; (******* **************************************************************Set GPIO output**************************************************************** *****)procedure output(pin, dir, cmd: string);var        fileDesc: integer;        gpioPinValuePath: string;        begin        gpioPinValuePath := '/sys/class/gpio/'+'gpio'+pin+'/value';        gpioExport(pin, dir);        (* Set SoC pin output state *)        fileDesc := fpopen(gpioPinValuePath, O_WrOnly);        fpwrite(fileDesc, cmd[1], 1);        fpclose(fileDesc);end; (********* ************************************************************Close GPIO *********************************************************************) procedure gpioUnexport(pin: string);var        fileDesc: integer; begin        (* Free SoC pin *)        fileDesc := fpopen('/sys/class/gpio/unexport', O_WrOnly);        fpwrite(fileDesc, pin[1], Length(pin));        fpclose(fileDesc);end; (***************** ****************************************************Free (unexport) GPIO pins on program exit********************************************* ************************)procedure unexportGPIO;var        io: integer; begin        for io := 0 to 27 do                if dGPIO[io] in [GPIO_Input..GPIO_Output] then                        gpioUnexport( intToStr(io));end; (************************************************** *******************Read inputs**************************************** *****************************)procedure readInputs;var        io:integer;begin        for io := 0 to 27 do                if dGPIO[io] = GPIO_Input then                                GPIO[io] := input(aGPIO[io][0], aGPIO[io][1]); (* input function, returns boolean input state *)end; (************************************************** *******************Set outputs**************************************** *****************************)procedure setOutputs;var        io: integer;begin        for io := 0 to 27 do                if dGPIO[io] = GPIO_Output then                        begin                              if GPIO[io] then (* Define command *)                                      aGPIO[io][2] := '1'                                else                                        aGPIO[io][2] := '0';                              output(aGPIO[io][0], aGPIO[io][1], aGPIO[io][2]); (* output procedure, write output state *)                        end;end;// ----------------------------------------------------------- -----------Procedure init_GPIO;var        i: integer;begin        for i := 0 to 27 do                begin                        aGPIO[i][0] := intToStr(i); //define pin                        case IOlist.GPIO[i] of                                'output': begin                                                      aGPIO[i][1] := 'out';                                                        aGPIO[i][2] := '0';   // init off state                                                      dGPIO[i] := GPIO_Output;                                                end;                                'input' : begin                                                        aGPIO[i][1] := 'in';                                                      dGPIO[i] := GPIO_Input;                                                end;                           ELSE                                              begin                                                      dGPIO[i] := GPIO_NotUsed;                                              end;                        end{case};                end;        setOutputs;        readInputs;        writeln ('CHG 12');end; begin        writeln ('IO_GPIO Mod version');        init_GP IO;(****************************************************************** ***End unit*********************************************************** **********)end. ---------------------------------------------------------------------- MarkMLl · 2021-02-21 20:05 I'd be cautious about the performance of all of those fpopen() fpclose() syscalls. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 20:16 Can always be restored to the prior. I doubt it will break... I do want to look into opening once per program instance and closing once per program instance - that's just more globals to hold the references. ---------------------------------------------------------------------- MarkMLl · 2021-02-21 20:44 Quote from: AlanTheBeast on February 21, 2021, 09:16:30 pmI do want to look into opening once per program instance and closing once per program instance - that's just more globals to hold the references. That's crying out for a class, with procedures/functions ("methods") to set/reset/read a pin and internal storage of the handle or text file assigned to its value. However, one has to be very careful with all of this stuff since direction and accessibility can change during the lifetime of a program. The test program I'm using to explore this- which was written way before the RPi came out- can cope with that, but I find myself wondering how the monitor functionality of the "new" API copes if the role of a pin it's watching changes. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 21:23 To me a unit is fine for this w/o needing a class.  A unit has a globals section to hold state and handles whether in the interface or implementation and that's fine for this - at least for my hobby purposes.  And that's how ojz0r's unit was.  Fine. Old school.  I know. Generally for h/w applications of the port, I wouldn't expect the direction or configuration of a pin to change during the instance of the program.  If a device were more sophisticated than that, then the programmer would have to up his sophistication to match. Now that I'm grasping how this GPIO interface is implemented in Linux I have to say I'm really not pleased with it - sucks would be a compliment.  I'm less and less sure I can do my project as originally envisioned.  I may need a sensor processor that is sans OS and has a very tight interface to the general system. On that note, if I know the memory mapping (ports?) of the devices, can I end run the /sys/class/gpio ??? or will the memory controller intercept that? ---------------------------------------------------------------------- MarkMLl · 2021-02-21 21:31 Quote from: AlanTheBeast on February 21, 2021, 10:23:03 pmTo me a unit is fine for this w/o needing a class.  A unit has a globals section to hold state and handles whether in the interface or implementation and that's fine for this - at least for my hobby purposes.  And that's how ojz0r's unit was.  Fine. Old school.  I know. I suspect I've been doing this stuff longer than you have, so have even more excuse to be set in my ways. And my school was /definitely/ older than yours. And a pin could usefully be implemented as a class. QuoteGenerally for h/w applications of the port, I wouldn't expect the direction or configuration of a pin to change during the instance of the program.  If a device were more sophisticated than that, then the programmer would have to up his sophistication to match. Irrespective of what you might expect, the direction/sense/accessibility /can/ be changed during execution of a program... and if the GPIO device is connected via something like USB it might even be unplugged (or a second device plugged in). I'm not thinking about it being done by the program itself, but by a user in a different session. QuoteNow that I'm grasping how this GPIO interface is implemented in Linux I have to say I'm really not pleased with it - sucks would be a compliment.  I'm less and less sure I can do my project as originally envisioned.  I may need a sensor processor that is sans OS and has a very tight interface to the general system. The fundamental problem is that Linux isn't an RTOS... add to that that GPIO bits might not be endowed with an adequate number of interrupts. Use an FPGA... you know you want to :-) MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-21 22:31 I'll stick to my liteness on the class issue. For my project the pins will not be changing direction or function at all.  This is a project where the only person using it will be me.  An FPGA could do it if I can acquire the processor cell for free - but I don't have a dev environment for that either... not sure how hard it is to do these days for that matter or what it would take out of my non-infinitely deep budget.  I never did an FPGA.  The engineers were stuck with that.  I seem to recall a lot of hair being pulled out.  But that was a long time ago. A 64 bit Arm or intel SoC mounted on a breakout board and some programming tools would really be all I need.  Don't need no stinkin' OS.  Give me an interrupt controller and a timer and that's all a boy needs for a hot time.  I'd even, yes, I'll say it, lower myself to programming in C .  I'll shop around - there has to be something out there that doesn't need Linux. (32 bit would likely do but nothing is cheaper than brute force when doing one-off projects...) ---------------------------------------------------------------------- DonAlfredo · 2021-02-22 04:39 QuoteDon't need no stinkin' OS.https://ultibo.org/ ---------------------------------------------------------------------- ojz0r · 2021-02-22 07:32 Quote from: AlanTheBeast on February 21, 2021, 08:42:30 pm@ojz0r I've made some changes (as I was trying to understand it, these made sense to improve the speed). 1- Eliminated GVL. 2- Classless unit (removed try/finally) 3- Added a control array to speed evaluation I just settled when i got it working, i dont really need exceptional speed. However your code looks much neater, i will check it out more in detail when i get the chance. Quote from: AlanTheBeast on February 21, 2021, 11:31:17 pmAn FPGA could do it if I can acquire the processor cell for free - but I don't have a dev environment for that either... not sure how hard it is to do these days for that matter or what it would take out of my non- infinitely deep budget.  I never did an FPGA.  The engineers were stuck with that.  I seem to recall a lot of hair being pulled out.  But that was a long time ago. I like the FPGA's more, full control of every aspect of the hardware and no pesky OS to hold you back ---------------------------------------------------------------------- PascalDragon · 2021-02-22 08:02 Quote from: AlanTheBeast on February 21, 2021, 11:31:17 pmA 64 bit Arm or intel SoC mounted on a breakout board and some programming tools would really be all I need.  Don't need no stinkin' OS.  Give me an interrupt controller and a timer and that's all a boy needs for a hot time.  I'd even, yes, I'll say it, lower myself to programming in C .  I'll shop around - there has to be something out there that doesn't need Linux. You could use bare metal AArch64 examples like this (Rpi3) or this (RPi4). In principle these can be ported to FPC, though FPC does not yet have a enabled aarch64-embedded target, though it wouldn't be that difficult to do so. ---------------------------------------------------------------------- MarkMLl · 2021-02-22 08:07 Quote from: AlanTheBeast on February 21, 2021, 11:31:17 pmAn FPGA could do it if I can acquire the processor cell for free - but I don't have a dev environment for that either... not sure how hard it is to do these days for that matter or what it would take out of my non- infinitely deep budget.  I never did an FPGA.  The engineers were stuck with that.  I seem to recall a lot of hair being pulled out.  But that was a long time ago. https://hackaday.io/list/160076-fpga-tutorials https://hackaday.com/2020/01/24/new-part-day-led-driver-is-fpga-dev- board-in-disguise/ MarkMLl ---------------------------------------------------------------------- MarkMLl · 2021-02-22 14:05 Quote from: AlanTheBeast on February 21, 2021, 10:23:03 pmOn that note, if I know the memory mapping (ports?) of the devices, can I end run the /sys/class/gpio ??? or will the memory controller intercept that? There's this sort of thing, which implies that /dev/gpiomem and possibly /dev/mem might be usable. https://raspberrypi.stackexchange.com/questions/99785/what-is-the- correct-way-to-use-dev-gpiomem-with-mmap-to-get-access-to-raspberry That is definitely not something I will be playing with, since it is non-portable (i.e. RPi-specific) and only conceals the performance issue rather than providing a robust solution. I append a compiles-but-untested implementation of static and dynamic interface units for the gpiod library. Use /either/ gpiod.pas /or/ gpiod_dynamic.pas, the API exposed should be identical and should behave as documented for C etc. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-22 14:08 @PascalDragon @DonAlfredo @ojz0r @MarkMLI Thanks all for your inputs and suggestions.  I won't have much time for the project until Friday (well, the book keeper is in my office tomorrow, so maybe I'll drag the project to work while she does real work). QuoteQuoteI've made some changes (as I was trying to understand it, these made sense to improve the speed). 3- Added a control array to speed evaluation I just settled when i got it working, i dont really need exceptional speed. However your code looks much neater, i will check it out more in detail when i get the chance. Not sure about neater - indents didn't paste right and there's more to do in the lower level code - but I have to understand it a bit better first. I confess to code efficiency creeping elegance syndrome.  MarkMLI would call it 'dangerous optimization' I think. QuoteI like the FPGA's more, full control of every aspect of the hardware and no pesky OS to hold you back  Esp. the /OS part! ---------------------------------------------------------------------- AlanTheBeast · 2021-02-22 14:14 QuoteThere's this sort of thing, which implies that /dev/gpiomem and possibly /dev/mem might be usable. https://raspberrypi.stackexchange.com/questions/99785/what-is-the- correct-way-to-use-dev-gpiomem-with-mmap-to-get-access-to-raspberry Nice!  Funny that the question is "what is the correct way" and yet the solution is most likely the least correct way!  (I haven't looked yet...).  That's great for me! Quote That is definitely not something I will be playing with, since it is non-portable (i.e. RPi-specific) and only conceals the performance issue rather than providing a robust solution. If it's robust to my solution, that's all I need.  I'll put it up (if I go that way) with specificity warnings. QuoteI append a compiles-but-untested implementation of static and dynamic interface units for the gpiod library. Use /either/ gpiod.pas /or/ gpiod_dynamic.pas, the API exposed should be identical and should behave as documented for C etc. Thanks.  Not sure I can get to it before Friday.  Maybe tomorrow morning. ---------------------------------------------------------------------- MarkMLl · 2021-02-22 15:34 Quote from: AlanTheBeast on February 22, 2021, 03:14:58 pmNice!  Funny that the question is "what is the correct way" and yet the solution is most likely the least correct way!  (I haven't looked yet...).  That's great for me! Well, it can be semantically valid to ask the correct way to operate something even if the result of operating it is abhorrent. At the risk of being inflammatory, "what is the correct way to operate the napalm dispenser if the enemy fires on the field hospital?". :-/ I anticipate that the gpiod API will operate substantially faster than the /sys/class/gpio one, but relying on "good enough" thoughput is no alternative to a properly designed physical interface. Here's a minimal gpiod example, it checks the basic calling conventions but doesn't go much further than that: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i (* A numbered list of ports is prepared at startup, or any time this is called  and no port is open. The list is returned as a StringList, which should be  freed by the caller. Entries in the StringList comprise a GpioChip name,  optionally followed by a space and a device name in parentheses.*)FUNCTION ListGpioChardevPorts(currentPort: THandle= InvalidGpioHandle): TStringList; var  searchRec: TSearchRec;  gpiochip, gpioname, gpiolabel: string;  pChip: pgpiod_chip; begin  if currentPort <> InvalidGpioHandle then    exit(nil);  if not DirectoryExists('/dev') then    exit(nil);  result := TStringList.Create;  try    result.Sorted := true;    result.Duplicates := dupIgnore;    IF FindFirst('/dev/gpiochip*', faAnyFile, searchRec) = 0 THEN      REPEAT        gpiochip := '/dev/' + searchRec.Name;//        if not Gpiod.gpiod_is_gpiochip_device(PChar(gpiochip)) then//          continue;        pChip := Gpiod.gpiod_chip_open(PChar(gpiochip));      if pChip = nil then          continue;        try          gpioname := StrPas(Gpiod.gpiod_chip_name(pChip)); (* Same as searchRec.Name? *)          gpiolabel := StrPas(Gpiod.gpiod_chip_label(pChip));        gpiochip := searchrec.name;          if gpioLabel <> '' then          gpiochip += ' (' { + 'gpiod, ' } + gpioLabel + ')';          result.Add(gpiochip)        finally          Gpiod.gpiod_chip_close(pChip)        end      UNTIL FindNext(searchRec) <> 0;    FindClose(searchRec)  finally    if result.Count = 0 then      FreeAndNil(result)  endend { ListGpioChardevPorts } ;  That should work identically for either the gpiod or the gpiod_dynamic unit, the "magic" being that the explicit Gpiod. is required. There looks to be a bit of variability between versions of the library, for example gpiod_is_gpiochip_device() is declared in the header files shipped by the kernel but not in the binary library from Debian (and Raspbian is a Debian derivative). If there's a mismatch of that type the static linkage will fail at build time, while I'd expect the dynamic linkage to throw an exception at runtime. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-22 21:32 Quote from: MarkMLl on February 22, 2021, 04:34:22 pm At the risk of being inflammatory, "what is the correct way to operate the napalm dispenser ..." Operating that correctly would indeed be inflammatory... I'll look into the rest tomorrow or Friday.  Herself believes I have "communal chores" to catch up on... and if she believes it, well... ---------------------------------------------------------------------- MarkMLl · 2021-02-22 22:07 Quote from: AlanTheBeast on February 22, 2021, 10:32:36 pmI'll look into the rest tomorrow or Friday.  Herself believes I have "communal chores" to catch up on... and if she believes it, well... So far I'm happy with the interface units. What I'm not happy about is that there's information in /sys/class/gpio that doesn't have a counterpart in the gpiod API... you'll probably not see it on an RPi but in brief the gpiod API always numbers I/O lines starting at zero while /sys/class/gpio allows you to deduce whether there's inaccessible bits which means that the first accessible bit should have some higher number. The CH341 board I'm using has two possible drivers: i2c-ch431 (eight GPIO lines) and spi-ch431 (two GPIO lines). If I use the /sys/class/gpio interface I can work out the physical correspondence, if I use gpiod I can't... I might possibly be able to force line names in the module/driver but I'm not at all confident. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-22 22:40 Noted. And it looks like housework is good for me as my mind wanders...  While I have to confirm the behaviour, I recalled that the gyro/accel module can be configured to output the data at a desired sampling rate.  It has an OCXO, so the sampling should be reasonably accurate.  Can set rates well in excess of 1 Khz.  Each sample 'frame' would be about 20 bytes or so... I assume that Linux will buffer serial data coming in ???  I can hit it pretty often to 'drain' and process... I have to see how well I can use the GPS to 'frame' the timing of the gyro/accel - but for that I would have liked to use the 1PPS pin - that no longer seems viable.  I was going to set the GPS to 10 Hz frames, but it can be up to 18 (such a messy number hopefully I can set it to 16 Hz). Edit: As part of this, I suppose I can use my fav:  "now" to do rough RT dispatching of tasks and "now" and GPS time to discipline some sort of local to the code soft clock and some sort of task to back fill time on recent accel/gyro frames.  The actuator part of this job will be relatively slow at about 40 - 100 Hz.  I think.  TBD. ---------------------------------------------------------------------- AlanTheBeast · 2021-02-23 00:13 Quote from: DonAlfredo on February 22, 2021, 05:39:10 amQuoteDon't need no stinkin' OS.https://ultibo.org/ Just visited that site and it looks very promising.  Thanks!!!!! Edit: may be a dead group.    Edit: there is life there.  Registration turned out to be manual and I've received e-mail from them... I'll look into it more towards the weekend. ---------------------------------------------------------------------- DonAlfredo · 2021-02-23 04:59 Not dead I guess. Last update 20 days ago : https://github.com/ultibohub/Core Last update 8 days ago : https://github.com/ultibohub/Tools ---------------------------------------------------------------------- MarkMLl · 2021-02-23 06:55 Quote from: AlanTheBeast on February 22, 2021, 11:40:06 pmNoted. And it looks like housework is good for me as my mind wanders...  While I have to confirm the behaviour, I recalled that the gyro/accel module can be configured to output the data at a desired sampling rate.  It has an OCXO, so the sampling should be reasonably accurate.  Can set rates well in excess of 1 Khz.  Each sample 'frame' would be about 20 bytes or so... I assume that Linux will buffer serial data coming in ???  I can hit it pretty often to 'drain' and process... Surely you'll be using I2C or similar for that, not GPIO? QuoteI have to see how well I can use the GPS to 'frame' the timing of the gyro/accel - but for that I would have liked to use the 1PPS pin - that no longer seems viable.  I was going to set the GPS to 10 Hz frames, but it can be up to 18 (such a messy number hopefully I can set it to 16 Hz). Edit: As part of this, I suppose I can use my fav:  "now" to do rough RT dispatching of tasks and "now" and GPS time to discipline some sort of local to the code soft clock and some sort of task to back fill time on recent accel/gyro frames.  The actuator part of this job will be relatively slow at about 40 - 100 Hz.  I think.  TBD. PPS will /definitely/ need to trigger an interrupt, even on something like a Teensy: polling isn't sufficiently accurate. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-23 12:35 @MarkMLI, Yes, I2C or the UART which are on the GPIO header.  Waiting on hardware from the US.  Seems to be trapped in NJ for some reason - maybe Canadian Customs has to be placated first. TBD. PPS trailing edge interrupt would be fantastic.  Not sure if I can do this in Linux.  Possibly if I go the Ultibo route that DonAlfredo pointed out. It's not clear to me yet that I actually need PPS.  But for sure that would be the most accurate time check possible if not for the app then for testing.  I may buy a USB sillyscope to check timing between my code and the GPS PPS signal - if the software can 'manage' time well enough, then the PPS won't be needed. ---------------------------------------------------------------------- MarkMLl · 2021-02-23 12:54 Quote from: AlanTheBeast on February 23, 2021, 01:35:32 pmPPS trailing edge interrupt would be fantastic.  Not sure if I can do this in Linux.  Possibly if I go the Ultibo route that DonAlfredo pointed out. I don't think it's safe to assume you can do that without a kernel module, although the gpiod API has a monitor capability... which still might not get you better than 10 mSec resolution. And in any event- again- LINUX IS NOT AN RTOS so you can never rely on its latency. QuoteIt's not clear to me yet that I actually need PPS.  But for sure that would be the most accurate time check possible if not for the app then for testing.  I may buy a USB sillyscope to check timing between my code and the GPS PPS signal - if the software can 'manage' time well enough, then the PPS won't be needed. Remember that you'll find it difficult to get a calibration certificate for GPS, so "the most accurate time check possible" has to be treated cautiously. "The most accurate readily available" perhaps. A Royal Navy ship (possibly a minesweeper) experimentally disconnected its GPS a few years ago, and found that its primary radar stopped working. A certain amount of paranoia is, IMO, justified. Re. DSO: https://forum.lazarus.freepascal.org/index.php/topic,53058.ms g392300.html#msg392300 MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-23 17:40 QuoteQuotePPS trailing edge interrupt would be fantastic.  Not sure if I can do this in Linux.  Possibly if I go the Ultibo route that DonAlfredo pointed out. I don't think it's safe to assume you can do that without a kernel module, although the gpiod API has a monitor capability... which still might not get you better than 10 mSec resolution. And in any event- again- LINUX IS NOT AN RTOS so you can never rely on its latency. No need to repeat ... got it the first time.  I will, post integration, also try DonAlfredo's suggestion... As to resolution, if as I believe, the gyro/accel module samples as described, then the integration of that data can take place in nearish realtime and can be soft aligned.  If they have a serial number or timestamp, even better (but I don't believe so).  IOW counting those frames will provide me a time reference at 1/frame_rate s.  I don't know offhand if there's a checksum, so reasonableness checking might be needed as well. QuoteQuoteIt's not clear to me yet that I actually need PPS.  But for sure that would be the most accurate time check possible if not for the app then for testing.  I may buy a USB sillyscope to check timing between my code and the GPS PPS signal - if the software can 'manage' time well enough, then the PPS won't be needed. Remember that you'll find it difficult to get a calibration certificate for GPS, so "the most accurate time check possible" has to be treated cautiously. "The most accurate readily available" perhaps. The PPS is the calibration.  These things are, even in the cheapest sensors, on the order of 100 ns or better compared to UTC (at the phase centre of the antenna - if you have cable from the antenna to the correlator front end, then account for propagation in the cable at about 2/3 the speed of light).  IAC I don't care about UTC - I do care about the period.  This necessitates an interrupt, obviously. The first GPS I'm buying states about 40ns (IIRC).    1 usec period accuracy would be much more than accurate enough for my project. QuoteA Royal Navy ship (possibly a minesweeper) experimentally disconnected its GPS a few years ago, and found that its primary radar stopped working. A certain amount of paranoia is, IMO, justified. Shipboard systems (of which I have little experience) have been ever more integrated with what I call hodepodge.  (I'm probably being too cynical).  Shipboard radar systems often integrate GPS for a variety of functions from target indicator computations (velocity, course, etc.) but also to aid signal processing (clutter suppression I believe - don't quote me) as well as simple things like actual bearing v. relative bearing indications. I'm surprised the radar system didn't have a fallback mode however.  Such in aviation is simply unacceptable for many systems (DO-178B/C level B or A [Boeing didn't heed that on the Max]) and even lesser level systems typically have some functionality when aiding data is not provided. Quote Re. DSO: https://forum.lazarus.freepascal.org/index.php/topic,53058.ms g392300.html#msg392300 Very interesting.   Not sure why you posted that - if I get a silly scope I'll be running it off of a separate computer with the included s/w. Haven't decided I'll need it yet.  You did remind me of a product I worked on in the late 80s/ early 90's with a TMS320C25 (or C40) however. In the meantime since I appreciate everything you've written over the last while (very much!), I will reward you with a curse: https://www.youtube.com/watch?v=d4EgbgTm0Bg (quaternions - which you may be familiar with... I've found some very nicely done C source code on GitHub that I'll translate to Pascal at some point in the not distant future ...). https://github.com/MartinWeigel/Quaternion/blob/master/Quaternion.c ---------------------------------------------------------------------- MarkMLl · 2021-02-23 18:21 Quote from: AlanTheBeast on February 23, 2021, 06:40:36 pmNo need to repeat ... got it the first time.  I will, post integration, also try DonAlfredo's suggestion... With respect to everybody concerned, I've looked only slightly at Ultibo and so far I don't recall seeing anything about a *guaranteed* interrupt latency. QuoteAs to resolution, if as I believe, the gyro/accel module samples as described, then the integration of that data can take place in nearish realtime and can be soft aligned.  If they have a serial number or timestamp, even better (but I don't believe so).  IOW counting those frames will provide me a time reference at 1/frame_rate s.  I don't know offhand if there's a checksum, so reasonableness checking might be needed as well. Perhaps I should have put latency rather than resolution there: don't expect much better than 10 mSec from Linux. Generally speaking most OSes these days are written to set up hardware transfers of a few Kb and to only have to service a single interrupt on completion. As a reminder that Linux is not an RTOS, it took quite a lot of cleaning up in the 2.5 era to get it good enough to drive MIDI. QuoteThe PPS is the calibration.  These things are, even in the cheapest sensors, on the order of 100 ns or better compared to UTC (at the phase centre of the antenna - if you have cable from the antenna to the correlator front end, then account for propagation in the cable at about 2/3 the speed of light).  IAC I don't care about UTC - I do care about the period.  This necessitates an interrupt, obviously. The first GPS I'm buying states about 40ns (IIRC).    1 usec period accuracy would be much more than accurate enough for my project. You misunderstand. Correct me it I'm wrong, but I don't believe that the DoD give out calibration certificates or guarantees of service level. QuoteI'm surprised the radar system didn't have a fallback mode however.  Such in aviation is simply unacceptable for many systems (DO-178B/C level B or A [Boeing didn't heed that on the Max]) and even lesser level systems typically have some functionality when aiding data is not provided. Fun fact: you might recall that a French plane was lost in the South Atlantic a few years ago, and they recovered the "black box" in the nick of time before its battery ran out. I read the report, and it appeared that the pilots- at least one of whom wasn't exactly the sharpest knife in the rack- had made absolutely no attempt to refer to GPS to deduce their altitude or rate of ascent/descent. And the report- which was of course French- didn't seem to think that was in any way out of the ordinary. QuoteIn the meantime since I appreciate everything you've written over the last while (very much!), I will reward you with a curse: https://www.youtube.com/watch?v=d4EgbgTm0Bg (quaternions - which you may be familiar with... I've found some very nicely done C source code on GitHub that I'll translate to Pascal at some point in the not distant future ...). https://github.com/MartinWeigel/Quaternion/blob/master/Quaternion.c I'm familiar with them from BRL-CAD, where chunks of the UI are pretty much unusable unless you grok them. Meanwhile, I'm still trying to sort out some aspects of the gpiod stuff, and am rebuilding my WPi to help out with that. It's the usual sort of Linux problem: sometimes you need to map from a named device in /dev to a more detailed description in /sys, and that can be tedious. But so far the interface units I posted don't look too bad. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-23 21:04 QuoteWith respect to everybody concerned, I've looked only slightly at Ultibo and so far I don't recall seeing anything about a *guaranteed* interrupt latency. If it's as bare as claimed, and if it allows the programmer to set a timer, and if that timer can trigger an interrupt, that the programmer can set the vector to point at his code, then I would expect sub microsecond latency.  I'd prefer to code this part in assembler but not a killer if it isn't.  (And I'm not familiar with ARM assembly language and don't want to be unless pressed).  Ultibo does support inline assembler.  Paired with that I'd want to know what other interrupts are being serviced, for what reason and if there is a priority scheme.  Can I get the highest priority interrupt?  I won't be in there that long.  Promise! IAC it would appear to have far lower latency risk than Linux, which rumour has it is not an RTOS.  Not sure where I heard that. QuoteYou misunderstand. Correct me it I'm wrong, but I don't believe that the DoD give out calibration certificates or guarantees of service level. You're quite correct.  They don't.  But it's irrelevant. US DOD provide the clocks in orbit and monitor them on a four hour cycle against a ground based truth (the 4 hour policy may have changed over the years).  They are very accurate.  Beyond the signal leaving the satellite, the DOD's interest in the matter ends (other than for its government clients).  So first off we trust the US DOD on this.  (No point here in discussing 'what if's' on this IMO.) Receiver manufacturers derive the 1 PPS (I've forgotten the exact method) in hardware, but it is not difficult to do and it is definitely easy to verify against standards at those labs that have them (depending on the accuracy required)).  It is derived from the signal but the s/w in the receiver has to gate it on once the receiver has sufficient signal from space [number of sats needed depends on the application - a ground station that is accurately surveyed could do with a single satellite, I believe; an aircraft would need 4].  The manufacturers declare in their spec how accurate their 1 PPS signal is for the operating conditions of the spec.  So you trust (and perhaps verify) the accuracy of the device as it is marketed. Just re-reading the spec sheet for the first device coming in: 60 ns, 99% of the time.  (This is marketed as "Professional grade". Not sure but seems to be everything that isn't consumer or automotive.  Certainly can't include commercial aviation.) Further, a pin can be programmed to any rate between 10 MHz down to 4 seconds based on that.  With such I could set up an interrupt at whatever rate convenient to the project... So we trust and perhaps verify. QuoteI read the report, and it appeared that the pilots- at least one of whom wasn't exactly the sharpest knife in the rack- had made absolutely no attempt to refer to GPS to deduce their altitude or rate of ascent/descent. And the report- which was of course French- didn't seem to think that was in any way out of the ordinary. GPS is not a source of altitude info, to begin with, in normal flight operations.  That particular A-340 almost certainly did not have a GPS with VNAV capability (it would be passing PVT to the INS of course).  There is no cockpit indication at all of altitude from GPS other than (possibly) diving into the FMS (to the INS). Finally, IIRC, the crew merely had to cross check left and right sources and that should have been enough to have them at least suspect they were losing altitude quickly .... also IIRC the left side pitot/static system was the culprit (and there was an airworthiness directive open on that model that Air France hadn't gotten around to sorting out yet...) Link to the report - je lis le français tres bien .... QuoteMeanwhile, I'm still trying to sort out some aspects of the gpiod stuff, and am rebuilding my WPi to help out with that. It's the usual sort of Linux problem: sometimes you need to map from a named device in /dev to a more detailed description in /sys, and that can be tedious. But so far the interface units I posted don't look too bad. I'll wait until the weekend to get to that.... ---------------------------------------------------------------------- AlanTheBeast · 2021-02-24 21:47 Very positive reply from the Ultibo team. It is very clear that it will handle a high rate of interrupts (way beyond my needs) and that it is direct to my code (must play nice - haven't read the 'rules' but I assume one must handle it fast and reliably...) Also clear that one can set code to run on a particular core and stick there - though I'm not sure that I'll require that or any particular sensitivity to which core is the running core. So, what I will aim to do is: - Program the GPS Timepulse pin to 1 KHz or higher (perhaps 4 Khz) to signal(v) processing cycles and be the time keeper.   Generate flags for lower rate processes as well.  This 'rate' will be extremely accurate (based on GPS time incl. 1 PPS - I assume the GPS receiver has an internal counter slaved to the 1PPS and hopefully that it re- calibrates v. 1 PPS over runtime...)  IAC that level of accuracy (sub 100ns) is not needed.  usec level accuracy is good enough... one issue is that this signal is 3V.  May need to step that up to 5V. - The Ulbito library provides for queued UART i/o at speeds well in excess of my needs.  There may be a way to electrically sync the accels/gyros to the GPS.  TBD. - I2C from the accel/gyros I bought maxes out at 400 Kb/s.  This should support 1 KHz sampling - depends how many bytes per frame...  The accel/gyro that supports SPI was out of stock. I'll probably begin by reviewing MarkMLI's code and using it with current setup to see how far I can push it. Key parts are still in the Fedex universe somewhere... other parts have trickled in at least. ---------------------------------------------------------------------- MarkMLl · 2021-02-25 10:29 Wrapping this up from my POV, after comparing GPIO handling on a PC and a Raspberry Pi, with particular emphasis on the (new) gpiod API. On an RPi, the on-board GPIO lines are handled by code statically linked into the kernel, so it should be possible to rely on their naming order even in the absence of other "hints". That does not apply to a PC, or to any other target where GPIO support is loaded from a kernel module; in that case the device order will change depending on the order that kernel modules are loaded at boot and/or the order that GPIO devices are plugged in. I can confirm that on an RPi, Raspbian ("Raspberry Pi OS") associates both on-board and USB-connected GPIO ports with group "gpio", while on a PC (Debian) the user will need root privilege to perform most operations. This might be an oversight or might be intentional, since a significant proportion of Linux PCs are operating as servers and there have already been reports of badly-configured hardware and software allowing access to critical system buses and devices. Now to discuss the "hints". The classic GPIO text-based API, which is used by almost all demos so far, puts entries in /sys/class/gpio where the names are related to the bus position. So on an RPi with internal GPIO devices one sees gpiochip0  gpiochip100  gpiochip504 while on an RPi which also has a USB-connected CH341 board (plus kernel module) one sees gpiochip0  gpiochip100  gpiochip496  gpiochip504 In this particular case it is the gpiochip496 device which is USB- connected, but assume that number will "wander" depending on the USB topology. There will also be /dev/gpiochip* devices, but these are numbered sequentially: gpiochip0  gpiochip1  gpiochip2  gpiochip3 If the gpiod package is installed, the gpiodetect command describes these as # gpiodetect gpiochip0 [pinctrl-bcm2835] (54 lines) gpiochip1 [brcmvirt-gpio] (2 lines) gpiochip2 [raspberrypi-exp-gpio] (8 lines) gpiochip3 [i2c-ch341] (8 lines) and this may be cross-referenced with what's in /sys/class/gpio: # cat gpiochip0/label pinctrl-bcm2835 # cat gpiochip100/label brcmvirt-gpio # cat gpiochip504/label raspberrypi-exp-gpio # cat gpiochip496/label i2c-ch341 If multiple CH341 (or similar) cards were plugged in, it would be difficult to distinguish them. However for USB devices I think this is relevant: # ls -ld /sys/class/gpio/gpiochip496/device/gpiochip* drwxrwx--- 3 root gpio 0 Feb 25 09:41 gpiochip496/device/gpiochip3 Hence assuming that the labels associated with on-board GPIO devices are unique, I think it's possible to get sufficient "hints" to work out the disposition of devices that might "wander". The reason that this is important is that the "new" gpiod API opens devices by device name (i.e. /dev/gpiochip3 etc.) and can then extract the label and the number of GPIO lines: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   chipHandle := Gpiod.gpiod_chip_open(PChar('/dev/gpiochip3');  if chipHandle = nil then    exit;  ngpio := Gpiod.gpiod_chip_num_lines(chipHandle);  chipLabel := StrPas(Gpiod.gpiod_chip_label(chipHandle));  What it can't extract however is the base of the group of GPIO lines physically supported by the chip, and knowing that can be important if the lowest GPIO line on a device can vary. As a concrete example, the CH341 can be handled either as an I2C+GPIO device with 8x GPIO lines, or an SPI+GPIO device with only 2x GPIO lines... the *top* two, but despite the physical difference in both cases the GPIO lines are numbered from zero (0..7 or 0..1 respectively). I think that covers most details, I suppose I ought to tack it into the wiki at some point. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-25 12:58 MarkMLI wrote: QuoteWrapping this up from my POV, after comparing GPIO handling on a PC and a Raspberry Pi, with particular emphasis on the (new) gpiod API. By the weekend I may even understand enough of that (just rolled out of bed - haven't had enough coffee yet ... Thanks.  I look forward to trying that out with the package you posted the other day.  Big day at work today, finalizing the 2020 books for tax time.. almost done - then I should have more time for this.  My components are still jammed up in NJ/FedEx.  What I get for choosing the cheapest shipping option "FedEx mail". I did purchase a 4K monitor which allegedly arrives today.  That should make working with Lazarus on the Pi a lot easier than the 1080p screen presently attached. Cheers! ---------------------------------------------------------------------- MarkMLl · 2021-02-25 13:19 Quote from: AlanTheBeast on February 25, 2021, 01:58:05 pmThanks.  I look forward to trying that out with the package you posted the other day. I believe that the stuff I posted the other day is functionally OK. Cosmetically it's a bit of a mess since it's had the minimum TLC necessary to convert the .h to a .inc which my (unpublished) preprocessor can then use to generate static and dynamic .pas wrappers. You might find that there's one or two functions which aren't in the library version that distreaux are currently shipping. This will obviously cause a link error if you're using static linkage, but a runtime error if you're using dynamic... hence e.g. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i // Older versions of libgpiod e.g. as shipped with Debian "Buster" might not// support this entry point.           try            x := Gpiod.gpiod_line_is_active_low(lineHandle)          except            x := false          end  After coming across a number of places where this happened I changed the dynamic loading unit to have this in the two LoadRoutine() functions: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     raise DynamicModuleException.Create(FLastError)  MarkMLl MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-26 13:30 QuoteI believe that the stuff I posted the other day is functionally OK. I guess I missed something along the road.  I'll look for the latest version. ---------------------------------------------------------------------- MarkMLl · 2021-02-26 13:38 Quote from: AlanTheBeast on February 26, 2021, 02:30:37 pmQuoteI believe that the stuff I posted the other day is functionally OK. I guess I missed something along the road.  I'll look for the latest version. Only been posted once. See #73 of this thread. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-27 00:04 Quote Only been posted once. See #73 of this thread. Great - already DL'd - not unpacked yet.  Probably tomorrow.  I have a test target - an old GPS with a serial port. Cheers, Have a great weekend! ---------------------------------------------------------------------- AlanTheBeast · 2021-02-27 15:55 Quote  I have a test target - an old GPS with a serial port. ... which I can't use directly with the Pi because it's 5V, and Pi needs 3V.  So I need to find some level converters first... delays, delays... I'll delve into MarkMLI's GPIO package in the meantime.  Can't get it to link - even though  lgpiod is in the same folder as the project ( or in its subfolder) Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Compile Project, Target: pharosGPS: Exit code 1, Errors: 1, Warnings: 2pharosGPS.lpr(12,0) Warning: "crtbegin.o" not found, this will probably cause a linking failurepharosGPS.lpr(12,0) Warning: "crtend.o" not found, this will probably cause a linking failure/usr/bin/ld.bfd: cannot find -lgpiodpharosGPS.lpr(12,0) Error: Error while linking ---------------------------------------------------------------------- MarkMLl · 2021-02-27 17:06 Have you installed the gpiod development package? My Lazarus "Other unit files" setting included gpiod (i.e. as a subdirectory of the project directory and that contained ./gui_test.lpi ./gpiod ... ./gpiod/gpiod.pas ./gpiod/gpiodDefs.inc ./gpiod/gpiod_dynamic.pas ./gpiod/headers ./gpiod/headers/gpiod.h ./gpiod/headers/gpiod.pp- ./gpiod/headers/gpiod-original.h ./gpiod/gpiod-macros.inc ./gpiod/Makefile ./gpiod/WHENCE ./gpiod/dynamicmodule.pas ./gpiod/dynamicmodule.pas~ ... ./pollgpiochardev.pas ./gpiochardevhardware.pas Assume that some of that is cruft that you won't have, I'm showing it "warts and all". Otherwise you might do better using the dynamic unit to start with, but note the two changed statements I mentioned a couple of days ago. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-27 17:33 Sounds right.  Wasn't clear I had to "install" anything -  I thought the package (so to speak) would just be a complete thing - soup to nuts. Yes - folder is there.  I had moved some of those files into the same folder as where my main program (project) file is located. I know absolutely nothing about programming in this environment. Lazarus, I know absolutely nothing about the LCL. I'm not proficient in object programming I'll plow on,,, (I also have to re-install Lazarus ... alas I re-installed the OS because of something I munged up in Linux land..., at least I had backed up all the other stuff done to date). ---------------------------------------------------------------------- MarkMLl · 2021-02-27 18:08 Quote from: AlanTheBeast on February 27, 2021, 06:33:26 pmSounds right.  Wasn't clear I had to "install" anything -  I thought the package (so to speak) would just be a complete thing - soup to nuts. You've got a Raspberry Pi. Running Raspbian or whatever they call it these days. I suggest you familiarise yourself with its SOP, and the significance of lines like this which describe Raspbian (nee Debian) packages: gpiod - Tools for interacting with Linux GPIO character device - binary libgpiod-dev - C library for interacting with Linux GPIO device - static libraries and headers The basic gpiod package will include a dynamically-linkable library, to which gpiod_dynamic.pas should interface. The libgpiod-dev package will include a statically-linkable library, to which gpiod.pas should interface. Absolutely nothing to do with Lazarus. this is RPi stuff. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-27 18:56 Quotegpiod - Tools for interacting with Linux GPIO character device - binary libgpiod-dev - C library for interacting with Linux GPIO device - static libraries and headers The basic gpiod package will include a dynamically-linkable library, to which gpiod_dynamic.pas should interface. The libgpiod-dev package will include a statically-linkable library, to which gpiod.pas should interface. Absolutely nothing to do with Lazarus. this is RPi stuff. Thanks - I confused that error with the names of the folder you had in your package (gpiod) containing gpiod.pas ...;; OTOH: Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i pi@raspberrypi:~/Documents/PharosGPS $ sudo apt-get install gpiodReading package lists... DoneBuilding dependency tree       Reading state information... Donegpiod is already the newest version (1.2-3+rpi1).0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. pi@raspberrypi:~/Documents/PharosGPS $ sudo apt-get install lgpiod-devReading package lists... DoneBuilding dependency tree       Reading state information... DoneE: Unable to locate package lgpiod- dev   yet: ( line 5 of below): Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Compile Project, Target: pharosGPS: Exit code 1, Errors: 1, Warnings: 2pharosGPS.pas(13,60) Warning: "crtbegin.o" not found, this will probably cause a linking failurepharosGPS.pas(13,60) Warning: "crtend.o" not found, this will probably cause a linking failure/usr/bin/ld.bfd: warning: /home/pi/Documents/PharosGPS/link.res contains output sections; did you forget -T?/usr/bin/ld.bfd: cannot find -lgpiodpharosGPS.pas(13,60) Error: Error while linking ---------------------------------------------------------------------- MarkMLl · 2021-02-27 19:16 have you installed the libgpiod-dev package? Are you using gpiod.pas or gpiod_dynamic.pas? I had this stuff running painlessly on a newly-configured RPi a couple of days ago, so I know it works. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-27 19:34 What a difference a few chars make ... libgpiod-dev  , not lgpiod-dev  So, it compiles (with the crt begin/end errors), runs (I have it write a random number to a file). So, on to some blinking lights. Thanks!!! ---------------------------------------------------------------------- AlanTheBeast · 2021-02-28 14:59 @MarkMLI: In a post further up (#76), you posted what I assume is a demo function to list all of the ports.  I tried to use this but it won't compile using your units: Example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i FUNCTION ListGpioChardevPorts(currentPort: THandle= InvalidGpioHandle): TStringList; Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i pharosGPS.pas(14,53) Error: Identifier not found "InvalidGpioHandle" "InvalidGpioHandle"is not defined anywhere in your package that I can find. The compiler threw other errors with that function, as well Searched for it and it's only in my testcode: Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i pi@raspberrypi:~/Documents/PharosGPS $ grep -rnw  -e 'InvalidGpioHandle'backup/pharosGPS.pas:14:FUNCTION ListGpioChardevPorts(currentPort: THandle= InvalidGpioHandle): TStringList;backup/pharosGPS.pas:22:  if currentPort <> InvalidGpioHandle thenpharosGPS.pas:14:FUNCTION ListGpioChardevPorts(currentPort: THandle= InvalidGpioHandle): TStringList;pharosGPS.pas:22:  if currentPort <> InvalidGpioHandle thenpi@raspberrypi:~/Documents/PharosGPS $ The problem with me is, as stated, everything LCL, object programming is in between me (simple programmer) and the hardware. Your package is so abstract to me that I can't make heads or tails of where the code meets the hardware,   Your objective is good, but the implementation might as well be Chinese to me, Could you post as _few lines_ as possible of CLI code that, using your units, will do, and only do: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Alanisasimpledumbass;USES    crt,  //if need be    gpiod,    gpiod_dynamic,    Dynamicmodule,    SysUtils ,    Classes //,    ;    type           //var          i: integer; // set GPIO pin 17 to output mode.         <  >         for i := 1 to 10 do             begin// turn the pin on                   < >                  sleep(100);//turn the pin off.                   < >                  sleep(100);             end;//- return the pin to the system (equivalent to Unexport).          <  >//- other'           < >  end.  With a working version of that, I'll be able to trace the code down to understand how it works. Thanks, ---------------------------------------------------------------------- MarkMLl · 2021-02-28 17:42 Assume InvalidGpioHandle is -1. That wasn't so much working demo code as an illustration of how to call the entry points, noting IN PARTICULAR that the leading "Gpiod." is REQUIRED for both the static and dynamic variants. Apart from that, the function of the various entry points is as described in the documentation for the gpiod library. I suggest familiarising yourself with that and with their examples: my units are a /very/ thin wrapper around that with no attempt to convert their API into something object-based. Looking briefly at your code, use EITHER the gpiod unit, OR the gpiod_dynamic unit, not both since that has your program trying to use two different library interfaces for the same functionality. I would suggest using gpiod_dynamic, since (a) that doesn't need the -dev package and (b) I've already pointed out that some of the documented gpiod functionality (i.e. from the POV of the kernel developers) isn't actually in the library version shipped by Debian so might or might not be in the one shipped by Raspbian, and if you use dynamic linkage you'll get a run-time exception which you can work around. I've not got code that you can easily drop into a project and run, but below are two snippets that you can use to see the sequence I've used... apart from that you're going to have to read the documentation. Assume that e indicates whether a line is enabled, x whether it needs to be inverted (xor operation) and v its value. You don't want to see the GUI stuff. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i         e := true;        v := 0;        lineHandle := Gpiod.gpiod_chip_get_line(chipHandle, i);        if lineHandle = nil then          e := false;        if e and Gpiod.gpiod_line_is_used(lineHandle) then          e := false;        if e and (Gpiod.gpiod_line_direction(linehandle) <> GPIOD_LINE_DIRECTION_INPUT) then          e := false;        if e and (Gpiod.gpiod_line_request_input(lineHandle, Pchar('GuiTest')) <> 0) then          e := false;        if e then // Older versions of libgpiod e.g. as shipped with Debian "Buster" might not// support this entry point.           try            x := Gpiod.gpiod_line_is_active_low(lineHandle)          except            x := false          end        else          x := false;        if e then begin                 (* Accessible and input                 *)          v := Gpiod.gpiod_line_get_value(lineHandle); // Bit from GPIO          if not (v in [0, 1]) then            continue;          v := v xor Ord(x);          linesForDisplay.Append(Format('d%d:%d', [i - lowest, v])); // Bit to GUI          Gpiod.gpiod_line_release(lineHandle)        end      end; ...         e := true;        v := Ord(guiTestForm.DigitalOutValue[i - lowest]); // Bit from GUI        lineHandle := Gpiod.gpiod_chip_get_line(chipHandle, i);        if lineHandle = nil then          e := false;        if e and Gpiod.gpiod_line_is_used(lineHandle) then          e := false;        if e and (Gpiod.gpiod_line_direction(linehandle) <> GPIOD_LINE_DIRECTION_OUTPUT) then          e := false;        if e and (Gpiod.gpiod_line_request_output(lineHandle, Pchar('GuiTest'), 0) <> 0) then          e := false;        if e then // Older versions of libgpiod e.g. as shipped with Debian "Buster" might not// support this entry point.           try            x := Gpiod.gpiod_line_is_active_low(lineHandle)          except            x := false          end        else          x := false;        if e then begin                 (* Accessible and output                *)          if Gpiod.gpiod_line_set_value(lineHandle, Ord((v <> 0) xor x)) = 0 then // Bit to GPIO            linesForDisplay.Append(Format('d%d:%d', [i - lowest, Ord((v <> 0) xor x)])); // Bit to GUI          Gpiod.gpiod_line_release(lineHandle)      end  I've not investigated using that API to set directions. What I've done so far is set them using the sysfs API, then unexport the line to make it unused hence available to the dev interface. As I've already written up, there's a gpiod program to show you chip/line status. I've been working hard outdoors all day, and now have to do paperwork. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-02-28 23:01 Minor progress... (between errands etc.). Can't seem to get a valid line handle. (probably because the chip handle is not valid?) Many variations on path used:    /dev/gpiochip0 (and 1, and via /sys/class, etc and so on... Compiles, runs, crashes on attempting to a) testing the path (commented out below) and b)   lineHandle := gpiod.gpiod_chip_get_line(chipHandle, i);  because presumably the returned chip handle is not valid because the path is wrong? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program pharosGPS;//{$mode objfpc}{$H+}USES    crt,//    gpiod,    gpiod_dynamic,    Dynamicmodule,SysUtils,    Classes     ;Const GPIOPath : Pchar = '/dev/gpiochip0/';       // tried via  /sys/class/gpio/... also var  e: boolean;  v: integer;  x: boolean;  i: word = 22;  lineHandle: Pgpiod_line;  chiphandle: Pgpiod_chip; begin     writeln ('START: ',GPIOPath);  e := true;  v := 0;  //writeln(gpiod.gpiod_is_gpiochip_device(GPIOPath));   //    <- this crashes too   chiphandle := gpiod.gpiod_chip_open (GPIOPath);   writeln ('LH');  lineHandle := gpiod.gpiod_chip_get_line(chipHandle, i);     //crashes here ---------------------------------------------------------------------- MarkMLl · 2021-03-01 00:14 Go back and look at my example. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i         pChip := Gpiod.gpiod_chip_open(PChar(gpiochip));        if pChip = nil then...  MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-03-01 14:42 Without changing my code, but changing the path again, it finally worked.  Some typo before? (rhetoric) Anyway, path       Const        GPIOPath : Pchar = '/dev/gpiochip0'; works       GPIOPath : Pchar = '/sys/class/gpio/gpiochip0';    does not work, returns a nil for the chiphandle. Onward ... Thanks. ---------------------------------------------------------------------- MarkMLl · 2021-03-01 18:28 Quote from: AlanTheBeast on March 01, 2021, 03:42:50 pm      GPIOPath : Pchar = '/sys/class/gpio/gpiochip0';    does not work, returns a nil for the chiphandle. Of course it doesn't work! Have you taken the trouble to read my #89, and in particular did you read the bit that referred to the gpiodetect command and gave you an example of its output? Did you look at the gpiodetect manpage, and in particular the "see also" section that pointed you at the various utility commands... the source for which you can read if you're in any doubt about the documented API? The two set of names- those in sysfs and those in /dev- are for DIFFERENT APIS, and you can't just mix-and-match at random and expect things to work. Except obviously where you have to, for reasons that I did my best to explain, and even then you're effectively running them in parallel rather than chucking them into a communal pot. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-03-01 21:31 I had tried both paths without success.  (And for the avoidance of doubt, in case it matters, I did remove the gpiod unit). And had compiled, running (crash or not) code with the correct one.  Something else was amiss.  So I try things to see what happens. pi@raspberrypi:~/Documents/PharosGPS $ gpiodetect gpiochip0 [pinctrl-bcm2711] (58 lines) gpiochip1 [raspberrypi-exp-gpio] (8 lines) Doesn't really clarify where they are, now does it? (other than that there is -h and -v ... no other commands). Further the following call does not work (crashes) with a valid path in it:            t := gpiod.gpiod_is_gpiochip_device(PChar('/dev/gpiochip0')); Which sends one down other rabbit holes... Now trying to figure out serial data (UART).  That is truly opaque in this well documented program. Esp. as I don't have a reliable source of UART input that I know for sure is outputting data to the pin... Perhaps a loop back from terminal ... tbd. I get you're frustrated.  To me, all of this is abstracted to the point of incomprehensibility and densely worded documentation doesn't show clearly.  Also: I'm not a Linux guy.  At all.  I don't use API's much.  At all.   When I had hardware to interface to, I always did it at the lowest level possible.  Not portable.  That was never the intention.  Nor is it with the current project. Cheers, Big boom from Hermann in your old home town the other day ... ---------------------------------------------------------------------- MarkMLl · 2021-03-02 07:25 Quote from: AlanTheBeast on March 01, 2021, 10:31:20 pmpi@raspberrypi:~/Documents/PharosGPS $ gpiodetect gpiochip0 [pinctrl-bcm2711] (58 lines) gpiochip1 [raspberrypi-exp-gpio] (8 lines) Doesn't really clarify where they are, now does it? (other than that there is -h and -v ... no other commands). As I said, that is a problem. Refer to your hardware documentation to find out which are which. QuoteFurther the following call does not work (crashes) with a valid path in it:            t := gpiod.gpiod_is_gpiochip_device(PChar('/dev/gpiochip0')); I ALREADY TOLD YOU THAT ONE WASN'T IMPLEMENTED!!!!! Message #76, and being able to cope with that sort of thing is one of the big advantages of dynamic linkage. QuoteNow trying to figure out serial data (UART).  That is truly opaque in this well documented program. Esp. as I don't have a reliable source of UART input that I know for sure is outputting data to the pin... Not my problem until you start looking at the serial.pp unit. In a separate topic. MarkMLl ---------------------------------------------------------------------- AlanTheBeast · 2021-03-02 13:08 Sorry Mark, The mind wanders - didn't realize I repeated that. I'll be looking more at the UART later this week.  Full work days ahead, alas.