 I'm Braden Lane. Well, technically, I'm actually an animated avatar. But I'm giving today's talk on the Portaprog, a portable ISP and UDPI programmer for both development and production. Let's get into it. In January of 2019, I actually hadn't done any electronics. Not any circuit design, not any schematics. I knew what a resistor was from high school, but that was about the extent of it. And I had this idea for a toy, a little robot I called the Screamsy. The toy kids love and parents hate. And why I tagged it that, if you can imagine for a moment, a little robot toy that responds to sound. The volume of the sound controls the robot's speed. The pitch of the sound controls the robot's direction. Now give this toy to a seven-year-old. The Screamsy is an ESP8266 based robot with a little motor controller, and it supports both audio control and a little web app that I created. The web app is actually quite enjoyable. You can take a group of Screamsy's, put them together, and play a game we call Screamsy Soccer. But here you can actually experience firsthand why parents might hate this toy. One thing I learned in creating the Screamsy and creating my own printed circuit boards is you can actually repurpose them. So I took the same controller, without the audio input, but with the web application support, and created Big Red. All of this led me to what my real idea was, a challenge coin for the infosecond-advanced technologies communities. Imagine for a moment you've got a challenge coin, but it's electronic. And so you have the ability to do various puzzles, cryptography, various things like that would be possible with the challenge coin. And that was my idea for what became the e-challenge coin. Now the e-challenge coin did not start out looking anything like what my idea was. But eventually I was able to test out the idea for the touch sensors, the LEDs, the other controls, and get to my very first prototype, which didn't work. Which led me to my second prototype, which kind of didn't work, but with a few bodges I was able to make it function. And then finally to the third prototype. And here we actually did to see the AT Mega 328PB, the LEDs, and the resistors. But I noticed I was starting to run out of space. I had to modify my expectations of 0805 components down to 0603s. And then here we have the final e-challenge coin, the production model. One challenge coin wasn't enough. Eventually I created 240 e-challenge coins, all by hand. Programming these was a challenge in and of itself. I created the portable ISP programmer for this purpose. It was specifically for ISP chips like the AT Mega 328PB, but it also worked on AT Tiny chips. And I created a series of ornaments. I create one new ornament each year, the first being the bell. That was followed by the snowman, and then now most recently the tin soldier. And these all use AT Tiny 13s. And here's the original portable ISP, built using a TT GO 18650. And the only modification that had to be made was one capacitor was added to it. And then a series of wires to get me my little breakout header at the end. The interface of the portable ISP uses a single button. You can see it here is green. And actually that just is a plastic push button that activates a button that's already on the printed circuit board. So the portable ISP required no custom hardware to create what we have here. I did create a series of jigs and cables that make it easier for working with various projects. Here's an example of me using the portable ISP. This is a QFP32 adapter, simply plugged in. And to place the chip in it, press the button to start the programming process. It loads the firmware to the chip. And then it goes through the process of verifying the flash process. And it's ready to flash another chip. So this is how I was able to flash a series of chips each day I was working on these. When I started the 2021 E Challenge coin, I needed UDPI support. Well, the portable ISP was only SPI support. So I started working on the code to create the portaprog. And the initial first version of the portaprog looked exactly like the portable ISP. Then I started to think about how I was going to do tests, because the test on the original E Challenge coin was a very manual task. None of it could be automated. And so I started looking at alternatives. And so I went to the next version of the TT Go. This gave me a little scrolling to spray with a joystick. But what I really wanted was I wanted a larger screen. And so I started trying out other pre-existing hardware. And while the large screen on the right worked very well, it required a lot of modification to the board. Eventually I settled on the portaprog using a TT Go T display. In addition to the cables that I've created for the portaprog, I've developed a jig design. It uses a reusable base with two different clamping locations. And then interchangeable adapters. And each time I create a new project, I create an adapter for that project. The command set for the portaprog evolved over time. Initially I focused on the programming capabilities, the ability to send flash firmware to the portaprog, the ability to flash a device from the portaprog, store the firmware to the local file system on the portaprog so that I would be able to use it at a later date, interrogate and set the fuses, and potentially deal with the eProm being able to read and write that information as well. That expanded to then being able to do some various configuration of a UART interface between the portaprog and an attached device, as well as interrogating a chip to find out what its memory capabilities, its version, its type information is available. And some configuration information, the ability to detect a chip that's attached, get information about that chip, manually specify that the portaprog should be working in UDPI mode versus SPI mode, and setting up the UART between the portaprog and the attached device. This led me to wanting to do test automation, and a number of other commands started to evolve, and the portaprog command set grew very quickly. The ability to power on and off the device, send UART messages to the device, and query UART messages coming back from the device. Also, since the portaprog had some available buttons, I wanted to be able to customize and configure those for any particular application. Very early in the portaprog development process, I settled on an architecture for how the memory was going to be processed and how information was going to flow between the various endpoints. So our computer, our portaprog, and our attached device, and information would flow between them. I decided that I wanted the flow to only occur between two points at a time. So while the portaprog has local storage, it also has an in-memory buffer. So communication between the computer and the portaprog would be between the communication and the in-memory buffer. Portaprog to the device would be the in-memory buffer between the device and the portaprog and its local storage would be in-memory to local storage. So the memory is always used as sort of a way station for the information. This actually has a number of benefits. Performance is one of them, but also data validation is another. So a typical development scenario, information is sent from the computer as a stream to the portaprog and it's stored in memory. Then a write command will take that information from memory and send it out to the device. To program a device off-site using the portaprog and standalone, the firmware is loaded from the file system to in-memory and then from memory to the device. To pull information from a device, it's read from the device to the in-memory buffer, and then it can either be stored from memory to the local file system or it can be received by the computer. And finally in a production environment, information is loaded from the file system to memory and then because it's stored in memory and it persists, it can be written to a device, a new attached device written again, a new attached device written again, repeat, repeat, repeat. Let's take a look at a development scenario with the portaprog. Here we have an example. This is the 2021 eChallenge coin and it's DICE demo. The DICE demo is actually pretty simple and waits for the user to touch one of the touch sensors to determine whether it's going to be doing a randomization of a one-sided die through an eight-sided die. Once that's done, it will go and begin an animation. The animation is on the coin itself using the LEDs. The animation progresses and it gradually starts to slow down. And then when it reaches a lower threshold, the animation will stop and the randomized die value will be displayed using one of the LEDs and text information is output on the UART from the device. So the portaprog is actually able to receive that UART information and display it on its screen. For development, I use VSCode in conjunction with VSCode and Platform.io actually has an option for a custom upload command. So I'm able to integrate this directly with the portaprog. You can see here we set the device type to UDPI then we echo the send command to the portaprog followed by cat and the source code. This is the stream information that gets uploaded to the device and then finally we execute the write command which takes it from the in-memory buffer of the portaprog and puts it out onto itself. And we see here in the upper corner that's actually a screenshot of the portaprog screen. It has done the write, it does the verify and then it's done and it can be tested directly on the device. It's also possible to set up the portaprog if it's plugged into a USB port to have the information that's coming from the device to the portaprog over UART be echoed from the portaprog to your computer. The portaprog is configured at one baud rate to talk to the device. In this case UART messages will be displayed on the device but they will also be echoed back to the portaprog. The portaprog is configured at one baud rate to send the code to the portaprog. The portaprog will then start the write process followed by the verify process and then any other output from the coin, so in this case those UART messages we had, will be displayed on the device but they will also be echoed back to the portaprog. The portaprog will then be sent to the device but they will also be echoed back to the computer here. See the device has been set to UDPI, it has received the portaprog has received the appropriate code and now let's jump over to the terminal and we'll be able to see the UART information. We can see here that it's still proceeding with the write, the write is finished, now it's doing the verify task and if you remember in our demo what happens is the user touches one of the touch sensors and that determines how to start a randomizing process and then it will actually have come up with the values and then we have it, we've gone through, we've done a couple of tests and that information is actually going from the device to the portaprog being displayed on the portaprog screen but then it's also being echoed through the UART back to the computer, kind of handy when you're doing development. Taking a look at the portaprog device itself, there's three programmable buttons across the top and then there's also a navigation button to move through menus, I can also scroll backwards through the virtual viewport display buffer that's available and then a press of the middle short press versus long press will have two different actions. So here we're just going through and we're going to navigate through the various files, these are the files that are currently on this portaprog, there's three firmware files, ornament, snowman and bell and we can either flash those, we can delete them, we can turn to the previous menu so let's go through the process of just deleting these files, so here it's pretty easy we just do a delete, we do a long press we select the file again, we move down to delete, we do a long press and we've deleted all the files that are currently on this portaprog I've shown you the various ornament projects I have, there's actually four files here, so I have a smoke test that works on any ornament and then there's the production code for the three ornaments I currently have available the snowman, the bell and the soldier so this one file we'll go through the process of removing any existing files from the portaprog and then it will go through the process of uploading and storing the new firmware, so the send command is sending from the computer to the portaprog, then we follow that by the cat command which is actually just streaming the hex file and then finally we do a store and a file name so they get saved to the portaprog's flash storage, executing the command will actually be able to see the information arrive on the portaprog screen so the upload is going to first do the deletes, then it's going to follow that by doing the upload of each of the firmware of course we've already deleted the file so those deletes generate errors and then we see that we've received and stored, received and stored, received and stored repeatedly for the files that are now uploaded to that device we can take a quick look and actually see that those files are on the device, we can do a directory of the portaprog in addition to doing a directory of the portaprog we can do a cat command on a file, here we are looking at the config file Wi-Fi is Skynet, be careful and the port is the port for all the commands being sent to it that's customizable, the bot right refers to the communication between the portaprog and the attached device and then we can also specify script commands or even script files to the three programmable buttons I often refer to the portaprog as my bench buddy so when it's not at my computer it's over at my bench and I use it when I'm doing production work so for instance if I'm making a batch of 10 ornaments I will have it set up so I can just quickly flash the smoke test onto each one of the 10, verify that they've been assembled correctly and then flash final firmware and the process is very quick because the firmware gets loaded into memory from the onboard storage and then it simply goes from memory out to the device repeat repeat repeat I've created a tag connect cable from my portaprog and my ornaments all have the footprint for the tag connect on them the ornaments use an AT tiny 13 so the firmware is about 1K the file of course is larger because it's in hex ascii format and so button one will do a right command so we attach it to the ornament press the right command press the right command press the right command and repeat right down the line and just like that we've programmed all 10 of these with the final production firmware the pre-production version of the portaprog is using a ttco t-display the portaprog has a gsp32 with battery charge capability the portaprog itself is a receiver board with a few additional components to combine the two together there are a few bodges let's take a look at those looking at the component side of the board let's dive into which modifications I had to make to the ttco to be able to be used as a portaprog the first modification I make deals with the ldo of the board so the ldo has an enable resistor which is tied to the voltage source whether that be usb or battery anytime either is connected the board is active and live to be able to have an on off switch I remove this resistor the second modification is to remove a pair of coupling capacitors that tie together gpio pins collectively these two capacitors affect four different gpio pins that we're going to be using that concludes the modifications to the ttco now let's look at how we actually combine it with the portaprog board itself so we removed that ldo resistor what we're going to do is r1 is actually a replacement for that resistor and then we tie a wire from that resistor pad down to tp1 this is actually the enable pin of the ldo tp1 then connects to the switch 5 and that's how we get our power switch to work so the power switch basically ties the voltage source back through r1 and back up to the ldo next we need a lot of gpio pins, gpio 36 through 39 on an esp32 do not have pull-up resistors so I use a resistor network to provide pull-ups to all four of those gpio pins while I'm at it I also add resistors for rx and tx of the uart connection that's r3 and r4 finally r2 is a bridge resistor between the rx and tx used for udpi so the process of creating a udpi is since it's a one wire serial interface you take rx and tx, you bridge them with a resistor and then you take the rx side as your udpi so the receive is unattinuated and the transmit is attinuated the final thing I add is a MOSFET and that is to control power to the attached device I found that I was having voltage bleed through on uart and other pins and so if many of the pins from the portaprog were connected to the device even if I shut off vcc to the device it would still often have just enough power in a low power mode to operate this MOSFET actually switches the ground side of the pins to the attached device up to this point we've dealt with the programming and interaction between the portaprog and an attached device for this set of capabilities the existing hardware from the portable isp would be sufficient I may actually go through the process of porting the code that I currently have back to that hardware one of the reasons is that hardware is readily available and the price of that hardware has not changed much anyone looking for a portaprog primarily for programming capability that would be flashing firmware and modifying fuses this hardware is sufficient and it works great on the bench as demonstrated when I did the programming of the ornaments the limiting factor on these two ttgo boards is the OLE display its resolution is insufficient for doing any real test automation on the display however the one with the joystick does have PS RAM which would allow for larger buffers for larger chips moving forward we're now going to look at the scripting capability and the abilities for doing test automation the portaprog source code actually generates its readme file and its online documentation so in addition to all of the commands being available on the portaprog using its help command all that information in extended form is available on the open source at GitLab Brayden Lane portaprog the command set is broken up into a series of categories the first one being configuration that would be setting up the portaprog for communication with the attached device so that would be things like the baud rate is it a UDPI chip is it an SPI chip there's also commands for detecting what kind of chip is attached interrogating it for its information storage EEPROM that kind of information there's a series of file commands for interacting with the portaprog you can get a directory of the files that are currently stored on the portaprog you can delete those files you can actually ask it to list those files then there are a set of commands for the IO with the attached device this would be reading and writing the firmware to the device interacting with its EEPROM and setting and checking fuses are also available the IO commands are extended to moving data so the moving operations we've seen before moving from the computer to the in-memory buffers of the portaprog from the portaprog out to an attached device down to the file system from the file system to in-memory there are also commands for sending a command file from the computer to the portaprog and storing it and also loading a command file from the local storage and executing it when sending firmware from a computer to the portaprog it uses the intel hex or i8 hex file format and the portaprog processes that and verifies it when it stores it in memory in memory it's stored as binary and then it's converted back to hex format when it's written out to the file system the AVR commands are specific to the device so the ability to read the fuses from the attached device and report them back uses with the exception of the locking bits i made a mistake once and so i no longer allow the portaprog to execute lock bits erasing an attached device writing new firmware to the attached device reading the firmware from it into memory and the read operation is actually smart it will read the entire chip and then it scans backwards from the end of the buffer that it just read until it finds uninitialized data so it does a it tries to be as smart as possible to come up with what size the actual firmware is can also read and write to eProm if the device has such a thing and then there's power commands and these are kind of helpful, you'll notice here that it does again refer to the sGround so that MOSFET is controlling the ground side of the circuit can be turned on and off or just toggled the power commands were created for two reasons the first was there were instances where i did not want the device to start executing immediately after it had been written and verified the second case is during development if i want to restart the device i can just do a quick power cycle the command set also includes the ability to set the scripts that are going to be executed by the three programmable buttons these can be assigned individual commands a string of commands or a command file when i started to use the portaprog for doing test automation the script command set grew to include a set of commands for interacting with the portaprog display as well as interacting with the attached device the clear and text commands affect the portaprog itself so you're able to clear the display and put up an informational text message might be helpful for a test engineer there's also a uclear and utext these actually affect the attached device so uclear would clear anything that's in the buffer that may have come from the attached device to the portaprog the utext command sends text from the portaprog through to the attached device the utext command can be used in conjunction with the test command utext would send a piece of text from the portaprog to the attached device test then monitors the uart for a text string in the return and it can wait up to a certain period of time during that period of time it will continue to look for the text any text that doesn't match is discarded if it finds a match then it returns immediately otherwise it'll wait for the timeout the mute commands were late additions to the portaprog command set they prevent any internal messages of the portaprog being rendered on the display this is helpful during test automation so that the test script is the only information being displayed on the portaprog the portaprog config file stores information about attaching to the local wifi the port for its various command operations bot rate for the attached device timeout for the messages from the attached device the initial power state of the attached device an optional script file that will be run every time the portaprog first starts up and then default assignments for the various buttons a new portaprog does not have a config file so the documentation provides the most common commands for uploading a config file from windows and from linux if there is no config file the portaprog creates its own wifi hotspot to allow these to be uploaded also if a portaprog is away from its configured wifi it will also create its own hotspot the current portaprog hardware is using a ttgo t display with a 240x135 color display it uses all three serial ports and two spi interfaces serial 2 is used for udpi and that requires a 4.7k resistor connected between the rx and tx pins with the rx pin being the unified connection for udpi that is because udpi is a one wire serial interface so it reads and writes on the same single pin test automation was a driving factor for the creation of the portaprog the portable isp only did programming and the initial version of the portaprog also only did programming for spi chips and updi chips but i wanted to be able to do test automation when i started the 2020 e-challenge coin all i was focused on was programming i started the 2021 e-challenge coin i really wanted to make sure that i could verify all the hardware very easily at the bench and so test automation was what i wanted to perform so let's look at the files that are involved in setting up the portaprog when i'm doing test automation of course the config file here gonna connect to our wifi if it's available otherwise it sets itself up as a hotspot it'll then configure the connection for the uart between the attached device in this case the e-challenge coin and the portaprog so that's the 9600 baud with a 500 millisecond timeout and it will launch and execute the start file this will actually perform initialization of other operations what to do on the portaprog happens each time the portaprog is powered up so the first thing it's gonna do is it's gonna make sure that no power is attached to the device so the e-challenge coin will be powered down we set updi mode and we preload the firmware now the firmware has been loaded from spifs to our in-memory buffer we set button 1 to load and execute our smoke test and for convenience purposes i tend to set button 3 to power toggle that smoke test that's being executed whenever we press button 1 is over on the right hand side and we can take a look at the commands that are gonna be executed so each time button 1 gets pressed these commands will all execute in order so the first thing it's gonna do is it's gonna clear the uart connection between the portaprog and the e-challenge coin so there's no data still residing there it'll ensure that the power is off to the e-challenge coin and it will set the programming mode to updi both of those are redundant with our start file but it's just an easy way to make sure that everything's set the way we want it'll clear the screen on the portaprog the right command will flash firmware to the attached device and then perform verification and then mute on says no more information that the portaprog may be generating on its own should go to the screen one more time so at this point the only thing that will appear on the screen of the portaprog are messages that are coming from our smoke test process itself as soon as we power on issue that command then the code, the firmware on the e-challenge coin will start to execute and that is our smoke test code and the next thing we're gonna do is we're going to wait up to 5 seconds to see if we receive the word buzzer so that's what that test command is doing over in the smoke test itself and then an informational message on the display LEDs and tone is a good press the wake button tells the user to press the wake button if they do hear the tone and see all the LEDs light assuming that is all successful then we will output the message LED buzzer test pass and fail so you'll notice in our smoke test we're looking for the word buzzer so that now has been received and so our test script will actually continue on it's going to immediately send a piece of information over the UART using the UTEXT command it will send the word UART so that now has been sent from the portaprog to our e-challenge coin whenever it goes to check its receive buffer on the UART it will have that text waiting for it over in the script it will continue on we want to do a calibration of the touch sensor so we want to make sure that no touch sensors are being activated before we start the calibration we just give a warning to the user if indeed we detect any and then we perform the calibration itself if all the values are within a known range we'll mark that as pass if they're slightly out of range we can mark that as a warning and if they're way out of range then we can mark that as a fail typically this is a pass-fail test if a resistor is missing or has tombstoneed on the printed circuit board then that touch sensor will always be active and so this will end up as a failure as a sanity check we do a test of our pseudo-random generator and then we test the IR transceiver the programming jig that we're using for the 2020 mini challenge coin has an optical loop back on the IR transceiver so if we transmit the IR test it'll actually sit on the receive side and we can immediately look for it inside our loop we'll take a look have we received anything on the IR receive side if we have we'll compare that text against what we're looking for which is the text IR test if it matches we're good if it doesn't match we'll discard it and we'll give ourselves a couple of more attempts at this test we can loop through a few times if we get to the end of all the iterations on this and we never receive cleanly IR test then we'll mark this one fail otherwise we can mark it as pass remember over in our smoke test we have transmitted using the u-text command the text u-art and so we're going to take a look and say as anything come in on our u-art the challenge coin says yes I've received something on the u-art I want to compare it to what I'm expecting which is the word u-art and if it matches then I know that that test has been successful I can mark it as a pass fail and all of this loops a few times so we have a couple of chances to get all these tests done and then at the end of these loops we test all the flags for each of the tests and verify that we've received a status on every test if all of those tests were successful then the code sets an eProm byte to one which says ok the smoke test was successful you can now switch from smoke test to production mode and then we will transmit back over the u-art to the portaprog smoke test pass or fail remember for the past six seconds we've been looking for the word smoke test thankfully this test runs much faster than I can talk it will have received the word smoke test and then the script will just simply wait for 500 milliseconds and then power off the eChallengeCoin and unmute the portaprog now let's actually take a look at the portaprog the test jig and the 2021 eChallengeCoin and see this example execute this will be done at the bench so there's the portaprog in the jig eChallengeCoin you can see the wake button right there there's the script we're going to be running it's been assigned to button one so every time we press button one it will load and execute the script so it's powered off the eChallengeCoin it has set it to UPDI mode it has started the write operation so we're flashing the firmware as soon as the firmware has been flashed we will start the verification process of the firmware it will clear the screen and then it will power on the eChallengeCoin and immediately start executing those commands and we press ok we're done and all the tests have passed smoke test has passed and it has powered off the eChallengeCoin the bulk of the time is spent during the write operation and we're back in addition to the portaprog itself I've developed a jig adapter system the reason is because each one of my projects tends to have a custom printed circuit board and has different requirements for how it is interfaced here you see the 2020 eChallengeCoin in black the 2021 eChallengeCoin they're in white the red is the eChallengeCard and the blue is the smart response xe device each one of these has a different way of being interfaced for programming and for test so the eChallengeCoin use the tabs around the perimeter the eChallengeCard uses a standard pin header the smart response xe device has a custom footprint under the case initially I used cables for interfacing to the various printed circuit boards so for the eChallengeCoin in 2020 when I was doing the development I created this little pigtail with a standard SPI connector on one end and a series of alligator clips on the other these could be connected to the tabs around the perimeter of the eChallengeCoin and the standard pin header simply plugs into the end connector on the portaprog and the portaprog maintains a standard SPI six pin connector as the first portion of its header when I moved from the portable ISP to the portaprog I was able to bring along the QFP32 adapter I have not recently used this adapter but I will have the jig assembly that I'll be showing and here is the tag connect cable that I use on my holiday ornaments when programming and testing a large number of PCBs at a time it's helpful to have a jig that does the alignment for me so here is the reusable base and this is the interface adapter for the 2020 eChallengeCoin it uses pogo pins for the SPI interface and the portaprog slides into the side and interfaces to the little adapter board then it's simply a matter of lifting the arm, placing in the printed circuit board closing the arm and then pressing the program smoke test button once the portaprog has been configured for another project it's a matter of simply sliding out the adapter so now we'll slide in the adapter for the 2021 eChallengeCoin you can see it actually has a little insert which will auto align against the battery holder place in the printed circuit board lock it down slide in the portaprog and we're ready to start programming the 2021 eChallengeCoin this one actually has that little optical loop back for the IR transceiver the portaprog jig actually has two locations for clamping so for the eChallengeCoin the clamp is in the lower position for the eChallengeCard the clamp is in the upper position while I could move the clamp between the two I've just printed another base so I'll insert the adapter for the eChallengeCard the little black U you see at the bottom is actually its optical loop back because the IR transceiver is located at the bottom of the card place the card in, clamp it down and once again we just slide the portaprog into its position and now we can start programming the eChallengeCard finally we have the eChallenge console project which is the upscaling of the SmartResponse XE device and I have printed an adapter for it it uses a series of Pogo pins aligned to a custom footprint that is inside the SmartResponse XE device and is accessed through a series of holes in the battery compartment drop the device in clamp it into position and we're ready to start so this is the ecosystem that I have created for the portaprog jigs consisting of a standard base with two clamp locations interchangeable adapters to create them the eChallenge card the 2021 eChallenge coin the 2020 eChallenge coin the eChallenge console and the cables so what's next for the portaprog the real question is is it a product, is it a prototype is it an exercise left for the reader while I like the TTGO T-Display it requires too many bodges and the assembly process while I have been successful at creating 10 or 15 of them it's time consuming and it's error prone I am hoping that Adafruit will be releasing later this year a new feather, an ESP32 with the display already integrated and three buttons if this becomes available I will likely port the portaprog to this device and find a way to get by with just the three buttons another option I've played with is creating my own custom board this would use a sharp memory display so that's a 400x240 monochrome display and a third option I'm investigating is Dustin Watts's Touchdown which is a touch deck with a 480x320 and touchscreen and hopefully one of those three options will work out in the meantime you're welcome to create your own portaprog all the code is open source and available and if you have any requests or find a bug pull requests are encouraged and there you have it the portaprog a portable ISP and UDPI programmer for both development and production follow me on Instagram and on Twitter and don't forget to check out the open source at GitLab, Brayden Lane, Portaprog