Skip to content

Workflow for avr build#405

Draft
brentfpage wants to merge 3 commits intoespotek-org:masterfrom
brentfpage:workflow_for_avr_build_b
Draft

Workflow for avr build#405
brentfpage wants to merge 3 commits intoespotek-org:masterfrom
brentfpage:workflow_for_avr_build_b

Conversation

@brentfpage
Copy link
Copy Markdown
Contributor

@brentfpage brentfpage commented Jan 30, 2026

(Following up on some of the discussion in #381.)
This PR:

  • adds a workflow (firmware.yml) for the firmware
  • makes edits to continuous.yml:
    • adds a firmware compilation job
    • adds support for the mac build scheme described in the bullet below
  • revises mac.yml so that:
    • when mac.yml is called by continuous.yml, the firmware .hex asset produced by continuous.yml is packaged into the mac desktop interface
    • when mac.yml is called in some other context, the firmware .hex asset produced by the most recent call to continuous.yml is packaged into the desktop interface
  • and similarly for the other platforms' workflows

The versioning is centralized, but not automatic. Namely, the current version of the firmware has to be set in .github/actions/define-firmware-ver-action/action.yml. At compile time, the firmware version defined there gets injected:

  • into AVR_Code/.../src/main.c as the macro FIRMWARE_VERSION_ID, which previously was defined in AVR_Code/.../src/globals.h
  • into the desktop interface as the macro EXPECTED_FIRMWARE_VERSION, which previously was defined in Desktop_Interface/genericusbdriver.h

Also, the inclusion of the version number in the .hex file names has been retained, so they are, e.g., labrafirm_0007_0{1 or 2}.hex. To me, this is worthwhile because then the firmware that's packaged into a given release can be very easily determined.

@brentfpage brentfpage marked this pull request as draft January 30, 2026 08:13
@brentfpage
Copy link
Copy Markdown
Contributor Author

Copying from a previous draft of this PR:


Posted by @mi-hol

@brentfpage I like the approach documented above and would approve it. With the number of changes a real review seems impossible though.

Lets see how other maintainers react.

The is only a minor nit pick

Namely, the current version of the firmware has to be set in a repository-wide variable, AVR_VER

I'd suggest to change name of variable from AVR_VER to AVR_FIRMWARE_VERSION so its purpose is completely self explanatory

@brentfpage brentfpage changed the title Workflow for avr build (ver. b) Workflow for avr build Jan 31, 2026
@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Feb 7, 2026

@brentfpage I triggered re-run of all workflows after merging #404 but they still fail

@brentfpage
Copy link
Copy Markdown
Contributor Author

brentfpage commented Feb 7, 2026

@brentfpage I triggered re-run of all workflows after merging #404 but they still fail

I just added AVR_VER as a repo-wide variable here (harmless and reversible) , which should make the mac build work. The other builds with automated firmware packaging have not been implemented. The firmware version is now defined in .github/actions/define-firmware-ver-action/action.yml

@brentfpage
Copy link
Copy Markdown
Contributor Author

As an aside, the firmware that's currently configured to be packaged is that from the most recent "continuous release" in my fork. This practice will be necessary unless/until this PR is fully merged into the genuine repo and a continuous release is run that generates firmware files.

@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Feb 8, 2026

added AVR_VER as a repo-wide variable here (harmless and reversible) , which should make the mac build work.

Well I re-ran and it still failed :(
Is something preventing you from running these actions in your fork?
Running them would give you the confidence that the changes actually work as expected and is the key to merging them quickly.
I trust in contributors to provide 100% working changes after initial discussions have completed within the team about a proposed approach.


scoperangeenterdialog.cpp:4:131: warning: unused parameter 'delay' [-Wunused-parameter]
    4 | scopeRangeEnterDialog::scopeRangeEnterDialog(QWidget *parent, bool buttonVisible, double yTop, double yBot, double window, double delay) :
      |                                                                                                                                   ^
genericusbdriver.cpp:479:75: error: expected expression
  479 |     qDebug("EXPECTING FIRMWARE VERSION 0x%04hx", EXPECTED_FIRMWARE_VERSION);
      |                                                                           ^
genericusbdriver.cpp:484:45: error: expected expression
  484 |     if((firmver != EXPECTED_FIRMWARE_VERSION) || (variant != DEFINED_EXPECTED_VARIANT)){
      |                                             ^
1 warning generated.
2 errors generated.

The other builds with automated firmware packaging have not been implemented.

Please add these changes, test, change status to "ready for review" and we'll review again after that has happened.

@brentfpage
Copy link
Copy Markdown
Contributor Author

brentfpage commented Feb 8, 2026

Unfortunately I had missed this key point:
"[variables] are not passed to workflows that are triggered by a pull request from a fork"
from the heading of https://github.com/espotek-org/Labrador/settings/variables/actions . So, the workflow won't work in full unless/until the PR is merged. As a stop-gap solution, I simply hard-coded the value of AVR_VER (0x0007) in mac.yml. The mac build now works.
Now obsolete (3/19/2026)

The PR is still a draft (only one workflow has been implemented), so I'll hold off on indicating that it's "Ready for review".

@brentfpage brentfpage marked this pull request as ready for review February 8, 2026 23:25
@brentfpage brentfpage marked this pull request as draft February 8, 2026 23:25
@EspoTek
Copy link
Copy Markdown
Collaborator

EspoTek commented Feb 19, 2026

Just to add some hairiness, the Windows installer currently needs to be manually updated whenever we bump the firmware version.

This is one of the reasons we were sticking with pre-built binaries for everything.

I think it makes sense to have a job for automatically building the firmware, but unless we find a clean solution to the Windows Installer problem I don't think we want to be auto-pulling new builds in.

@brentfpage
Copy link
Copy Markdown
Contributor Author

brentfpage commented Feb 23, 2026

@EspoTek Is it possibly the case that the manually updated installer is downloaded in windows.yml with this line?

Invoke-WebRequest -Uri "http://espotek.com/ai167.msi" -OutFile "ai167.msi"

If so, could you please elaborate on what steps are necessary for generating that .msi file?

@EspoTek
Copy link
Copy Markdown
Collaborator

EspoTek commented Feb 23, 2026

@EspoTek Is it possibly the case that the manually updated installer is downloaded in windows.yml with this line?

Invoke-WebRequest -Uri "http://espotek.com/ai167.msi" -OutFile "ai167.msi"

If so, could you please elaborate on what steps are necessary for generating that .msi file?

That like there is installed a (proprietary) program called "Advanced Installer", that's converts the .aip (Advanced Installer Project) file to the .msi package.

If we ever increment the firmware version, we'll need to either manually add them to the Advanced Installer project or possibly take advantage of some Advanced Installer feature that automatically adds them for us?

@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Feb 23, 2026

we'll need to either manually add them to the Advanced Installer project or possibly take advantage of some Advanced Installer feature that automatically adds them for us?

Updated
@brentfpage @EspoTek I started already some time ago a branch to simplify & standardize the Advanced Installer project.

  • Therefore continuing to improve the currently used approaches seems to be a short-term fix only
  • mid-term I'd prefer to simplify the whole handling of firmware variants and updates.

Reasoning is:

  • major differences in code dealing with USB for unclear (aka undocumented) reasons (at least to me)
  • many "loose ends" due to unmanaged dependencies to old USB library releases

The open questions in this regard are for me:

Does my reasoning make sense?

@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Feb 23, 2026

@EspoTek Is it possibly the case that the manually updated installer is downloaded in windows.yml with this line?

Invoke-WebRequest -Uri "http://espotek.com/ai167.msi" -OutFile "ai167.msi"

If so, could you please elaborate on what steps are necessary for generating that .msi file?

That link there is installed a (proprietary) program called "Advanced Installer", that's converts the .aip (Advanced Installer Project) file to the .msi package.

If we ever increment the firmware version, we'll need to either manually add them to the Advanced Installer project or possibly take advantage of some Advanced Installer feature that automatically adds them for us?

To reduce dependency on the specific server http://espotek.com via insecure http protocol I'm in favour of converting this piece of code to a GH action from marketplace. I'd be happy to own that task.

@EspoTek
Copy link
Copy Markdown
Collaborator

EspoTek commented Feb 24, 2026

  • can the current reasons for needing 2 firmware variants be eliminated?
    Not simply - this is unfortunately a limitation of the ATXMEGA microcontroller we use. Long story short, we require 750kB/s of bandwidth and the ATXMEGA's USB hardware only lets us allocate these in blocks of 8, 16, 32, 64, 128, 256, 512 or 1023 kB/s. On Windows x64, we can get away with 6x 128kB/s endpoints because libusbK knows which endpoint it's communicating with. On other platforms we need to use 1x 1023kB/s endpoint because regular libusb abstracts this away.

It might be possible to switch between the two modes (1x 1023 byte endpoint vs 6x 128 byte) dynamically, this but we'd need to have a whole lot of dynamic code running on the MCU.

  • can the process of firmware flashing be unified for Windows & other OSes?

This is probably more doable - we'd need to build dfu-programmer as a DLL. But honestly, I don't really see a major advantage from this, since the system we have in place already works well.

@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Feb 24, 2026

we'd need to build dfu-programmer as a DLL.

Why the Labrador project?
dfu-programmer has its own lifecycle in a separate project.
This is from my view an example for an "unmanaged dependency"

But honestly, I don't really see a major advantage from this, since the system we have in place already works well.

My experience tells me that at some point in time any code dependency will stop working and suddenly a nightmare surfaces because the skills to maintain it are not there.

From an external view many dependencies have been copied into the project to make it work but that is not a sustainable setup for the long-term unfortunately.

Reducing the amount of code required would be a strategy to survive.

@brentfpage brentfpage force-pushed the workflow_for_avr_build_b branch from 74cf134 to c4eae9f Compare March 19, 2026 01:54
@brentfpage
Copy link
Copy Markdown
Contributor Author

I looked into utilizing the Advanced Installer Github Action for the windows workflow, but unfortunately the Action requires an enterprise license. So, it looks like sticking with the current approach is the way forward. As for

the Windows installer currently needs to be manually updated whenever we bump the firmware version

@EspoTek could this be as straightforward as manually updating the firmware file paths in Labrador.aip ? Currently in this PR, the paths in Labrador.aip have been changed to easily identifiable dummy paths that are replaced with real file paths by windows.yml. This is specifically done using a shell command, but in the future maybe it can instead be done using /UpdateFile. I wasn't able to get /UpdateFile to work for this most recent PR draft but may try again later.
On a related note, should the LABRA~[10 or 11] parts of the FileName entries in the aip be changed when the firmware is updated? In this PR, currently only the 000N part of labrafirm_000N_01.hex gets changed. Lastly, I deleted the labrafirm_000N_02.hex files from the aip, which simplifies the windows workflow and seems likely harmless.

@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Mar 19, 2026

updated:
@EspoTek @brentfpage I'm not convinced AIP to be the best way forward because:

  • correction based on this comment we are already using CMake and version 4.3 introduced new capabilities for package building
  • the currently used AIP version is outdated
  • the license key was lost
  • removal of 32bit version is an open action

that said short-term I'd suggest to just stick with

manually updating the firmware file paths in Labrador.aip

Then address above topics in a next step trying to standardize the package building with CMake

Would this approach make sense?

@turboencabulator
Copy link
Copy Markdown
Contributor

This PR feels like it has scope creep. Can we get a single workflow to build the existing firmware now, then worry about firmware version updates and packaging issues separately in a future PR? I think the latter needs a lot of thought and discussion.

@turboencabulator
Copy link
Copy Markdown
Contributor

we are already using CMake and version 4.3 introduced new capabilities for package building

As far as I'm aware, nothing in this project uses CMake. (And personally I'd like to keep it that way, every project I've seen that uses it is constantly tweaking things to get it right.)

@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Mar 21, 2026

As far as I'm aware, nothing in this project uses CMake.

@turboencabulator oops I confused Labrador with another project. Thanks for making me aware of my error :) l
I'l fix the statements made asap.

…ersion id

- add a workflow for building the firmware.  the workflow calls the define-firmware-ver action and uses the result to set the FIRMWARE_VERSION_ID macro in the compiled firmware
- delete the hard-coded value of FIRMWARE_VERSION_ID in AVR_Code/.../globals.h
- make the firmware compilation Makefile compatible with action-avr-make from Github; also add support for defining FIRMWARE_VERSION_ID
@brentfpage brentfpage force-pushed the workflow_for_avr_build_b branch from 484fc57 to 184f126 Compare March 21, 2026 19:27
@brentfpage
Copy link
Copy Markdown
Contributor Author

Can we get a single workflow to build the existing firmware now, then worry about firmware version updates and packaging issues separately in a future PR?

Good idea – the PR now just includes a new action for defining the firmware version and a new workflow for compiling the firmware. I ran the firmware workflow in my fork, uploaded the resulting variant 02 .hex asset to my board, and confirmed that the board then interfaced properly with the Labrador UI on my mac. I also made sure that the variant 01 .hex differs from the variant 02 .hex (as expected), but I don't have an x64 windows machine so can't confirm that the variant 01 .hex actually works. If someone has such a machine, could you please upload labrador_0007_01.hex from here to your board and test its functionality?

@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Mar 22, 2026

If someone has such a machine, could you please upload labrador_0007_01.hex from here to your board and test its functionality?

will do but will likely need until Wednesday

@EspoTek
Copy link
Copy Markdown
Collaborator

EspoTek commented Mar 22, 2026

I looked into utilizing the Advanced Installer Github Action for the windows workflow, but unfortunately the Action requires an enterprise license. So, it looks like sticking with the current approach is the way forward. As for

the Windows installer currently needs to be manually updated whenever we bump the firmware version

@EspoTek could this be as straightforward as manually updating the firmware file paths in Labrador.aip ? Currently in this PR, the paths in Labrador.aip have been changed to easily identifiable dummy paths that are replaced with real file paths by windows.yml. This is specifically done using a shell command, but in the future maybe it can instead be done using /UpdateFile. I wasn't able to get /UpdateFile to work for this most recent PR draft but may try again later. On a related note, should the LABRA~[10 or 11] parts of the FileName entries in the aip be changed when the firmware is updated? In this PR, currently only the 000N part of labrafirm_000N_01.hex gets changed. Lastly, I deleted the labrafirm_000N_02.hex files from the aip, which simplifies the windows workflow and seems likely harmless.

Updating the .aip directly using sed or whatever the Windows equivalent is seems like a good approach to me. I've looked at it in Cursor and the filenames at least are plain text. I'd probably encode the full filename in the .aip rather than the "N" but that's just me (EDIT: maybe not, haha. Just read the code and it seems sensible as-is!).

Deleting the _02 will cause issues as it's used by the 32-bit build.

@EspoTek
Copy link
Copy Markdown
Collaborator

EspoTek commented Mar 22, 2026

Also I'm happy to ship this is variant 01 works. Looks good!

@brentfpage brentfpage marked this pull request as ready for review March 23, 2026 00:17
@brentfpage
Copy link
Copy Markdown
Contributor Author

One last thing I just did is to add the firmware workflow to continuous.yml. This will be convenient if/when a new PR is opened for packaging the firmware automatically into UI releases. Also, it's generally useful to have firmware versions tied to UI versions, which including the firmware in continuous.yml accomplishes. Maybe it would be even better to include the firmware in the continuous releases but somehow hide the firmware in the releases page, but there's no way to do that as far as I can tell.

@EspoTek
Copy link
Copy Markdown
Collaborator

EspoTek commented Mar 23, 2026

Can't we just not call upload_artifact?

@brentfpage
Copy link
Copy Markdown
Contributor Author

I think the .hex products would then never make it out of the firmware workflow's workspace, which gets deleted when the workflow exits. Even if an asset is uploaded using upload_artifact, it is only available for 90 days. There appears to be an additional upload step in continuous.yml that transfers all the assets (which have already had upload_artifact called on them) to some release directory, where they don't have an expiration date. Given this state of affairs, unless hex assets are included in the repository directly, I think that uploading them to the release directory is necessary.

@EspoTek
Copy link
Copy Markdown
Collaborator

EspoTek commented Mar 23, 2026

Wait, why is this the case? We'll run this script every time we rebuild anyway, right?

@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Mar 23, 2026

x64 windows machine .., could you please upload labrador_0007_01.hex from here to your board and test its functionality?

Tested with Labrador version from commit 8fdaf80
and your firmware file.

no wires connected:

image

but with just wires connect it seems to pick up a lot of noise preventing exact measurement
need to crosscheck with original firmware though
image

disconnecting USB gave:

image
  winUsbDriver destructor ran!
  genericUsbDriver dectructor entering
  genericUsbDriver dectructor completed
  Reinitialising USB driver!
  Making USB Driver invisible!!
  pipeID 0 = 129
  pipeID 1 = 130
  pipeID 2 = 131
  pipeID 3 = 132
  pipeID 4 = 133
  pipeID 5 = 134
  Generic Usb Driver setup complete
  driver =  winUsbDriver(0x213ff398460)
  newGain = 8.000000
  gainMask = c0c
  Not connected.  Ignoring Control Request!!!
  Null handle error in usbSendControl
  numBuffers is not equal to 0, 1 or 2

@EspoTek
Copy link
Copy Markdown
Collaborator

EspoTek commented Mar 23, 2026

@mi-hol does it show any issues when you pump through a "weird" sin wave, such as 791Hz? This will show any issues where the USB driver doesn't recombine the 6 endpoints in the correct order.

@mi-hol
Copy link
Copy Markdown
Contributor

mi-hol commented Mar 23, 2026

does it show any issues when you pump through a "weird" sin wave, such as 791Hz

Sorry, thats beyond my technical abilities.
Maybe with detailed step-by-step instructions and prerequisites I would be able.

@EspoTek
Copy link
Copy Markdown
Collaborator

EspoTek commented Mar 23, 2026

does it show any issues when you pump through a "weird" sin wave, such as 791Hz

Sorry, thats beyond my technical abilities. Maybe with detailed step-by-step instructions and prerequisites I would be able.

When I do it, I'll:

  • Connect Signal Gen CH1 AC to oscilloscope CH1 with a wire (see pinout https://github.com/espotek-org/Labrador/wiki/Pinout)
  • Set the Signal Gen CH1 to a Sin wive at 791Hz and 2V
  • Check to see if there are discontinuities in the waveform (ie, it's not a "smooth" sine - it suddenly jumps up and down randomly)

@brentfpage brentfpage marked this pull request as draft March 24, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants