How to generate HEX/BIN file for eprom using C? - Page 1
Forum section: electronics / general

author: georgian
author_rank: Regular Contributor
timestamp: November 09, 2020, 09:52:11 pm
content: Hello guys,I'm working on some sort of 8bit to 12bit encoder/decoder (not sure how to name it). I want to have an 8bit BCD input displayed on 3 7-segment displays. For this I want to use an D27C210 EPROM (because it has more than enough outputs).Using the code below i split a number into its digits and than concatenate them to get the desired combination.for example: address 1 -> 0x1.....address 100 -> 0x100...address 255 -> 0x255.The questions are, how to arrange the data into one file, or table. Can i just use fopen() to create a file and write to it? What should i write? HEX or DEC value? The output file should be compatible with the TL866II Plus programmer (I don't have it yet, but it's on the way)I know that there are other ways to achieve this but I still want to know how to generate a HEX file for an EPROM.Thanks a lot.Code:#include<stdlib.h>#include<stdio.h>int finalResult();int split(int length);int digits; //Array to store each digit.int main() {//Test routinefor (int i = 0; i < 256; i++) {split(i);printf("Address: %d\tValue HEX: 0x%X \tValue DEC: %d\n", i, finalResult(), finalResult());}return 0;}//Split the number into 3 digits and store them in an array.int split(int input) {int pos = 0;while (input > 0) {int digit = input % 10;digits = digit; pos++;input /= 10;}return pos;}//Concatenate the digits each ito it's right position.int finalResult() {int res = ((digits << 8) | digits << 4) | digits;return res;}Console output:Code:Address: 0Value HEX: 0x0Value DEC: 0Address: 1Value HEX: 0x1Value DEC: 1Address: 2Value HEX: 0x2Value DEC: 2Address: 3Value HEX: 0x3Value DEC: 3Address: 4Value HEX: 0x4Value DEC: 4Address: 5Value HEX: 0x5Value DEC: 5Address: 6Value HEX: 0x6Value DEC: 6Address: 7Value HEX: 0x7Value DEC: 7Address: 8Value HEX: 0x8Value DEC: 8Address: 9Value HEX: 0x9Value DEC: 9Address: 10Value HEX: 0x10Value DEC: 16Address: 11Value HEX: 0x11Value DEC: 17Address: 12Value HEX: 0x12Value DEC: 18Address: 13Value HEX: 0x13Value DEC: 19Address: 14Value HEX: 0x14Value DEC: 20Address: 15Value HEX: 0x15Value DEC: 21Address: 16Value HEX: 0x16Value DEC: 22Address: 17Value HEX: 0x17Value DEC: 23Address: 18Value HEX: 0x18Value DEC: 24Address: 19Value HEX: 0x19Value DEC: 25Address: 20Value HEX: 0x20Value DEC: 32Address: 21Value HEX: 0x21Value DEC: 33Address: 22Value HEX: 0x22Value DEC: 34Address: 23Value HEX: 0x23Value DEC: 35Address: 24Value HEX: 0x24Value DEC: 36Address: 25Value HEX: 0x25Value DEC: 37Address: 26Value HEX: 0x26Value DEC: 38Address: 27Value HEX: 0x27Value DEC: 39Address: 28Value HEX: 0x28Value DEC: 40Address: 29Value HEX: 0x29Value DEC: 41Address: 30Value HEX: 0x30Value DEC: 48Address: 31Value HEX: 0x31Value DEC: 49Address: 32Value HEX: 0x32Value DEC: 50Address: 33Value HEX: 0x33Value DEC: 51Address: 34Value HEX: 0x34Value DEC: 52Address: 35Value HEX: 0x35Value DEC: 53Address: 36Value HEX: 0x36Value DEC: 54Address: 37Value HEX: 0x37Value DEC: 55Address: 38Value HEX: 0x38Value DEC: 56Address: 39Value HEX: 0x39Value DEC: 57Address: 40Value HEX: 0x40Value DEC: 64Address: 41Value HEX: 0x41Value DEC: 65Address: 42Value HEX: 0x42Value DEC: 66Address: 43Value HEX: 0x43Value DEC: 67Address: 44Value HEX: 0x44Value DEC: 68Address: 45Value HEX: 0x45Value DEC: 69Address: 46Value HEX: 0x46Value DEC: 70Address: 47Value HEX: 0x47Value DEC: 71Address: 48Value HEX: 0x48Value DEC: 72Address: 49Value HEX: 0x49Value DEC: 73Address: 50Value HEX: 0x50Value DEC: 80Address: 51Value HEX: 0x51Value DEC: 81Address: 52Value HEX: 0x52Value DEC: 82Address: 53Value HEX: 0x53Value DEC: 83Address: 54Value HEX: 0x54Value DEC: 84Address: 55Value HEX: 0x55Value DEC: 85Address: 56Value HEX: 0x56Value DEC: 86Address: 57Value HEX: 0x57Value DEC: 87Address: 58Value HEX: 0x58Value DEC: 88Address: 59Value HEX: 0x59Value DEC: 89Address: 60Value HEX: 0x60Value DEC: 96Address: 61Value HEX: 0x61Value DEC: 97Address: 62Value HEX: 0x62Value DEC: 98Address: 63Value HEX: 0x63Value DEC: 99Address: 64Value HEX: 0x64Value DEC: 100Address: 65Value HEX: 0x65Value DEC: 101Address: 66Value HEX: 0x66Value DEC: 102Address: 67Value HEX: 0x67Value DEC: 103Address: 68Value HEX: 0x68Value DEC: 104Address: 69Value HEX: 0x69Value DEC: 105Address: 70Value HEX: 0x70Value DEC: 112Address: 71Value HEX: 0x71Value DEC: 113Address: 72Value HEX: 0x72Value DEC: 114Address: 73Value HEX: 0x73Value DEC: 115Address: 74Value HEX: 0x74Value DEC: 116Address: 75Value HEX: 0x75Value DEC: 117Address: 76Value HEX: 0x76Value DEC: 118Address: 77Value HEX: 0x77Value DEC: 119Address: 78Value HEX: 0x78Value DEC: 120Address: 79Value HEX: 0x79Value DEC: 121Address: 80Value HEX: 0x80Value DEC: 128Address: 81Value HEX: 0x81Value DEC: 129Address: 82Value HEX: 0x82Value DEC: 130Address: 83Value HEX: 0x83Value DEC: 131Address: 84Value HEX: 0x84Value DEC: 132Address: 85Value HEX: 0x85Value DEC: 133Address: 86Value HEX: 0x86Value DEC: 134Address: 87Value HEX: 0x87Value DEC: 135Address: 88Value HEX: 0x88Value DEC: 136Address: 89Value HEX: 0x89Value DEC: 137Address: 90Value HEX: 0x90Value DEC: 144Address: 91Value HEX: 0x91Value DEC: 145Address: 92Value HEX: 0x92Value DEC: 146Address: 93Value HEX: 0x93Value DEC: 147Address: 94Value HEX: 0x94Value DEC: 148Address: 95Value HEX: 0x95Value DEC: 149Address: 96Value HEX: 0x96Value DEC: 150Address: 97Value HEX: 0x97Value DEC: 151Address: 98Value HEX: 0x98Value DEC: 152Address: 99Value HEX: 0x99Value DEC: 153Address: 100Value HEX: 0x100Value DEC: 256Address: 101Value HEX: 0x101Value DEC: 257Address: 102Value HEX: 0x102Value DEC: 258Address: 103Value HEX: 0x103Value DEC: 259Address: 104Value HEX: 0x104Value DEC: 260Address: 105Value HEX: 0x105Value DEC: 261Address: 106Value HEX: 0x106Value DEC: 262Address: 107Value HEX: 0x107Value DEC: 263Address: 108Value HEX: 0x108Value DEC: 264Address: 109Value HEX: 0x109Value DEC: 265Address: 110Value HEX: 0x110Value DEC: 272Address: 111Value HEX: 0x111Value DEC: 273Address: 112Value HEX: 0x112Value DEC: 274Address: 113Value HEX: 0x113Value DEC: 275Address: 114Value HEX: 0x114Value DEC: 276Address: 115Value HEX: 0x115Value DEC: 277Address: 116Value HEX: 0x116Value DEC: 278Address: 117Value HEX: 0x117Value DEC: 279Address: 118Value HEX: 0x118Value DEC: 280Address: 119Value HEX: 0x119Value DEC: 281Address: 120Value HEX: 0x120Value DEC: 288Address: 121Value HEX: 0x121Value DEC: 289Address: 122Value HEX: 0x122Value DEC: 290Address: 123Value HEX: 0x123Value DEC: 291Address: 124Value HEX: 0x124Value DEC: 292Address: 125Value HEX: 0x125Value DEC: 293Address: 126Value HEX: 0x126Value DEC: 294Address: 127Value HEX: 0x127Value DEC: 295Address: 128Value HEX: 0x128Value DEC: 296Address: 129Value HEX: 0x129Value DEC: 297Address: 130Value HEX: 0x130Value DEC: 304Address: 131Value HEX: 0x131Value DEC: 305Address: 132Value HEX: 0x132Value DEC: 306Address: 133Value HEX: 0x133Value DEC: 307Address: 134Value HEX: 0x134Value DEC: 308Address: 135Value HEX: 0x135Value DEC: 309Address: 136Value HEX: 0x136Value DEC: 310Address: 137Value HEX: 0x137Value DEC: 311Address: 138Value HEX: 0x138Value DEC: 312Address: 139Value HEX: 0x139Value DEC: 313Address: 140Value HEX: 0x140Value DEC: 320Address: 141Value HEX: 0x141Value DEC: 321Address: 142Value HEX: 0x142Value DEC: 322Address: 143Value HEX: 0x143Value DEC: 323Address: 144Value HEX: 0x144Value DEC: 324Address: 145Value HEX: 0x145Value DEC: 325Address: 146Value HEX: 0x146Value DEC: 326Address: 147Value HEX: 0x147Value DEC: 327Address: 148Value HEX: 0x148Value DEC: 328Address: 149Value HEX: 0x149Value DEC: 329Address: 150Value HEX: 0x150Value DEC: 336Address: 151Value HEX: 0x151Value DEC: 337Address: 152Value HEX: 0x152Value DEC: 338Address: 153Value HEX: 0x153Value DEC: 339Address: 154Value HEX: 0x154Value DEC: 340Address: 155Value HEX: 0x155Value DEC: 341Address: 156Value HEX: 0x156Value DEC: 342Address: 157Value HEX: 0x157Value DEC: 343Address: 158Value HEX: 0x158Value DEC: 344Address: 159Value HEX: 0x159Value DEC: 345Address: 160Value HEX: 0x160Value DEC: 352Address: 161Value HEX: 0x161Value DEC: 353Address: 162Value HEX: 0x162Value DEC: 354Address: 163Value HEX: 0x163Value DEC: 355Address: 164Value HEX: 0x164Value DEC: 356Address: 165Value HEX: 0x165Value DEC: 357Address: 166Value HEX: 0x166Value DEC: 358Address: 167Value HEX: 0x167Value DEC: 359Address: 168Value HEX: 0x168Value DEC: 360Address: 169Value HEX: 0x169Value DEC: 361Address: 170Value HEX: 0x170Value DEC: 368Address: 171Value HEX: 0x171Value DEC: 369Address: 172Value HEX: 0x172Value DEC: 370Address: 173Value HEX: 0x173Value DEC: 371Address: 174Value HEX: 0x174Value DEC: 372Address: 175Value HEX: 0x175Value DEC: 373Address: 176Value HEX: 0x176Value DEC: 374Address: 177Value HEX: 0x177Value DEC: 375Address: 178Value HEX: 0x178Value DEC: 376Address: 179Value HEX: 0x179Value DEC: 377Address: 180Value HEX: 0x180Value DEC: 384Address: 181Value HEX: 0x181Value DEC: 385Address: 182Value HEX: 0x182Value DEC: 386Address: 183Value HEX: 0x183Value DEC: 387Address: 184Value HEX: 0x184Value DEC: 388Address: 185Value HEX: 0x185Value DEC: 389Address: 186Value HEX: 0x186Value DEC: 390Address: 187Value HEX: 0x187Value DEC: 391Address: 188Value HEX: 0x188Value DEC: 392Address: 189Value HEX: 0x189Value DEC: 393Address: 190Value HEX: 0x190Value DEC: 400Address: 191Value HEX: 0x191Value DEC: 401Address: 192Value HEX: 0x192Value DEC: 402Address: 193Value HEX: 0x193Value DEC: 403Address: 194Value HEX: 0x194Value DEC: 404Address: 195Value HEX: 0x195Value DEC: 405Address: 196Value HEX: 0x196Value DEC: 406Address: 197Value HEX: 0x197Value DEC: 407Address: 198Value HEX: 0x198Value DEC: 408Address: 199Value HEX: 0x199Value DEC: 409Address: 200Value HEX: 0x200Value DEC: 512Address: 201Value HEX: 0x201Value DEC: 513Address: 202Value HEX: 0x202Value DEC: 514Address: 203Value HEX: 0x203Value DEC: 515Address: 204Value HEX: 0x204Value DEC: 516Address: 205Value HEX: 0x205Value DEC: 517Address: 206Value HEX: 0x206Value DEC: 518Address: 207Value HEX: 0x207Value DEC: 519Address: 208Value HEX: 0x208Value DEC: 520Address: 209Value HEX: 0x209Value DEC: 521Address: 210Value HEX: 0x210Value DEC: 528Address: 211Value HEX: 0x211Value DEC: 529Address: 212Value HEX: 0x212Value DEC: 530Address: 213Value HEX: 0x213Value DEC: 531Address: 214Value HEX: 0x214Value DEC: 532Address: 215Value HEX: 0x215Value DEC: 533Address: 216Value HEX: 0x216Value DEC: 534Address: 217Value HEX: 0x217Value DEC: 535Address: 218Value HEX: 0x218Value DEC: 536Address: 219Value HEX: 0x219Value DEC: 537Address: 220Value HEX: 0x220Value DEC: 544Address: 221Value HEX: 0x221Value DEC: 545Address: 222Value HEX: 0x222Value DEC: 546Address: 223Value HEX: 0x223Value DEC: 547Address: 224Value HEX: 0x224Value DEC: 548Address: 225Value HEX: 0x225Value DEC: 549Address: 226Value HEX: 0x226Value DEC: 550Address: 227Value HEX: 0x227Value DEC: 551Address: 228Value HEX: 0x228Value DEC: 552Address: 229Value HEX: 0x229Value DEC: 553Address: 230Value HEX: 0x230Value DEC: 560Address: 231Value HEX: 0x231Value DEC: 561Address: 232Value HEX: 0x232Value DEC: 562Address: 233Value HEX: 0x233Value DEC: 563Address: 234Value HEX: 0x234Value DEC: 564Address: 235Value HEX: 0x235Value DEC: 565Address: 236Value HEX: 0x236Value DEC: 566Address: 237Value HEX: 0x237Value DEC: 567Address: 238Value HEX: 0x238Value DEC: 568Address: 239Value HEX: 0x239Value DEC: 569Address: 240Value HEX: 0x240Value DEC: 576Address: 241Value HEX: 0x241Value DEC: 577Address: 242Value HEX: 0x242Value DEC: 578Address: 243Value HEX: 0x243Value DEC: 579Address: 244Value HEX: 0x244Value DEC: 580Address: 245Value HEX: 0x245Value DEC: 581Address: 246Value HEX: 0x246Value DEC: 582Address: 247Value HEX: 0x247Value DEC: 583Address: 248Value HEX: 0x248Value DEC: 584Address: 249Value HEX: 0x249Value DEC: 585Address: 250Value HEX: 0x250Value DEC: 592Address: 251Value HEX: 0x251Value DEC: 593Address: 252Value HEX: 0x252Value DEC: 594Address: 253Value HEX: 0x253Value DEC: 595Address: 254Value HEX: 0x254Value DEC: 596Address: 255Value HEX: 0x255Value DEC: 597

author: S. Petrukhin
author_rank: Super Contributor
timestamp: November 10, 2020, 12:12:29 am
content: Do you want to write a binary value conversion table in EEPROM to 3x7 = 21 discrete outputs for displaying it on the led?

author: georgian
author_rank: Regular Contributor
timestamp: November 10, 2020, 12:26:35 am
content: Quote from: S. Petrukhin on November 10, 2020, 12:12:29 amNo, it will be 3 x 4. 3 BCD outputs to connect to CD4511 7 segment driver.I'll use just 8 address lines. When they are all high (255) the output of the EPROM will be something like this.D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D110 0 1 0 0 1 0 1 0 1 0 1 -- 597 (decimal) / 0x255 (hex)D0 - D3 connected to 1st CD4511D4 - D7 connected to 2nd CD4511D8 - D11 connected to 3rd CD4511I hope it's more clear now.I intend to play more with EPROMS and for the next project will be to store instruction for a standard 16x2 LCD. But for every project I need to generate a hex file for the EEPROM.

author: S. Petrukhin
author_rank: Super Contributor
timestamp: November 10, 2020, 12:58:13 am
content: Quote from: georgian on November 10, 2020, 12:26:35 amDo you need to display a binary number from 0 to 999 on the indicator using BCD drivers, and transcode BIN - > 3 digits of BCD in EPROM? You can do without EPROM, but if you really need it, then here are the steps, it can be made more compact, I wrote this for clarity:Code:int d1,d2,d3;uint_16 res;for (int i=0; i<=999; i++) {d1=i / 100;d2=(i - d1*100) / 10;d3=i - d1*100 - d2*10;res=(d1 << 8) or (d2 << 4) or d3;printf("Address: %d\tValue HEX: 0x%X",i,res)}And just write the res values to a binary file. The programmer can flash a binary image to EPROM, it is not necessary to do it in HEX format.

author: helius
author_rank: Super Contributor
timestamp: November 10, 2020, 01:28:23 am
content: I would suggest that the easiest way is to write your file in binary and then write binary to the PROM."Hex files" are not actually just hexadecimal numbers, they are one of several specific formats that use commands to put data in specific addresses, and also have check digits. Intel Hex has different commands from Motorola Hex, etc. So you could read the documentation for (e.g.) Intel Hex, decide how to use commands to output your data, generate lines of the appropriate length to the correct addresses, etc etc... Or just write in binary which the TL866 can write verbatim without any other complexity.

author: brucehoult
author_rank: Super Contributor
timestamp: November 10, 2020, 02:24:25 am
content: You can use standard gnu tools to create exactly the binary file you want using either assembly language or C.Create a simple minimal linker script something like this in a file rom_link:Code:OUTPUT_FORMAT(ihex)MEMORY {rom : ORIGIN = 0, LENGTH = 2K}SECTIONS {.text : {} >rom}Then write your ROM values in, for example, assembly language in romdata.S:Code:.byte 1,2,3,4,5Then build it:Code:$ gcc -nostartfiles -nostdlib -T rom_link -o romdata romdata.S$ cat romdata:050000000102030405EC:00000001FF$If you wish, you could put.org 2048after the.byteto fill the rest of the ROM with zeroes. If you put more data there than was specified inLENGTHin the linker script then the linker will give an error.Or, you can do it in C, say in romdata.c:Code:char foo[] = {1,2,3,4,5};Build it in just the same way:Code:$ gcc -nostartfiles -nostdlib -T rom_link -o romdata romdata.c$ cat romdata:050000000102030405EC:00000001FF$The output file will be the same.

author: tszaboo
author_rank: Super Contributor
timestamp: November 10, 2020, 08:32:07 am
content: Use a standard way. It is almost always better to use a standard, because there are tools available.Either write the file as an Intel HEX or a Motorola HEX. And search for a library, then you dont need to reinvent the wheel.

author: Syntax Error
author_rank: Frequent Contributor
timestamp: November 10, 2020, 12:50:07 pm
content: Do you have a schematic for your circuit?Just a thought here. From my understanding, the 4511 has a latching/strobe pin which keeps the 7 seg display static or loads the data. So connecting your 4511 drivers direct to a microcontroller only requires 3 GPIO pins for the latching lines and 4 for the BCD lines. You only ever need 4 lines for the BCD, so you can add as many digits as you have spare GPIO pins. The MCU contains the translation table, reads the input number and does the segment loading.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: November 10, 2020, 01:06:33 pm
content: I like to do these sorts of things in JS. It's accessible, it's pretty powerful, and it has access to most anything you might need. You can do it right here even, just hit F12!Example, copy this one-liner to the console* and run it:Code:window.location = URL.createObjectURL(new Blob(Array.from("Hello World\n"), {type: 'text/plain;charset=utf-8'}));This creates a "blob" (a container for data), from the data passed in (the "Hello World" string, converted to an array type), of MIME type text/plain (i.e., a text file). Then makes a URL to it, then sets the window to that URL to instantly view it. With a little different code, you can download that URL instead, and voila, you can save files of arbitrary (binary) content, just put in your array of data.This does of course need a JS environment to work, which pretty much anything useful has (JS of some sort is built into every modern OS; file access mechanisms will vary, of course). You may still be more comfortable with C or whatever, which is fine, and to be fair, it's probably easier to drop some stock HEX formatting code into C, than to port it to JS, if you need it in that format. But I wouldn't think it's much bother either way.There's no shortage of ways to do it; BASIC isn't very trendy these days, but would've been a prime choice in prior decades (back when every PC came with a BASIC ROM!), and is pretty easy to write stuff like this. Python and other high level languages are probably choice today. Or for the Linux guru, write it all in C, you've always got a compiler there at your fingertips, no problem whatsoever. Or in bash scripts for that matter...(Or, I'm not sure you'd want to (or even be able to) do such things with Windows batch files, but PowerShell probably could, for not too much more effort than with other command scripts.)Tim

author: georgian
author_rank: Regular Contributor
timestamp: November 10, 2020, 09:59:51 pm
content: Quote from: brucehoult on November 10, 2020, 02:24:25 amLooks like i can generate the file using your method.I will modify my code to output whatever I want in an array in a c file and that should do the trick. Can't wait for my programmer to test.@3sl4co1l - Great idea for quick and small projects. Not sure if it will work with 1Mb of data.@Syntax Error - Yeah, I know that an arduino can do that. Might be a lot cheaper as well. I did play around with arduino but never with parallel EPROMS, so it's time to level up, or down)Thank you all so far.*EDIT: Why is my romdata file different than yours? did you actualy use this line too?Code:char foo[] = {1,2,3,4,5};

author: brucehoult
author_rank: Super Contributor
timestamp: November 11, 2020, 12:55:46 am
content: QuoteDifferent how?Yes, I tested it both ways. Identical output. I used the native x86_64 gcc and binutils on Linux, but any GNU toolchain should work the same.

author: georgian
author_rank: Regular Contributor
timestamp: November 11, 2020, 01:13:26 am
content: Quote from: brucehoult on November 11, 2020, 12:55:46 amThis is how i have it. The first 2 lines are different. I doubt that it will work like this. The EPROM (D27C210) takes 16bit word on the data lines. Might be good to changechar footounsigned short foo.Code:ubuntu@ubuntu:~/C$ cat rom_linkOUTPUT_FORMAT(ihex)MEMORY {rom : ORIGIN = 0, LENGTH = 2K}SECTIONS {.text : {} >rom}ubuntu@ubuntu:~/C$ cat romdata.cchar foo[] = {1,2,3,4,5};ubuntu@ubuntu:~/C$ cat romdata:10000000040000001000000005000000474E5500ED:10001000020000C004000000030000000000000017:050020000102030405CC:00000001FFubuntu@ubuntu:~/C$Code:ubuntu@ubuntu:~/C$ gcc -vUsing built-in specs.COLLECT_GCC=gccCOLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapperOFFLOAD_TARGET_NAMES=nvptx-none:hsaOFFLOAD_TARGET_DEFAULT=1Target: x86_64-linux-gnuConfigured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-17ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-HskZEa/gcc-9-9.3.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnuThread model: posixgcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)ubuntu@ubuntu:~/C$

author: T3sl4co1l
author_rank: Super Contributor
timestamp: November 11, 2020, 07:50:23 am
content: Quote from: georgian on November 10, 2020, 09:59:51 pmThat's the best part, you have GB of RAM available. From which the browser might complain after a few hundred megs. Passing around big arrays is child's play, even with all the interpreter/GC/profiling overhead.Easily done in C too of course, whether via malloc or memory-mapping a file. Let the OS handle the heavy lifting for you.Tim

author: brucehoult
author_rank: Super Contributor
timestamp: November 11, 2020, 10:38:04 am
content: Quote from: georgian on November 11, 2020, 01:13:26 amThat's entirely up to you. Only you know what data you want in the ROM. If you use short then you'll have to make sure you get little-endian vs big-endian correct for your ROM application. If you specify the bytes explicitly (using char) then you know it's correct.I don't know where those first two lines come from. You didn't show the command(s) you used to create romdata from romdata.c

author: S. Petrukhin
author_rank: Super Contributor
timestamp: November 11, 2020, 11:14:58 pm
content: Quote from: georgian on November 10, 2020, 09:59:51 pmI wrote you a simple EPROM content generator. Just replace printf with write to file procedure to the eeprom.bin file.

author: georgian
author_rank: Regular Contributor
timestamp: November 12, 2020, 09:32:41 pm
content: So far so good. Thank you all for suggestions. I ended up using the following code. It just works. It outputs a binary file that the minipro accepts and I'm happy with it.Code:#include<stdlib.h>#include<stdio.h>unsigned short finalResult();int split(int length);FILE *ptr;unsigned short buffer;unsigned int tmp = 0;int digits; //Array to store each digit.int main() {//fill the bufferfor (unsigned int i = 0; i < 65536; i++) {split(i);tmp = finalResult();if (i > 255) {tmp = 0;}buffer = tmp;}for (unsigned int i = 0; i < 258; i++) {tmp = buffer;printf("Address: %d\tValue HEX: 0x%X \tValue DEC: %d\n", i, tmp, tmp);}//size_t n = sizeof(buffer)/sizeof(buffer);ptr = fopen("rom.bin","wb");fwrite(buffer, 2, 65536, ptr);fflush(ptr);fclose(ptr);return 0;}//Split the number into 3 digits and store them in an array.int split(int input) {int pos = 0;while (input > 0) {int digit = input % 10;digits = digit; pos++;input /= 10;}return pos;}//Concatenate the digits each into it's right position.unsigned short finalResult() {unsigned short res = ((digits << 8) | digits << 4) | digits;return res;}However another problem has arrived. Before waiting for the minipro programmer to come, I made an arduino sketch for an Atmega32 in order to program the EPROM. It works fine but at the address 0 it writes 0xff instead of 0 and I have no idea why... All other addresses and data is fine. The code is messy.Again, many thanks!Code:#ifndef F_CPU#define F_CPU 8000000L#endif//Necessary librarys.#include <avr/io.h>#include <util/delay.h>#include <stdbool.h>//#include <"uart.h">//Port definitions#define PORT_ADDRESS PORTC#define DATA_PORT_LOW PORTA#define DATA_PORT_HIGH PORTB#define VPP_EN PD6#define OE PD5#define CE PD4#define PGM PD3//Variablesuint8_t FIRST_ADDRESS = 0x00;uint8_t LAST_ADDRESS = 0xff;uint16_t data= 0;uint16_t buffer;void enterProgramMode();void exitProgramMode();void writeData(uint8_t address, uint16_t data);uint16_t readData(uint8_t address);unsigned int split(uint16_t input);uint16_t finalResult();void setup() {Serial.begin(115200);//Configure pinsDDRC = 0xff; //All pins as outputDDRA = 0xff;DDRB |= 1 << PB3 | 1 << PB2 | 1 << PB1 | 1<< PB0; //Only the first 4bits are usedDDRD |= 1 << VPP_EN | 1 << OE | 1 << CE | 1 << PGM; //Set PD6 to PD3 as outputPORT_ADDRESS = 0;DATA_PORT_LOW = 0;PORTD = 0;_delay_ms(1000);Serial.print("Enter programming mode\n");enterProgramMode();_delay_ms(500);for (uint16_t i = FIRST_ADDRESS; i < LAST_ADDRESS + 1; i++) {split(i);data = finalResult();writeData(i, data);Serial.print(i);Serial.print(" ");Serial.print(data);Serial.print(" ");Serial.print(DATA_PORT_LOW);Serial.println();_delay_ms(10);}_delay_ms(500);exitProgramMode();//Usless code starts here....enterReadMode();for (uint16_t i = FIRST_ADDRESS; i < LAST_ADDRESS + 1; i++) {data = readData(i);Serial.print(i);Serial.print(" ");Serial.print(data);Serial.print(" ");Serial.print(PINB, BIN);Serial.print(" ");Serial.print(PINA, BIN);Serial.println();_delay_ms(10);}Serial.println("DONE!");//return 0;}void enterProgramMode() {PORTD |= 1 << VPP_EN | 1 << CE;PORTD &= ~(1 << OE);DATA_PORT_LOW = 0;DATA_PORT_HIGH = 0;}//Usless, dosen't work for now.void enterReadMode() {DDRA &= 0;PORTA = 0xff;DDRB &= ~ (1 << PORTB3 | 1 << PORTB2 | 1 << PORTB1 | 1 << PORTB0);PORTB |= (1 << PORTB3 | 1 << PORTB2 | 1 << PORTB1 | 1 << PORTB0);PORTD = 0;PORTD |= 1 << PORTD5 | 1 << PORTD4;}void exitProgramMode() {PORTD &= ~(1 << VPP_EN | 1 << CE);PORTD |= 1 << OE;}void writeData(uint8_t address, uint16_t data) {uint8_t dataL, dataH;dataH = data >> 8;dataL = data & 0xff;PORT_ADDRESS = address; //Set the address_delay_us(100);DATA_PORT_LOW = dataL; //Write lower 8bitDATA_PORT_HIGH = dataH; //Write upper 4bit (or whats left)PORTD |= (1 << PGM); //Toggle PGM pin_delay_us(105);PORTD &= ~ (1 << PGM);_delay_ms(50);}//usless function. Dosen't work.uint16_t readData(uint8_t address) {uint8_t dataL;uint8_t dataH;uint16_t data;PORTC = address;_delay_ms(20);dataL = PINA;dataH = PINB;data = (dataH << 8) | (dataL & 0xff);//data |= dataL & 0xff;return data;}unsigned int split(uint16_t input) {unsigned int pos = 0;while (input > 0) {int digit = input % 10;buffer = digit; pos++;input /= 10;}return pos;}uint16_t finalResult() {uint16_t res = ((buffer << 8) | buffer << 4) | buffer;return res;}void loop() {// put your main code here, to run repeatedly:}

author: T3sl4co1l
author_rank: Super Contributor
timestamp: November 13, 2020, 07:56:15 am
content: Does the EPROM datasheet guarantee that a 105us write cycle will suffice?Often they follow a procedure to partially write, verify, and continue writing until verified.Tim

author: Rue_mohr
author_rank: Newbie
timestamp: November 13, 2020, 03:42:39 pm
content: This looks good. I have not tried to do 16 bits yet, but if you write your output to a file in binary, you should be fine.#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>int main() {int fd;int n;if ((fd = open ( "output.bin", O_CREAT|O_WRONLY|O_TRUNC, 00666)) == -1) {printf("Cant open output file\n");return 0;}//-T-e-s-t- Production routinefor (int i = 0; i < 256; i++) {split(i);printf("Address: %d\tValue HEX: 0x%X \tValue DEC: %d\n", i, finalResult(),n = finalResult());write(fd, &n, 2);}close(fd);return 0;}when you write the ROM, use a command *like*./minipro -p 2764@DIP28 -s -w /files/programming/c/lcdmessage/output.binminipro does not mention that they support files in binary format.If you want, I have a way of achiving your goal with less chips, if you are interested, please inquire.Rue

author: georgian
author_rank: Regular Contributor
timestamp: November 13, 2020, 08:52:01 pm
content: Quote from: T3sl4co1l on November 13, 2020, 07:56:15 amIn the datasheet, page 5 it says it's enough. I added more delays and still the same. At address 0, the Atmega writes 0xff in the EPROM or it dose't write anything at all at that address. other addresses are fine.OE,CE, and PGM are inverted with an cd4049. Instead of 12V on the VPP, I only have around 10V because of the way i switch the voltage on the pin using an optocopler.Datasheet:https://datasheet.octopart.com/D27C210-200V10-Intel-datasheet-139899587.pdfhexdump:Code:0000000 ff ff 01 00 02 00 03 00 04 00 05 00 06 00 07 000000010 08 00 09 00 10 00 11 00 12 00 13 00 14 00 15 000000020 16 00 17 00 18 00 19 00 20 00 21 00 22 00 23 000000030 24 00 25 00 26 00 27 00 28 00 29 00 30 00 31 000000040 32 00 33 00 34 00 35 00 36 00 37 00 38 00 39 000000050 40 00 41 00 42 00 43 00 44 00 45 00 46 00 47 000000060 48 00 49 00 50 00 51 00 52 00 53 00 54 00 55 000000070 56 00 57 00 58 00 59 00 60 00 61 00 62 00 63 000000080 64 00 65 00 66 00 67 00 68 00 69 00 70 00 71 000000090 72 00 73 00 74 00 75 00 76 00 77 00 78 00 79 0000000a0 80 00 81 00 82 00 83 00 84 00 85 00 86 00 87 0000000b0 88 00 89 00 90 00 91 00 92 00 93 00 94 00 95 0000000c0 96 00 97 00 98 00 99 00 00 01 01 01 02 01 03 0100000d0 04 01 05 01 06 01 07 01 08 01 09 01 10 01 11 0100000e0 12 01 13 01 14 01 15 01 16 01 17 01 18 01 19 0100000f0 20 01 21 01 22 01 23 01 24 01 25 01 26 01 27 010000100 28 01 29 01 30 01 31 01 32 01 33 01 34 01 35 010000110 36 01 37 01 38 01 39 01 40 01 41 01 42 01 43 010000120 44 01 45 01 46 01 47 01 48 01 49 01 50 01 51 010000130 52 01 53 01 54 01 55 01 56 01 57 01 58 01 59 010000140 60 01 61 01 62 01 63 01 64 01 65 01 66 01 67 010000150 68 01 69 01 70 01 71 01 72 01 73 01 74 01 75 010000160 76 01 77 01 78 01 79 01 80 01 81 01 82 01 83 010000170 84 01 85 01 86 01 87 01 88 01 89 01 90 01 91 010000180 92 01 93 01 94 01 95 01 96 01 97 01 98 01 99 010000190 00 02 01 02 02 02 03 02 04 02 05 02 06 02 07 0200001a0 08 02 09 02 10 02 11 02 12 02 13 02 14 02 15 0200001b0 16 02 17 02 18 02 19 02 20 02 21 02 22 02 23 0200001c0 24 02 25 02 26 02 27 02 28 02 29 02 30 02 31 0200001d0 32 02 33 02 34 02 35 02 36 02 37 02 38 02 39 0200001e0 40 02 41 02 42 02 43 02 44 02 45 02 46 02 47 0200001f0 48 02 49 02 50 02 51 02 52 02 53 02 54 02 55 020000200 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff*0020000

author: Nominal Animal
author_rank: Super Contributor
timestamp: November 13, 2020, 09:56:43 pm
content: How about using two Padauk PMS152-S16 (datasheet;$0.08 at LCSC.com) instead, programming them using thefree-pdktoolchain and hardware programmer?Both chips are connected to the same 8 inputs, and 5 of the 10 outputs. (The two most significant bits of the 12-bit output value are always zero.)This leaves an extra pin for latch/update, if you want/need one. (Or, you can extend to 9 bit input and 12-bit output, by supplying only the 7 most significant input bits to the chip providing the most significant 7 output bits.)The programs themselves are trivial, except that you'll probably want to construct the input and output bit by bit, so you can get an optimal pin layout for your use case. (In particular, the least significant bit of the input always matches the least significant bit of the output, so at most you need 127 look-up entries.)Each chip only consumes a couple of mA even running at 16 MHz; for this use case, you can use a much lower frequency, dropping the current consumption under 0.1mA.

author: georgian
author_rank: Regular Contributor
timestamp: November 13, 2020, 10:01:58 pm
content: Quote from: Nominal Animal on November 13, 2020, 09:56:43 pmThis chips are really cheap, they are great for series production. As I read from datasheet they are OTP, one time programming. They are no use for me as i keep making mistakes and i'll need 100s of themThis isn't anything comercial, just me having too much free time now and trying to build/learn new things. Thank you anyway for the infos..

author: georgian
author_rank: Regular Contributor
timestamp: November 13, 2020, 10:11:18 pm
content: I got it right!Silly me forgot to connect the EPROM VCC pin to 5V. The breadboard I'm using has the VCC/GND rails split in the middle. Only the one rail for the EEPROM was left unconneted. Thats why the read function didn't work wellBut somehow it did work but not as expected. What should I do with the unused data/address pins? should they be pulled low or can they be left floating? the unused address pins are pulled low now, but the data unused data pins are left floating.EEPROM dump after programming.Code:0000000 00 00 01 00 02 00 03 00 04 00 05 00 06 00 07 000000010 08 00 09 00 10 00 11 00 12 00 13 00 14 00 15 000000020 16 00 17 00 18 00 19 00 20 00 21 00 22 00 23 000000030 24 00 25 00 26 00 27 00 28 00 29 00 30 00 31 000000040 32 00 33 00 34 00 35 00 36 00 37 00 38 00 39 000000050 40 00 41 00 42 00 43 00 44 00 45 00 46 00 47 000000060 48 00 49 00 50 00 51 00 52 00 53 00 54 00 55 000000070 56 00 57 00 58 00 59 00 60 00 61 00 62 00 63 000000080 64 00 65 00 66 00 67 00 68 00 69 00 70 00 71 000000090 72 00 73 00 74 00 75 00 76 00 77 00 78 00 79 0000000a0 80 00 81 00 82 00 83 00 84 00 85 00 86 00 87 0000000b0 88 00 89 00 90 00 91 00 92 00 93 00 94 00 95 0000000c0 96 00 97 00 98 00 99 00 00 01 01 01 02 01 03 0100000d0 04 01 05 01 06 01 07 01 08 01 09 01 10 01 11 0100000e0 12 01 13 01 14 01 15 01 16 01 17 01 18 01 19 0100000f0 20 01 21 01 22 01 23 01 24 01 25 01 26 01 27 010000100 28 01 29 01 30 01 31 01 32 01 33 01 34 01 35 010000110 36 01 37 01 38 01 39 01 40 01 41 01 42 01 43 010000120 44 01 45 01 46 01 47 01 48 01 49 01 50 01 51 010000130 52 01 53 01 54 01 55 01 56 01 57 01 58 01 59 010000140 60 01 61 01 62 01 63 01 64 01 65 01 66 01 67 010000150 68 01 69 01 70 01 71 01 72 01 73 01 74 01 75 010000160 76 01 77 01 78 01 79 01 80 01 81 01 82 01 83 010000170 84 01 85 01 86 01 87 01 88 01 89 01 90 01 91 010000180 92 01 93 01 94 01 95 01 96 01 97 01 98 01 99 010000190 00 02 01 02 02 02 03 02 04 02 05 02 06 02 07 0200001a0 08 02 09 02 10 02 11 02 12 02 13 02 14 02 15 0200001b0 16 02 17 02 18 02 19 02 20 02 21 02 22 02 23 0200001c0 24 02 25 02 26 02 27 02 28 02 29 02 30 02 31 0200001d0 32 02 33 02 34 02 35 02 36 02 37 02 38 02 39 0200001e0 40 02 41 02 42 02 43 02 44 02 45 02 46 02 47 0200001f0 48 02 49 02 50 02 51 02 52 02 53 02 54 02 55 020000200 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff*0020000

author: brucehoult
author_rank: Super Contributor
timestamp: November 13, 2020, 11:34:52 pm
content: Quote from: georgian on November 13, 2020, 10:01:58 pmThere is a version with flash. It's more expensive, of course, but you only need one of them :-)

author: Nominal Animal
author_rank: Super Contributor
timestamp: November 13, 2020, 11:36:04 pm
content: When writing the EPROM, I'd add 10k resistors to ground for each unused address and data pin.When using the EPROM, I'd connect unused address pins to ground, and leave unused data pins floating.By the way, here's the Arduino sketch I'd use to write the EPROM. This uses arbitrary pins, and waits for Enter (from Arduino serial monitor) before writing the data. I wrote it according to the datasheet you linked, and it compiles, but is otherwise untested. It does the full write-verify-rewrite-if-necessary thing, too, and reports each address written to the serial monitor. You do need to edit the pin numbers, and whether the logic (EPROM_ constants) match your circuit.Code:// Chip enable, output enable, program, and programming voltage control pins#define EPROM_CE 1#define EPROM_OE 2#define EPROM_PGM 3#define EPROM_PDG 4// Logic used for the above pins#define EPROM_CE_LOW LOW#define EPROM_CE_HIGH HIGH#define EPROM_OE_LOW LOW#define EPROM_OE_HIGH HIGH#define EPROM_PGM_LOW LOW#define EPROM_PGM_HIGH HIGH#define EPROM_PDG_12V LOW#define EPROM_PDG_5V HIGH// Address pins#define EPROM_A0 5#define EPROM_A1 6#define EPROM_A2 7#define EPROM_A3 8#define EPROM_A4 9#define EPROM_A5 10#define EPROM_A6 11#define EPROM_A7 12// Data pins#define EPROM_D0 13#define EPROM_D1 14#define EPROM_D2 15#define EPROM_D3 16#define EPROM_D4 17#define EPROM_D5 18#define EPROM_D6 19#define EPROM_D7 20#define EPROM_D8 21#define EPROM_D9 22// Write one word. Returns true if successful, false if failed.static bool eprom_program(uint8_t address, uint16_t data){const unsigned char data_hi = data >> 8,data_lo = data;unsigned char retries = 25;unsigned char lo, hi;// Make sure EPROM is in standby, outputs disabled.digitalWrite(EPROM_CE, EPROM_CE_LOW);digitalWrite(EPROM_OE, EPROM_OE_LOW);// Set address.digitalWrite(EPROM_A0, (address & 1) ? HIGH : LOW);digitalWrite(EPROM_A1, (address & 2) ? HIGH : LOW);digitalWrite(EPROM_A2, (address & 4) ? HIGH : LOW);digitalWrite(EPROM_A3, (address & 8) ? HIGH : LOW);digitalWrite(EPROM_A4, (address & 16) ? HIGH : LOW);digitalWrite(EPROM_A5, (address & 32) ? HIGH : LOW);digitalWrite(EPROM_A6, (address & 64) ? HIGH : LOW);digitalWrite(EPROM_A7, (address & 128) ? HIGH : LOW);while (1) {// Set output data.pinMode(EPROM_D0, OUTPUT); digitalWrite(EPROM_D0, (data_lo & 1) ? HIGH : LOW);pinMode(EPROM_D1, OUTPUT); digitalWrite(EPROM_D1, (data_lo & 2) ? HIGH : LOW);pinMode(EPROM_D2, OUTPUT); digitalWrite(EPROM_D2, (data_lo & 4) ? HIGH : LOW);pinMode(EPROM_D3, OUTPUT); digitalWrite(EPROM_D3, (data_lo & 8) ? HIGH : LOW);pinMode(EPROM_D4, OUTPUT); digitalWrite(EPROM_D4, (data_lo & 16) ? HIGH : LOW);pinMode(EPROM_D5, OUTPUT); digitalWrite(EPROM_D5, (data_lo & 32) ? HIGH : LOW);pinMode(EPROM_D6, OUTPUT); digitalWrite(EPROM_D6, (data_lo & 64) ? HIGH : LOW);pinMode(EPROM_D7, OUTPUT); digitalWrite(EPROM_D7, (data_lo & 128) ? HIGH : LOW);pinMode(EPROM_D8, OUTPUT); digitalWrite(EPROM_D8, (data_hi & 1) ? HIGH : LOW);pinMode(EPROM_D9, OUTPUT); digitalWrite(EPROM_D9, (data_hi & 2) ? HIGH : LOW);// Enable chip.digitalWrite(EPROM_CE, EPROM_CE_HIGH);delayMicroseconds(2);// Pulse PGM.digitalWrite(EPROM_PGM, EPROM_PGM_HIGH);delayMicroseconds(100);digitalWrite(EPROM_PGM, EPROM_PGM_LOW);delayMicroseconds(2);// Change data lines to inputs.pinMode(EPROM_D0, INPUT);pinMode(EPROM_D1, INPUT);pinMode(EPROM_D2, INPUT);pinMode(EPROM_D3, INPUT);pinMode(EPROM_D4, INPUT);pinMode(EPROM_D5, INPUT);pinMode(EPROM_D6, INPUT);pinMode(EPROM_D7, INPUT);pinMode(EPROM_D8, INPUT);pinMode(EPROM_D9, INPUT);// Enable EPROM outputs; provides verification.digitalWrite(EPROM_OE, EPROM_OE_HIGH);delayMicroseconds(2);lo = (digitalRead(EPROM_D0) == HIGH) ? 1 : 0+ (digitalRead(EPROM_D1) == HIGH) ? 2 : 0+ (digitalRead(EPROM_D2) == HIGH) ? 4 : 0+ (digitalRead(EPROM_D3) == HIGH) ? 8 : 0+ (digitalRead(EPROM_D4) == HIGH) ? 16 : 0+ (digitalRead(EPROM_D5) == HIGH) ? 32 : 0+ (digitalRead(EPROM_D6) == HIGH) ? 64 : 0+ (digitalRead(EPROM_D7) == HIGH) ? 128 : 0;hi = (digitalRead(EPROM_D8) == HIGH) ? 1 : 0+ (digitalRead(EPROM_D9) == HIGH) ? 2 : 0;digitalWrite(EPROM_OE, EPROM_OE_LOW);// Put chip in standby.digitalWrite(EPROM_CE, EPROM_CE_LOW);delayMicroseconds(2);// Verified correctly?if (lo == data_lo && hi == data_hi)return true;// No more retries?if (!retries--)return false;}}void setup() {Serial.begin(115200);// Make sure EPROM is in Standby modepinMode(EPROM_CE, OUTPUT);digitalWrite(EPROM_CE, EPROM_CE_LOW);// Make sure programming voltage is OFF (5V)pinMode(EPROM_PDG, EPROM_PDG_5V);// EPROM data output is disabledpinMode(EPROM_OE, OUTPUT);digitalWrite(EPROM_OE, HIGH);// EPROM is not in program modepinMode(EPROM_PGM, OUTPUT);digitalWrite(EPROM_PGM, HIGH);// Address lines are always outputs.pinMode(EPROM_A0, OUTPUT);pinMode(EPROM_A1, OUTPUT);pinMode(EPROM_A2, OUTPUT);pinMode(EPROM_A3, OUTPUT);pinMode(EPROM_A4, OUTPUT);pinMode(EPROM_A5, OUTPUT);pinMode(EPROM_A6, OUTPUT);pinMode(EPROM_A7, OUTPUT);}void loop() {uint16_t addr;int c;uint8_t h0, h1, h2;// Wait for USB connection, if native USB MCU (Leonardo etc.)while (!Serial);delay(1000);// Consume all pending serial input.while (Serial.available())Serial.read();// Output the prompt.Serial.println(F("Press Enter when ready to write ROM."));Serial.flush();// Consume serial input until newline.do {c = Serial.read();} while (c != '\n' && c != '\r');Serial.println(F("Writing EPROM."));Serial.flush();digitalWrite(EPROM_PDG, EPROM_PDG_12V);delayMicroseconds(2);// Data construction loops.addr = 0;for (h2 = 0; h2 < 10; h2++) {for (h1 = 0; h1 < 10; h1++) {for (h0 = 0; h0 < 10; h0++) {if (addr < 256) {const uint16_t value = h0 | (h1 << 4) | (((uint16_t)h2) << 8);Serial.print(addr, DEC);if (eprom_program(addr, value)) {Serial.println(F(": OK"));Serial.flush();addr++;} else {Serial.println(F(": Failed"));Serial.flush();addr = 257;}}}}}digitalWrite(EPROM_PDG, EPROM_PDG_5V);if (addr == 256) {Serial.println(F("EPROM written successfully."));} else {Serial.println(F("EPROM write failed."));}Serial.flush();}

author: Nominal Animal
author_rank: Super Contributor
timestamp: November 14, 2020, 12:00:38 am
content: Quote from: brucehoult on November 13, 2020, 11:34:52 pmYes, the Padauk PFS154-S16, which costs$0.10 at LCSC, although you must buy them in sets of five. It's not exact equivalent to the OTP one, but is programmable using the free tools, and I guess $0.20 (for two) is still cheap enough...Of course, one must also get/build theprogrammer. LCSC seems to be out of STM32F072C8T6's, so one would have to source those from Digikey/Mouser/etc.

author: brucehoult
author_rank: Super Contributor
timestamp: November 14, 2020, 12:23:11 am
content: Since you're using the runtime-dispatch-on-pin digitalWrite() anyway I'd shorten that program a ton by using:Code:char eprom_a[] = {5, 6, 7, 8, 9, 10, 11, 12};char eprom_d[] = {13, 14, 15, 16, 17, 18, 19, 20, 21, 22};... and then looping over them instead of unrolling. It'll be slower, but not perceptibly.Code:// Set address.for (int i=0; i<8; ++i) digitalWrite(eprom_a, (address & (1 << i)) ? HIGH : LOW);Etc.(I'm sure you know this .. it's for the OP)

author: Nominal Animal
author_rank: Super Contributor
timestamp: November 14, 2020, 01:24:50 am
content: Quote from: brucehoult on November 14, 2020, 12:23:11 amThe difference is huge on AVRs using e.g. Teensyduino, as theredigitalWrite()simplifies to a single instruction if the pin and state are literal constants, three if the pin is a literal constant. The array/variable version (including when pin numbers are declared asconst intinstead of macros) uses the slow Arduino jump table approach.The actual reason for using pin-specific macros, however, is that it makes it much easier to compare the code settings to the breadboard or PCB circuit. So much so that if I were to change the code to use arrays instead, I'd put the macros, not direct pin numbers, in the array initializer.(I knowIwould need to check the pins between the board and the codetwice, or I'd get at least one wrong. It might make the code longer than necessary, but it would for sure help me get the entire project right. I don't know whether others need that sort of thing, though.)If having the pins change state as close to simultaneously as possible was important, then I'd use a different approach, shadowing theNoutput pin state registers. Each data and address bit would correspond to a constant mask (ofNbytes), applied iff the corresponding bit is set. TheNoutput registers take one cycle to set each, so on a 16 MHz AVR, the transition would take 250ns if the pins are across four ports; or 188ns if the pins are across only three ports. Constructing the new port state would take a couple of dozen cycles, though.

author: brucehoult
author_rank: Super Contributor
timestamp: November 14, 2020, 02:12:16 am
content: Quote from: Nominal Animal on November 14, 2020, 01:24:50 amIn this case, to get speed you probably needed:Code:if (address & 1) digitalWrite(EPROM_A0, HIGH) else digitalWrite(EPROM_A0, LOW);if (address & 2) digitalWrite(EPROM_A1, HIGH) else digitalWrite(EPROM_A1, LOW);:Plus I'd write a macro so I could write:Code:SET_BITPIN(address, EPROM_A, 0);SET_BITPIN(address, EPROM_A, 1);:Or write some Perl/Python/C to generate it. (Oh how I miss LISP macros when I'm programming in something lesser...)

author: Rue_mohr
author_rank: Newbie
timestamp: November 14, 2020, 07:00:46 am
content: always ground unused inputs!congraduations!

author: Nominal Animal
author_rank: Super Contributor
timestamp: November 14, 2020, 07:21:30 am
content: Quote from: brucehoult on November 14, 2020, 02:12:16 amWell, not really... this is avr-gcc, after all. WhenEPROM_A0etc. are literal constants, and optimizations are enabled, using the Teensyduino AVR digitalWrite(),digitalWrite(EPROM_A0, (address & 1) ? HIGH : LOW);digitalWrite(EPROM_A1, (address & 2) ? HIGH : LOW);digitalWrite(EPROM_A2, (address & 4) ? HIGH : LOW);digitalWrite(EPROM_A3, (address & 8) ? HIGH : LOW);andif (address & 1) digitalWrite(EPROM_A0, HIGH); else digitalWrite(EPROM_A0, LOW);if (address & 2) digitalWrite(EPROM_A1, HIGH); else digitalWrite(EPROM_A1, LOW);if (address & 4) digitalWrite(EPROM_A2, HIGH); else digitalWrite(EPROM_A2, LOW);if (address & 8) digitalWrite(EPROM_A3, HIGH); else digitalWrite(EPROM_A3, LOW);do compile to the same code – SBRS/SBRC (Skip if Bit in Register is Set/Cleared), RJMP, SBI (Set Bit in I/O register) in one path, and CBI (Clear Bit in I/O register), and a RJMP in SBI or CBI path.The core Arduino AVRdigitalWrite()is much slower, as it does not do that sort of optimization at all.On say an ATmega32u4, one can useCode:#define DATA_0 D,3#define DATA_1 D,2#define DATA_2 D,1#define DATA_3 D,0#define DATA_4 D,4#define DATA_5 C,6#define DATA_6 D,7#define DATA_7 E,6#define DATA_8 B,4#define DATA_9 B,5#define ADDR_0 F,4#define ADDR_1 F,5#define ADDR_2 F,6#define ADDR_3 F,7#define ADDR_4 B,1#define ADDR_5 B,3#define ADDR_6 B,2#define ADDR_7 B,6// Helper macros#define MERGE2_(a, b) a ## b#define MERGE2(a, b) MERGE2_(a, b)#define SET_(prefix,name,bit) (MERGE2(prefix,name) |= 1 << bit)#define SET(...) SET_(__VA_ARGS__)static volatile unsigned char high_B = 0,high_C = 0,high_D = 0,high_E = 0,high_F = 0;void set_outputs(const uint8_t addr, const uint16_t data){unsigned char port_B, port_C, port_D, port_E, port_F;port_B = high_B;port_C = high_C;port_D = high_D;port_E = high_E;port_F = high_F;if (addr & 1) SET(port_, ADDR_0);if (addr & 2) SET(port_, ADDR_1);if (addr & 4) SET(port_, ADDR_2);if (addr & 8) SET(port_, ADDR_3);if (addr & 16) SET(port_, ADDR_4);if (addr & 32) SET(port_, ADDR_5);if (addr & 64) SET(port_, ADDR_6);if (addr & 128) SET(port_, ADDR_7);if (data & 1) SET(port_, DATA_0);if (data & 2) SET(port_, DATA_1);if (data & 4) SET(port_, DATA_2);if (data & 8) SET(port_, DATA_3);if (data & 16) SET(port_, DATA_4);if (data & 32) SET(port_, DATA_5);if (data & 64) SET(port_, DATA_6);if (data & 128) SET(port_, DATA_7);if (data & 256) SET(port_, DATA_8);if (data & 512) SET(port_, DATA_9);PORTB = port_B;PORTC = port_C;PORTD = port_D;PORTE = port_E;PORTF = port_F;}which sets all data and output pins within five clock cycles (313 ns at 16 MHz), taking about 50 cycles (3.13 µs at 16 MHz) or so, total. The pin order is completely arbitrary, and won't affect the speed. Thehigh_Xvariables need to "shadow" the port registers, containing 1 for non-address/data output pins that should stay high, as well as for input pins where the internal pullup should be enabled. To be any faster, one needs to rearrange the address and data pins to match the registers. (These can be found in the microcontroller schematics, or in the Arduino internal headers for that board.)Unfortunately, this faster method does not play nicely with Arduino libraries, becausedigitalWrite(non-address/data-pin, HIGH/LOW)andpinMode(any-pin, INPUT/INPUT_PULLUP)do not update the "shadow" values, so it is only really useful if one writes AVR code on bare metal, i.e. using avr-gcc and avr-libc, without external libraries.(I do not recommend using this faster method, though. I just wanted to show what I was talking about earlier, if the pins should transition close together, but one wants to use arbitrary pins for each bit.)

author: westfw
author_rank: Super Contributor
timestamp: November 14, 2020, 11:16:50 am
content: I would have been lazy and attacked your C program output with some editor macros to convert it to text that looked like a C structure definition with a .section attribute, and then used the standard compiler tools (gcc + objcopy, for gcc) to output just that section to a .hex file.(or, you know, objcopy would have taken a raw binary file and output a .hex as well, I guess.)

author: georgian
author_rank: Regular Contributor
timestamp: November 14, 2020, 12:57:18 pm
content: Quick update. I got it all working. I will post the final improved code that you guys suggested. Thank you all for all your support.https://youtu.be/_Y2V8trDlc0

author: S. Petrukhin
author_rank: Super Contributor
timestamp: November 15, 2020, 11:34:27 am
content: Quote from: georgian on November 12, 2020, 09:32:41 pmAfter erasing the EEPROM, all cells contain 0xFF. Your programmer starts writing from address 1, skips 0, and so there remains 0xFF.