Prox / RFID
Ladder Logic
[interfacing] †
Tube Joints
Key Code From Photo
SolveSpace (3d CAD)
SketchFlat (2d CAD)
Resume / Consulting
Contact Me

LDmicro Forum - LdMicro32 on Github

(you are viewing a thread; or go back to list of threads)

LdMicro32 on Github (by José GILLES)
Hi everybody

As the usual developpers of ldmicro have not manifested any interest for my improvements concerning ARMs, AVRs, SPI, I2C, bugs, menus, and so on...
I have decided to create a fork on Github to offer my version
of the software, named LdMicro32 (because of 32 bit ARMs) and starting at version 5.0

I you want to have a look at the sources, try the executables, with examples and libraries for ARMs and AVRs, jump to:


I hope that the usual developpers will have a look at it and integrate at least some of these improvements in a next version of ldmicro !

Enjoy it (or not) and let me know (if you want).

Best regards
J. Gilles
Wed Jan 2 2019, 17:16:31
(no subject) (by Luisin)
Hello could be Ldmicro in Spanish language.

Thank you.
Thu Jan 3 2019, 00:07:27
(no subject) (by Ziggy)

The usual developers ( of late Ihor) has been absent from the forum.

It may be that other more pressing issues have caught up with him, do not be disappointed if You get no immediate response.

In the mean time You keep on keeping on. I could not do what You are doing.

I have not tried Your offering in anger so I can not make any meaningful comments other than to repeat my comment in another post; my preference is for LDmicro to remain a "black box" self contained tool.

I am sure that AVRGCC compiler will produce tighter code but then again I dont mind giving up some code performance in exchange for simplicity; look at Arduino tradeoff. I would however object to LDmicro being similar to Arduino bloat

And now a quetion about the PWM options in the library.

The library addresses two items 8 bit and 10 bit performance

// modify duty
void PWM_Set(int canal, unsigned percent, int resol)
unsigned value= 0;
if (resol == 8)
value= (255 * percent) / 100; // PWM 8 bit
value= (1023 * percent) / 100; // PWM 10 bit

if (canal == 0x00) OCR0= value;
if (canal == 0x1A) OCR1A= value;
if (canal == 0x1B) OCR1B= value;
if (canal == 0x02) OCR2= value;

Could one modify the library readily to accept either 8 bit or ten bit PWM vallues rather than percentage values?
In fact intstead of inputing percentage value a promil value could be the higher resolution mode in ten bit mode?
Thu Jan 3 2019, 02:14:54
Traducion al Español (por José GILLES) (by Calubert)
Te adjunto como hacer la copilacion para ARM-STM32
Thu Jan 3 2019, 13:37:46, download attachment HowTo-v2_ ES.txt
(no subject) (by José GILLES)
Thanks for your interest

To Ziggy:

I'm not really disappointed ; I have successfully adapted ldmicro to my own needs (ARMs, SPI, I2C) and a bit more for AVRs users, without knowing if they intend to use it or not.

Concerning PWM lib, that's an advantage of my method using external C libraries: you can adapt libraries to your own needs without modifying ldmicro...
In your case, parameter percent is transmitted "as is", with just a warning if not between 0 and 100 ; so you can enter in ldmicro values in [0,255] or [0,1023] and ignore the warning, provided that you adapt your PWM libray to write directly value=percent to OCRX register !
Someone could (almost) transform a SPI into a second UART by rewriting SPI lib...

To Calubert:

Muchas gracias por la traduccion !
I have uploaded your file as ComoHacer.txt on Github.

I'd like to add a spanish version of ldmicro32, but I need some help to translate a bunch of english messages: I have gathered ALL the menus titles and displayed messages in ldmicro, but only a part is translated in earlier version.
If someone could translate remaining ones from english to spanish, I could generate a full spanish version...

To Luisin:

See just above !

Thu Jan 3 2019, 15:33:38
(no subject) (by Luisin)
Thank you all.
Thu Jan 3 2019, 15:49:28
(no subject) (by Alex)
could you add atmega2560 for i2c?
Sat Jan 5 2019, 21:56:14
(no subject) (by José GILLES)
It's done, yet ! But not tested.
Sun Jan 6 2019, 03:43:16
Traducir al español (by Calubert)
José GILLES; Si meló mandas la documentación en ingles TXT yo te la pasare al Español (Castellano)
mi correo [email protected] y si fuera de maximizado grande el archivo te puedo abrir un canal en Tecnocalubert.com en intranet.

José GILLES; If you tried to send the documentation in English, I will pass it to Spanish (Spanish)
my email [email protected] and if the file is maximized, I can open a channel on Tecnocalubert.com on the intranet.

José GILLES; Si vous avez envoyé la documentation en anglais TXT, je la transmettrai en espagnol (espagnol)
mon email [email protected] et si le fichier est agrandi, je peux ouvrir un canal sur Tecnocalubert.com sur l'intranet.
Sun Jan 6 2019, 07:40:26
(no subject) (by Alex)
thanks a lot José GUILLES
Sun Jan 6 2019, 07:58:48
(no subject) (by Alex)
hello i have a problem, i made changes to José GUILLES I2C example with ds1307, instead of numeric display i used a serial lcd, only variable called "sec" is displayed because of ladder program example, it worked ok, only "sec" was displayed in serial lcd, it was simulated in proteus, but after many tests sec was not displayed anymore instead there was another strange variable, maybe it is a simulation problem, it has happened to me in the past, simulation was wrong but real life was perfectly normal, but i would like to know first if i am doing ok in ladder program, i attach ladder , see video please:

Sun Jan 6 2019, 18:49:03, download attachment test-i2c.ld
(no subject) (by Alex)
i´ll test latter i real life but i want to know first if ladder is ok
Sun Jan 6 2019, 18:50:38
(no subject) (by Alex)
i tested in real life, first i made a ladder that only works with ldmicro, it has a variable "sec"(second) with arduino uno + serial lcd interface i displayed it and for making sure that lcd works ok, then i added ds3231 (0x68) and it prints strange values, my ds3231 has same reg 0x68 like ds1307, watch video please:

Mon Jan 7 2019, 02:13:50
(no subject) (by José GILLES)
To Calubert:

Thanks for your offer to translate english to spanish.
I'll prepare the file and send it to you.

To Alex:

I don't really undestand the pb on videos but I'll make some more trials and we'll probably solve it.
Mon Jan 7 2019, 09:16:21
(no subject) (by Alex)
thanks for your reply José GUILLES, in pb there are only the serial interface components for lcd, took from ldmicro wiki:


i attach a pdf image of my arduino + pb + ds3231 video
Mon Jan 7 2019, 20:03:54, download attachment arduino uno + serial lcd interface + ds3231.pdf
(no subject) (by José GILLES)
Hi Alex,

I have found the pb: in your I2C Read you have inverted adress (0x68) and register (0) fields !!!

I have wasted almost all the day to find that bloody mistake...
As I have reviewed my I2C library - thinking there was a pb in it - I noticed that prescale config for I2C clock was wrongly computed for AVRs (but it didn't prevent I2C from working).

Here's the new lib file to replace the old one.
I'll make an update on Github, also for ldmicro32.exe because a message was badly displayed in french version's config panel.

It should now work. Let me know.
Tue Jan 8 2019, 12:05:43, download attachment I2CLib.c
(no subject) (by Alex)
thanks a lot JOsé GUILLES i am really sorry for making such a dumb mistake, i´ll test new i2c lib in real life
Tue Jan 8 2019, 12:28:43
(no subject) (by Alex)
I corrected error as you said, tested again now with new i2c lib:


i´ll try yo add minutes and hours, is it possible to increase seconds or minutes or hours with an extrenal input button?
Tue Jan 8 2019, 13:14:50
(no subject) (by Alex)
i have added hours and minutes as i thought it would be,it looks pretty easy and intuitive, as ldmicro should be i guess :)

arduino uno + ds3231 + serial lcd interface clock:


i have some questions about it.

1) After i added a second i2c read function for minutes it appeared with i2c name "I2C1" then i added a third i2c function for hours it appeared with i2c name "I2C1" also, i changed to "I2C2" name, is that the correct way? then i made step 2

2) after i added the second i2c function for minutes everytime i added, edited or clicked 2 times on a function in ladder a ldmicro error message shows up, it says "invaled I2C name in ladder" then i changed all i2c names for sec, min and hour to just "I2C" and error mesage never appeared again, then why when i add a second i2c function it appears with "I2C1" name, it looks that when compiling if name is "I2C" for all o "I2C, I2C1 and I2C2" for each one it works ok also

3) there are few times when call flash MCU my bin file is deleted and i noticed that it happenes when i have my bootloader program running, is it because of that is not a big deal i can close bootloader and open again
Tue Jan 8 2019, 14:30:30
(no subject) (by José GILLES)
It begins to work fine !

1) Yes, you must use the same name for all I2C functions, "I2C" on AVRs, even if default name is I2C1 (for targets with several I2C buses) ; change it in the dialog boxes,

2) That's why you have (had) warning messages about your I2C names, if you use another one (Look at ldmicro Help-> Manual, part I2C)

3) I don't pretty understand the 3rd question: but if you have another programming software opened, I guess you must close it to run AvrDude ?

4) You can modify hour, min and seconds in your DS1307 by writing in the same registers with I2C function. Date is also available. Just beware that data are internally coded in BCD.

I'll post tomorrow a special I2C/LCD library which makes possible to access a LCD 16x2 display from ldmicro32 via I2C+IO-Expander (like arduino's 1602 module). I've juste tested it successfully.

Tue Jan 8 2019, 17:24:46
(no subject) (by Alex)
thanks for your reply José GUILLES, can´t wait to test lcd 16x2 via I2C+IO-Expander
Tue Jan 8 2019, 17:50:16
(no subject) (by José GILLES)
Required libraries to use I2C LCD Display on AVRs are available on my github:


Download new ldmicro32 zip file and extract avr libraries.
Replace all the libraries by newer ones.

And read LcdI2cLib.txt (in lib folder) to know how it works.

I have tested it OK on true AtMega16.
Wed Jan 9 2019, 06:00:44
(no subject) (by Alex)
thanks José GUILLES, before i make a bloody mistake... again, i recorded the steps i took for compiling via "call flashMcu" because it creates for me an empty "bin" file cpuld you please check what am i doing wrong?, i chahnged name libs to lib, watch video please:

Wed Jan 9 2019, 17:08:33
(no subject) (by Luisin)
Hello, you can create the hex file in a different way than with Atmel Studio, I follow the steps of HowTo-AVR.txt and I can not create the Hex file.

Thanks greetings.

Hola se puede crear el archivo hex de otra forma que no sea con Atmel Studio sigo los pasos de HowTo-AVR.txt y no consigo crear el archivo Hex.

Gracias un saludo.
Wed Jan 9 2019, 17:39:09
(no subject) (by José GILLES)
To Alex:

Your video is ugly... I can't really read texts...

But your bin directory remains empty because of a compiling error. This error is probably due to a bad file hierarchy in the project (The analysis of scrolling batch window would of course give the answer).

Here's attached my test ld file.
Put it in your usual working directory and just replace the old libs (*.c + *.h) in your "lib" subdirectory by the new ones in Libs\Avr of the zip file.
Don't forget to modify your I2C display address at the beginning of I2cLib.c

You don't need to change your flashMCU.bat

Then Compile AVR + flashMCU should work.
The hex program should write "Hello !" on the first line of the display and "0" on the second one.

To Luisin:

As you can see above, pbs can be of different kinds:
- bad file hierarchy
- bad path to compiler in flashMCU.bat
- bad compiler (which AvrStudio ?)

You must have:
1) LdMicro32 executable + flashMCU.bat modified in one directory
2) ld file in an(other) directory + lib subdirectory with AVR or ARM libs according to your target

If you can't make it work by following the Howto, make a good video as Alex and post it...

Thu Jan 10 2019, 04:38:14, download attachment i2c-lcd16x2.ld
(no subject) (by José GILLES)
For information, I have posted new files on Github, with a few
corrections (nothing critical) in ldmicro32.

I2C LCD Display 16x2 works on STM32 too and library is now available.

I don't forget spanish version, this week-end probably...

Thu Jan 10 2019, 17:24:28
(no subject) (by Alex)
in ladder.h generated file it says:

#include "lib\UsrLib.h"

#include "lib\I2cLib.h"

but in downloaded lib file it says: "I2CLib.h"

the letter C is in uppercase and letter c in ladder.h generated file is in lowercase, does it affects on something? i can´t generate hex.

there was another one ... lowercase and uppercase are important when calling and header file?

out of curiosity in UsrLib.c it says:

#include "..\ladder.h"

is it ok? shouldný it says:

#include "ladder.h"

just asking i am not an expert with c code
Thu Jan 10 2019, 22:34:37
(no subject) (by José GILLES)

C is a case sensitive language, except for a few things like includes ! So it dosn't matter here.

.. in ..\ladder.h means that ladder.h is in the directory above, and it should be the case because ladder.h is generated in project directory (with .ld) while libs are in lib subdirectory.

Does it work (as before) when you compile another simple ladder, without I2C ?

Can you stretch and scroll your compiling output (in black window), make a few screen shots so that I have a full vision of it, and post them ?
There must be "errors" somewhere. It should enable me to identify your pb.
Fri Jan 11 2019, 01:36:49
(no subject) (by bfwolf)
Hello José GILLES,

first of all, thank you very much for your work with ldMicro! ;-)

Using '\' in #include path is very problematic!
Please change your code-generator to use the '/' !!!
For example use #include "../ladder.h"

The '/' is working even in Windows since long ago and many compilers/preprocessors interpret the string in #inlude "path" directives, which leads to problems, because the '\' in C-strings is a escape-character!
Think about the "\n" for linefeeds..

Also, you should really take care of the case of filenames in #include directives, because case does really matter in other operating-systems (eg. linux)!
In Linux (and other OSes) "I2CLib.h" and "i2clib.h" are 2 different files !!!

Regards and thx in advance. ;-)
Fri Jan 11 2019, 04:21:37
(no subject) (by José GILLES)
Yes, you're right...
for linux users...

I'll take care of it in next release

Did you use I2c libs ?

Fri Jan 11 2019, 05:58:28
(no subject) (by bfwolf)
Hello José GILLES,

No, i'm sorry, i did'nt use them practically now.. ;-)

But your approach using external libraries with sources is the right way, as i believe! ;-)

Adapting to different microcontrollers would be a easy thing then, e.g. for Atmel/Microchip ARM-chips like those on Arduino-Due or Arduino-Zero etc. :-)

I have an other suggestion for minor changes:

Why not always embed the functions like
PlcDelay(), TIM3_Handler(), setupPlc(), mainPlc() and main()
by a #ifndef/#endif sequence, so they could be disabled
by a -DEXTERN_main and given in an other source file? ;-)

The funtions given in the generated source could then be used as templates for own implementations.

#ifndef EXTERN_PlcDelay
// PLC Cycle timing function.
void PlcDelay() {
while (! Next_Plc_Cycle);
Next_Plc_Cycle= 0;


#ifndef EXTERN_main
void main(void) { // You can use this as is.
int main(void) { // You can use this as is.
return 0;

I've already wrote this to Ihor, but either he ignored it
or he didn't understand my intentions...

Of course one could use e.g. AWK to cut these functions out of the generated source, but the #ifndef/#endif sequence would be much easier! :-)

Fri Jan 11 2019, 08:06:05
(no subject) (by José GILLES)
I'm happy you approve externalization !

I'll think at your suggestions:

a simplest way to do it may be to declare these functions as weak symbols, which can be overridden by strong ones in other sources.
I used it in I2C libs, not to be obliged to provide I2CLcd library if not used at all.

Best regards
Fri Jan 11 2019, 08:42:33
(no subject) (by bfwolf)
Hello José GILLES,

yes, declaring these functions as weak symbols would be easy,
but unfortunately 'weak' is not a standard compiler-feature,
so using #ifndef/#endif would be the most portable way. ;-)

Best regards and happy weekend ;-)
Fri Jan 11 2019, 09:00:39
(no subject) (by Alex)
here there are the screenshots
Fri Jan 11 2019, 10:00:23, download attachment screenshots black window.pdf
(no subject) (by Alex)
here there are the screenshots
Fri Jan 11 2019, 10:00:50, download attachment screenshots black window.pdf
(no subject) (by José GILLES)
To bfwolf:

Yes, weak is less portable, but it works with our Gcc compilers, and is lighter ; and everybody won't have to use these extras...

To Alex:

There are several errors in your output:

1) I2clib can't find ladder.h
That's very strange because ladder.h is generated by ldmicro.
- Did you record .c file in the same dir as .ld file ?
- verify that your I2CLib.c includes "..\ladder.h"
- verify if ladder.h exists

2) I2CLcdlib needs delay functions, which are in new libs named Usrlib.c and .h that you must copy in your lib directory

3) I2CLcdLib needs I2C_MasterSetReg and I2C_MasterGetReg
But these 2 functions are in I2cLib !

I wonder if your I2Clib.c file is the good one !
It has changed with new I2CLcd functions.
Reload all libraries from Github, especially I2Clib and Usrlib and remove all elder ones...

Fri Jan 11 2019, 11:48:58
(no subject) (by José GILLES)
To Alex:

Here's my file hierarchy to generate I2cLcd.hex
You should have the same one.

Not tested on mega328 but works on mega16.
The executable for atMega328 is in bin directory,
so that you can try it on arduino (I suppose).
Fri Jan 11 2019, 13:28:13, download attachment I2clcd.zip
(no subject) (by Ziggy)
I bet the above exchange between Jose and bfwolf has left most LDmicro users in a spin...
What happened to the ease of use ?
Is weak symbol a part of C or C++?
Do i need to understand inheritance and what is this polymorphism shit anyway?

While it is nice to make LDmore flexible.. if You make it too flexible You will break the typical users back.
To get to where you are pitching the user will need to be trained up.

Some thirty years ago i was looking into distributed digital control in building automation... The thing that came out of that deliberation was...

High tech needs to be so good that it looks like low tech to the uninitiated.

In other words use KISS rule.
Fri Jan 11 2019, 17:24:06
(no subject) (by Alex)
thanks José GUILLES. i deleted everything and downlaoded again, and copied your lib file from your file hierarchy, it generated hex :)


i am using arduino PC8574AT i/o expander board and this is what i got :


i´ll keep cheking i just wanted you to know that my ldmicro32 compiles hex
Fri Jan 11 2019, 22:20:32
(no subject) (by Alex)
about the topic of external compiler and make everything inside ldmicro, is it possible to make something similar like languages lang? in the past Ihor asked for help translating manual to spanish to Jose Manuel Ruiz Gutierrez, Ihor gave him a file to add the spanish words to it in this thread:


i mean is it possible to have somekind of general file for i2c, spi , parallel lcd, i don´t know.., since it is a lot of work, and we, the ldmicro community fill the code for the mcu´s we have and then integrate it into LDmicro with the help of the new developer, like, help him
Fri Jan 11 2019, 22:39:19
(no subject) (by José GILLES)
To Alex:

Good news if now you can compile ! There was a pb in your files...

It may not work for you because of different crystal frequency. I tried at 8 MHz and you must run at 16 ?

LCD displays need many little delays, that's why I added dely_ms and delay_us functions in UsrLib.c
For the time being these delay functions are empirical and just use counting loops ; edit UsrLib.c and at the back of the file, increase delays by replacing:

unsigned d= us/2; -> unsigned d= 5*us;

unsigned long d= 300*ms; -> unsigned long d= 1000*ms;

Recompile and retry.
If it works, you can reduce the values until limit...
If it doesn't, increase the values again and retry.

I'll make more reliable delays, as soon as possible.

To others:

After reflexion, I think I won't add weak prefixes because it's not portable enough, and I can't use #ifndef because prototypes in .h make functions always defined !
Anyway, people who would like to use files in another way will likely be able to solve it on their own...

For spanish version, Calubert offered to translate messages in spanish ; I intend to contact him this week-end.
If some of you have sufficient knowledge of german, portuguese or italian, let us know...


Don't laugh at C++ ; a software written in C++ with objects and inheritance would be much more simple to manage !
Sat Jan 12 2019, 03:42:38
(no subject) (by Alex)
Thanks for the answer, i am testing all kind of values -.- , hope find the correct ones.

btw, in ldmicro there are these functiones:


i read in the past that it was included by Dzairo a former ldmicro developer, i think before Ihor, he said that sfr can work with i2c here:


but how? or is it incomplete?, just want to get rid of doubts
Sun Jan 13 2019, 00:03:52
(no subject) (by José GILLES)

I don't know exactly what are these SFR functions, and what it could have to do with I2C...

But I can ensure you that my I2C functions work, even with LCD. Its probably just a question of time setting, unless your 16x2 display hasn't got the same design as mine ; but as far as I know it's standard. Our IO-Expanders are identical.
Sun Jan 13 2019, 05:34:48
(no subject) (by Ziggy)
SFR = special function register

these are various registers ( I am speaking of AVR annotation ) whihc are used to control various peripherals by setting bit values in specific ways and reading various bit values to determine state of peripherals such as for example counters, SPI etc.
Sun Jan 13 2019, 14:58:43
(no subject) (by Alex)
thanks for the explanation Ziggy, said it, is there some way to use it, for example, a ds3231 at least to enable its square wave 1hz option? can we do something with sfr:

Sun Jan 13 2019, 22:31:33
(no subject) (by José GILLES)
Yes, it seems to be made to access internal registers of an AVR...

One can read, write in registers, set, clear or test bits, ie do many elementary operations on registers like I2C ones (TWBR, TWCR, TWDR, TWSR)

But if one reads the I2C library, he will note that I2C initialization requires only 3 elementary operations, but read one byte on I2C requires about 30 elementary operations and delays !!!
That's not usable in a ladder, is it ?
Mon Jan 14 2019, 01:32:31
(no subject) (by Ziggy)
Hello Alex,

Those who are familiar with C programing of AVR already do this in C.

And once they have done it... they write a library ...

They make the library to enhance the function call such as for example Jose has already highlighted in the posting directly above this response.

Handling registers in low level mode is very low level programing..

It means understanding what each bit in the register does, how to modify each bit to achieve desired outcome, how to check the outcome has been reached and then do it again...
And while it works even inside the ladder it is deprecated in more recent releases of LDmicro.
Mon Jan 14 2019, 01:58:28
(no subject) (by Antonio)
Hello José GILLES

I have tried the example TEST-ADC creating a hex file and with the version Release, built 18:11:41 Jan 8 2019 it does not work.

When I create the hex file with the version Release, built 17:24:39 May 23 2018 Yes, it works.

Attached files and videos.


I have tried the other examples and they do not work with Arduino Uno either.

Mon Jan 14 2019, 15:33:47
(no subject) (by Antonio)
Compare Hex versions.
Mon Jan 14 2019, 16:31:43, download attachment compare hex versions.jpg
(no subject) (by José GILLES)

You compile directly to HEX / ASM for AtMega328 if I undestand well ?

I'll have a look at it tomorrow.
But what I can say immediately is that when I compile this ladder with last official 4.4.3 version by Ihor, and with my 5.0 one, I get exactly the same hex file.

Thus, they both work or not...
During development around C, I tried not to modify other compiling behaviours.

I don't know this strange old build...

Mon Jan 14 2019, 17:41:24
(no subject) (by Alex)
ok thanks for your answer, about the SFR function in ldmicro, yeah ".. .it is deprecated in more recent releases of LDmicro."
Mon Jan 14 2019, 19:02:46
(no subject) (by Antonio)
From the version v4.4.0.2 until 4.4.3 version by Ihor does not work.

Tue Jan 15 2019, 00:06:05
(no subject) (by José GILLES)
To Antonio:

I've just tried to recompile test-adc.ld with ldmicro 4.4.3 and 5.0 and it works with both on my true atmega328 !
It works in C mode too.

There must be a problem by your side ?

Tue Jan 15 2019, 04:21:10
(no subject) (by bfwolf)

Hello ;-) Did you once again think about my idea to allow excluding the functions like PlcDelay() or main() with #ifndef/#endif surrounding them? ;-)

I don't think, it should be so difficult, as you could just use the string-constant "EXTERN_" concatenated with the function-name (eg "PlcDelay").

Using exclude-macros would be the most portable way..

Prototypes in the generated header-file should't be a problem but could be useful for the own implementations in an additional c/c++ source-file..

Best regards ;-)
Thu Jan 24 2019, 03:59:41
(no subject) (by Vlado)
How Can It Work lcd 16x2

#include <LiquidCrystal_I2C.h> // F Malpartida's NewLiquidCrystal library
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity

Thank you.
Sun Jan 27 2019, 14:36:34
Post a reply to this comment:
Your Name:
Your Email:
(no HTML tags; use plain text, and hit Enter for a line break)
Attached file (if you want, 5 MB max):