From 93e0b16f79e953ceecf00fe770a85aca7fe4e72b Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Thu, 11 Sep 2025 20:13:53 +0300 Subject: [PATCH] Add MLXtest, 4.8ms for parsing image in standard range --- F1:F103/deprecated/MLX90640/mlx90640.c | 4 +- F3:F303/MLX90640test/Makefile | 10 + F3:F303/MLX90640test/alpha.csv | 1 + F3:F303/MLX90640test/eeprom.csv | 1 + F3:F303/MLX90640test/frame0.csv | 1 + F3:F303/MLX90640test/frame1.csv | 1 + F3:F303/MLX90640test/hardware.c | 34 ++ F3:F303/MLX90640test/hardware.h | 31 ++ F3:F303/MLX90640test/kta.csv | 1 + F3:F303/MLX90640test/kv.csv | 1 + F3:F303/MLX90640test/main.c | 56 +++ F3:F303/MLX90640test/mlx90640.c | 448 ++++++++++++++++++++++ F3:F303/MLX90640test/mlx90640.h | 68 ++++ F3:F303/MLX90640test/mlx90640_regs.h | 90 +++++ F3:F303/MLX90640test/mlxtest.bin | Bin 0 -> 30116 bytes F3:F303/MLX90640test/mlxtest.cflags | 1 + F3:F303/MLX90640test/mlxtest.config | 7 + F3:F303/MLX90640test/mlxtest.creator | 1 + F3:F303/MLX90640test/mlxtest.creator.user | 215 +++++++++++ F3:F303/MLX90640test/mlxtest.cxxflags | 1 + F3:F303/MLX90640test/mlxtest.files | 22 ++ F3:F303/MLX90640test/mlxtest.includes | 6 + F3:F303/MLX90640test/offset.csv | 1 + F3:F303/MLX90640test/openocd.cfg | 119 ++++++ F3:F303/MLX90640test/proto.c | 49 +++ F3:F303/MLX90640test/proto.h | 22 ++ F3:F303/MLX90640test/ringbuffer.c | 166 ++++++++ F3:F303/MLX90640test/ringbuffer.h | 41 ++ F3:F303/MLX90640test/strfunc.c | 334 ++++++++++++++++ F3:F303/MLX90640test/strfunc.h | 47 +++ F3:F303/MLX90640test/testdata.h | 82 ++++ F3:F303/MLX90640test/to_frame0.csv | 1 + F3:F303/MLX90640test/to_frame1.csv | 1 + F3:F303/MLX90640test/usb_descr.c | 210 ++++++++++ F3:F303/MLX90640test/usb_descr.h | 62 +++ F3:F303/MLX90640test/usb_dev.c | 240 ++++++++++++ F3:F303/MLX90640test/usb_dev.h | 57 +++ F3:F303/MLX90640test/usb_lib.c | 368 ++++++++++++++++++ F3:F303/MLX90640test/usb_lib.h | 328 ++++++++++++++++ F3:F303/MLX90640test/version.inc | 2 + 40 files changed, 3128 insertions(+), 2 deletions(-) create mode 100644 F3:F303/MLX90640test/Makefile create mode 100644 F3:F303/MLX90640test/alpha.csv create mode 100644 F3:F303/MLX90640test/eeprom.csv create mode 100644 F3:F303/MLX90640test/frame0.csv create mode 100644 F3:F303/MLX90640test/frame1.csv create mode 100644 F3:F303/MLX90640test/hardware.c create mode 100644 F3:F303/MLX90640test/hardware.h create mode 100644 F3:F303/MLX90640test/kta.csv create mode 100644 F3:F303/MLX90640test/kv.csv create mode 100644 F3:F303/MLX90640test/main.c create mode 100644 F3:F303/MLX90640test/mlx90640.c create mode 100644 F3:F303/MLX90640test/mlx90640.h create mode 100644 F3:F303/MLX90640test/mlx90640_regs.h create mode 100755 F3:F303/MLX90640test/mlxtest.bin create mode 100644 F3:F303/MLX90640test/mlxtest.cflags create mode 100644 F3:F303/MLX90640test/mlxtest.config create mode 100644 F3:F303/MLX90640test/mlxtest.creator create mode 100644 F3:F303/MLX90640test/mlxtest.creator.user create mode 100644 F3:F303/MLX90640test/mlxtest.cxxflags create mode 100644 F3:F303/MLX90640test/mlxtest.files create mode 100644 F3:F303/MLX90640test/mlxtest.includes create mode 100644 F3:F303/MLX90640test/offset.csv create mode 100644 F3:F303/MLX90640test/openocd.cfg create mode 100644 F3:F303/MLX90640test/proto.c create mode 100644 F3:F303/MLX90640test/proto.h create mode 100644 F3:F303/MLX90640test/ringbuffer.c create mode 100644 F3:F303/MLX90640test/ringbuffer.h create mode 100644 F3:F303/MLX90640test/strfunc.c create mode 100644 F3:F303/MLX90640test/strfunc.h create mode 100644 F3:F303/MLX90640test/testdata.h create mode 100644 F3:F303/MLX90640test/to_frame0.csv create mode 100644 F3:F303/MLX90640test/to_frame1.csv create mode 100644 F3:F303/MLX90640test/usb_descr.c create mode 100644 F3:F303/MLX90640test/usb_descr.h create mode 100644 F3:F303/MLX90640test/usb_dev.c create mode 100644 F3:F303/MLX90640test/usb_dev.h create mode 100644 F3:F303/MLX90640test/usb_lib.c create mode 100644 F3:F303/MLX90640test/usb_lib.h create mode 100644 F3:F303/MLX90640test/version.inc diff --git a/F1:F103/deprecated/MLX90640/mlx90640.c b/F1:F103/deprecated/MLX90640/mlx90640.c index af703c3..4198fd4 100644 --- a/F1:F103/deprecated/MLX90640/mlx90640.c +++ b/F1:F103/deprecated/MLX90640/mlx90640.c @@ -367,9 +367,9 @@ SEND("\n070a="); printuhex(IMD_VAL(REG_IGAIN)); newline(); Tar = Tar*Tar*Tar*Tar; float ac3 = alphaComp*alphaComp*alphaComp; float Sx = ac3*IRcompens + alphaComp*ac3*Tar; - Sx = params.KsTa * sqrt(sqrt(Sx)); + Sx = params.KsTa * sqrtf(sqrtf(Sx)); float To = IRcompens / (alphaComp * (1.f - params.ksTo[1]) + Sx) + Tar; - curval = sqrt(sqrt(To)) - 273.15; // To + curval = sqrtf(sqrtf(To)) - 273.15; // To // TODO: extended } mlx_image[pixno] = curval; diff --git a/F3:F303/MLX90640test/Makefile b/F3:F303/MLX90640test/Makefile new file mode 100644 index 0000000..64ba99e --- /dev/null +++ b/F3:F303/MLX90640test/Makefile @@ -0,0 +1,10 @@ +BINARY := mlxtest +# MCU code +MCU := F303xb +# change this linking script depending on particular MCU model, +LDSCRIPT := stm32f303xB.ld +DEFINES := -DUSB1_16 +LDLIBS := -lm + +include ../makefile.f3 +include ../../makefile.stm32 diff --git a/F3:F303/MLX90640test/alpha.csv b/F3:F303/MLX90640test/alpha.csv new file mode 100644 index 0000000..82a4341 --- /dev/null +++ b/F3:F303/MLX90640test/alpha.csv @@ -0,0 +1 @@ +0.0000000364125298802, 0.0000000368781911675, 0.0000000379259290639, 0.0000000383915903512, 0.0000000408363121096, 0.0000000415348040406, 0.0000000416512193624, 0.0000000422332959715, 0.0000000440959411208, 0.0000000446780177299, 0.0000000447944330517, 0.0000000445616024081, 0.0000000460750015918, 0.0000000467734935228, 0.0000000456093403045, 0.0000000456093403045, 0.0000000456093403045, 0.0000000453765096609, 0.0000000443287717644, 0.0000000443287717644, 0.0000000438631104771, 0.0000000432810338680, 0.0000000411855580751, 0.0000000406034814660, 0.0000000393229129259, 0.0000000390900822822, 0.0000000358304532710, 0.0000000355976226274, 0.0000000336185621563, 0.0000000323379936162, 0.0000000291947799269, 0.0000000283798726741, 0.0000000369946064893, 0.0000000375766830985, 0.0000000386244209949, 0.0000000390900822822, 0.0000000414183887187, 0.0000000421168806497, 0.0000000424661266152, 0.0000000428153725807, 0.0000000447944330517, 0.0000000454929249827, 0.0000000454929249827, 0.0000000453765096609, 0.0000000466570782010, 0.0000000474719854537, 0.0000000464242475573, 0.0000000463078322355, 0.0000000463078322355, 0.0000000461914169136, 0.0000000451436790172, 0.0000000450272636954, 0.0000000447944330517, 0.0000000439795257989, 0.0000000420004653279, 0.0000000413019733969, 0.0000000401378201786, 0.0000000399049895350, 0.0000000367617758457, 0.0000000362961145584, 0.0000000345498847309, 0.0000000330364855472, 0.0000000298932718579, 0.0000000290783646051, 0.0000000386244209949, 0.0000000388572516385, 0.0000000403706508223, 0.0000000408363121096, 0.0000000432810338680, 0.0000000436302798335, 0.0000000444451870862, 0.0000000447944330517, 0.0000000464242475573, 0.0000000465406628791, 0.0000000466570782010, 0.0000000474719854537, 0.0000000479376467410, 0.0000000493346306030, 0.0000000478212314192, 0.0000000475884007756, 0.0000000478212314192, 0.0000000477048160974, 0.0000000473555701319, 0.0000000463078322355, 0.0000000461914169136, 0.0000000456093403045, 0.0000000433974491898, 0.0000000438631104771, 0.0000000422332959715, 0.0000000413019733969, 0.0000000387408363167, 0.0000000378095137421, 0.0000000366453605238, 0.0000000352483766619, 0.0000000319887476508, 0.0000000309410097543, 0.0000000390900822822, 0.0000000393229129259, 0.0000000409527274314, 0.0000000414183887187, 0.0000000438631104771, 0.0000000442123564426, 0.0000000450272636954, 0.0000000452600943390, 0.0000000470063241664, 0.0000000472391548101, 0.0000000471227394883, 0.0000000480540620629, 0.0000000482868927065, 0.0000000499167072121, 0.0000000482868927065, 0.0000000481704773847, 0.0000000482868927065, 0.0000000482868927065, 0.0000000479376467410, 0.0000000468899088446, 0.0000000468899088446, 0.0000000463078322355, 0.0000000440959411208, 0.0000000445616024081, 0.0000000428153725807, 0.0000000420004653279, 0.0000000394393282477, 0.0000000385080056731, 0.0000000374602677766, 0.0000000359468685929, 0.0000000326872395817, 0.0000000316395016853, 0.0000000397885742132, 0.0000000404870661441, 0.0000000418840500060, 0.0000000422332959715, 0.0000000456093403045, 0.0000000454929249827, 0.0000000466570782010, 0.0000000464242475573, 0.0000000482868927065, 0.0000000486361386720, 0.0000000484033080284, 0.0000000489853846375, 0.0000000501495378558, 0.0000000494510459248, 0.0000000496838765685, 0.0000000495674612466, 0.0000000498002918903, 0.0000000495674612466, 0.0000000486361386720, 0.0000000481704773847, 0.0000000482868927065, 0.0000000480540620629, 0.0000000460750015918, 0.0000000458421709482, 0.0000000443287717644, 0.0000000439795257989, 0.0000000402542355005, 0.0000000401378201786, 0.0000000386244209949, 0.0000000374602677766, 0.0000000337349774782, 0.0000000330364855472, 0.0000000401378201786, 0.0000000408363121096, 0.0000000424661266152, 0.0000000426989572588, 0.0000000459585862700, 0.0000000460750015918, 0.0000000471227394883, 0.0000000467734935228, 0.0000000486361386720, 0.0000000491017999593, 0.0000000488689693157, 0.0000000494510459248, 0.0000000506151991431, 0.0000000499167072121, 0.0000000501495378558, 0.0000000500331225339, 0.0000000502659531776, 0.0000000499167072121, 0.0000000491017999593, 0.0000000485197233502, 0.0000000487525539938, 0.0000000484033080284, 0.0000000465406628791, 0.0000000463078322355, 0.0000000449108483735, 0.0000000444451870862, 0.0000000407198967878, 0.0000000407198967878, 0.0000000393229129259, 0.0000000379259290639, 0.0000000342006387655, 0.0000000336185621563, 0.0000000418840500060, 0.0000000421168806497, 0.0000000437466951553, 0.0000000442123564426, 0.0000000466570782010, 0.0000000472391548101, 0.0000000472391548101, 0.0000000477048160974, 0.0000000482868927065, 0.0000000495674612466, 0.0000000503823684994, 0.0000000502659531776, 0.0000000514301063959, 0.0000000514301063959, 0.0000000508480297867, 0.0000000509644451085, 0.0000000516629370395, 0.0000000511972757522, 0.0000000502659531776, 0.0000000496838765685, 0.0000000501495378558, 0.0000000491017999593, 0.0000000473555701319, 0.0000000467734935228, 0.0000000464242475573, 0.0000000451436790172, 0.0000000422332959715, 0.0000000414183887187, 0.0000000397885742132, 0.0000000390900822822, 0.0000000352483766619, 0.0000000343170540873, 0.0000000423497112934, 0.0000000425825419370, 0.0000000440959411208, 0.0000000446780177299, 0.0000000471227394883, 0.0000000477048160974, 0.0000000478212314192, 0.0000000480540620629, 0.0000000487525539938, 0.0000000500331225339, 0.0000000507316144649, 0.0000000506151991431, 0.0000000516629370395, 0.0000000516629370395, 0.0000000511972757522, 0.0000000514301063959, 0.0000000520121830050, 0.0000000516629370395, 0.0000000506151991431, 0.0000000500331225339, 0.0000000504987838212, 0.0000000494510459248, 0.0000000477048160974, 0.0000000471227394883, 0.0000000466570782010, 0.0000000454929249827, 0.0000000428153725807, 0.0000000418840500060, 0.0000000402542355005, 0.0000000395557435695, 0.0000000357140379492, 0.0000000346663000528, 0.0000000423497112934, 0.0000000426989572588, 0.0000000444451870862, 0.0000000452600943390, 0.0000000474719854537, 0.0000000475884007756, 0.0000000482868927065, 0.0000000486361386720, 0.0000000504987838212, 0.0000000502659531776, 0.0000000509644451085, 0.0000000515465217177, 0.0000000518957676832, 0.0000000527106749360, 0.0000000515465217177, 0.0000000517793523613, 0.0000000524778442923, 0.0000000523614289705, 0.0000000508480297867, 0.0000000511972757522, 0.0000000503823684994, 0.0000000503823684994, 0.0000000487525539938, 0.0000000480540620629, 0.0000000468899088446, 0.0000000464242475573, 0.0000000436302798335, 0.0000000424661266152, 0.0000000404870661441, 0.0000000399049895350, 0.0000000361796992365, 0.0000000353647919837, 0.0000000426989572588, 0.0000000430482032243, 0.0000000447944330517, 0.0000000456093403045, 0.0000000477048160974, 0.0000000479376467410, 0.0000000486361386720, 0.0000000491017999593, 0.0000000507316144649, 0.0000000506151991431, 0.0000000513136910740, 0.0000000517793523613, 0.0000000520121830050, 0.0000000530599209014, 0.0000000517793523613, 0.0000000522450136486, 0.0000000528270902578, 0.0000000524778442923, 0.0000000511972757522, 0.0000000515465217177, 0.0000000508480297867, 0.0000000508480297867, 0.0000000489853846375, 0.0000000485197233502, 0.0000000473555701319, 0.0000000467734935228, 0.0000000439795257989, 0.0000000429317879025, 0.0000000408363121096, 0.0000000402542355005, 0.0000000365289452020, 0.0000000355976226274, 0.0000000425825419370, 0.0000000436302798335, 0.0000000450272636954, 0.0000000458421709482, 0.0000000474719854537, 0.0000000485197233502, 0.0000000494510459248, 0.0000000494510459248, 0.0000000506151991431, 0.0000000517793523613, 0.0000000513136910740, 0.0000000523614289705, 0.0000000521285983268, 0.0000000527106749360, 0.0000000525942596141, 0.0000000524778442923, 0.0000000527106749360, 0.0000000523614289705, 0.0000000508480297867, 0.0000000516629370395, 0.0000000508480297867, 0.0000000508480297867, 0.0000000491017999593, 0.0000000488689693157, 0.0000000477048160974, 0.0000000470063241664, 0.0000000439795257989, 0.0000000436302798335, 0.0000000410691427533, 0.0000000403706508223, 0.0000000366453605238, 0.0000000362961145584, 0.0000000429317879025, 0.0000000438631104771, 0.0000000452600943390, 0.0000000459585862700, 0.0000000477048160974, 0.0000000487525539938, 0.0000000496838765685, 0.0000000498002918903, 0.0000000508480297867, 0.0000000520121830050, 0.0000000516629370395, 0.0000000524778442923, 0.0000000523614289705, 0.0000000530599209014, 0.0000000529435055796, 0.0000000527106749360, 0.0000000529435055796, 0.0000000525942596141, 0.0000000511972757522, 0.0000000520121830050, 0.0000000510808604304, 0.0000000510808604304, 0.0000000494510459248, 0.0000000492182152811, 0.0000000479376467410, 0.0000000472391548101, 0.0000000440959411208, 0.0000000437466951553, 0.0000000411855580751, 0.0000000406034814660, 0.0000000369946064893, 0.0000000364125298802, 0.0000000428153725807, 0.0000000436302798335, 0.0000000460750015918, 0.0000000457257556263, 0.0000000477048160974, 0.0000000488689693157, 0.0000000492182152811, 0.0000000491017999593, 0.0000000509644451085, 0.0000000513136910740, 0.0000000515465217177, 0.0000000514301063959, 0.0000000524778442923, 0.0000000527106749360, 0.0000000534091668669, 0.0000000528270902578, 0.0000000523614289705, 0.0000000529435055796, 0.0000000521285983268, 0.0000000520121830050, 0.0000000513136910740, 0.0000000514301063959, 0.0000000487525539938, 0.0000000489853846375, 0.0000000474719854537, 0.0000000475884007756, 0.0000000436302798335, 0.0000000432810338680, 0.0000000411855580751, 0.0000000401378201786, 0.0000000371110218111, 0.0000000360632839147, 0.0000000429317879025, 0.0000000438631104771, 0.0000000463078322355, 0.0000000459585862700, 0.0000000479376467410, 0.0000000489853846375, 0.0000000493346306030, 0.0000000493346306030, 0.0000000511972757522, 0.0000000514301063959, 0.0000000518957676832, 0.0000000515465217177, 0.0000000527106749360, 0.0000000528270902578, 0.0000000537584128324, 0.0000000529435055796, 0.0000000527106749360, 0.0000000532927515451, 0.0000000522450136486, 0.0000000521285983268, 0.0000000513136910740, 0.0000000515465217177, 0.0000000491017999593, 0.0000000492182152811, 0.0000000474719854537, 0.0000000474719854537, 0.0000000437466951553, 0.0000000433974491898, 0.0000000413019733969, 0.0000000402542355005, 0.0000000372274371330, 0.0000000361796992365, 0.0000000423497112934, 0.0000000433974491898, 0.0000000443287717644, 0.0000000457257556263, 0.0000000480540620629, 0.0000000486361386720, 0.0000000486361386720, 0.0000000489853846375, 0.0000000501495378558, 0.0000000509644451085, 0.0000000514301063959, 0.0000000510808604304, 0.0000000521285983268, 0.0000000524778442923, 0.0000000522450136486, 0.0000000524778442923, 0.0000000524778442923, 0.0000000520121830050, 0.0000000509644451085, 0.0000000515465217177, 0.0000000504987838212, 0.0000000507316144649, 0.0000000487525539938, 0.0000000485197233502, 0.0000000465406628791, 0.0000000460750015918, 0.0000000433974491898, 0.0000000423497112934, 0.0000000410691427533, 0.0000000402542355005, 0.0000000364125298802, 0.0000000358304532710, 0.0000000423497112934, 0.0000000433974491898, 0.0000000444451870862, 0.0000000458421709482, 0.0000000481704773847, 0.0000000487525539938, 0.0000000487525539938, 0.0000000491017999593, 0.0000000503823684994, 0.0000000510808604304, 0.0000000516629370395, 0.0000000511972757522, 0.0000000522450136486, 0.0000000525942596141, 0.0000000523614289705, 0.0000000525942596141, 0.0000000524778442923, 0.0000000520121830050, 0.0000000510808604304, 0.0000000516629370395, 0.0000000507316144649, 0.0000000507316144649, 0.0000000489853846375, 0.0000000485197233502, 0.0000000464242475573, 0.0000000459585862700, 0.0000000433974491898, 0.0000000423497112934, 0.0000000410691427533, 0.0000000402542355005, 0.0000000364125298802, 0.0000000357140379492, 0.0000000410691427533, 0.0000000423497112934, 0.0000000436302798335, 0.0000000444451870862, 0.0000000467734935228, 0.0000000473555701319, 0.0000000480540620629, 0.0000000477048160974, 0.0000000502659531776, 0.0000000504987838212, 0.0000000509644451085, 0.0000000510808604304, 0.0000000516629370395, 0.0000000514301063959, 0.0000000511972757522, 0.0000000514301063959, 0.0000000518957676832, 0.0000000513136910740, 0.0000000502659531776, 0.0000000502659531776, 0.0000000503823684994, 0.0000000496838765685, 0.0000000480540620629, 0.0000000470063241664, 0.0000000458421709482, 0.0000000456093403045, 0.0000000422332959715, 0.0000000422332959715, 0.0000000397885742132, 0.0000000390900822822, 0.0000000352483766619, 0.0000000346663000528, 0.0000000408363121096, 0.0000000423497112934, 0.0000000435138645116, 0.0000000444451870862, 0.0000000466570782010, 0.0000000474719854537, 0.0000000481704773847, 0.0000000478212314192, 0.0000000502659531776, 0.0000000506151991431, 0.0000000509644451085, 0.0000000510808604304, 0.0000000517793523613, 0.0000000514301063959, 0.0000000513136910740, 0.0000000515465217177, 0.0000000520121830050, 0.0000000513136910740, 0.0000000502659531776, 0.0000000501495378558, 0.0000000503823684994, 0.0000000498002918903, 0.0000000478212314192, 0.0000000468899088446, 0.0000000457257556263, 0.0000000454929249827, 0.0000000421168806497, 0.0000000421168806497, 0.0000000396721588913, 0.0000000388572516385, 0.0000000351319613401, 0.0000000345498847309, 0.0000000402542355005, 0.0000000414183887187, 0.0000000433974491898, 0.0000000436302798335, 0.0000000466570782010, 0.0000000464242475573, 0.0000000477048160974, 0.0000000471227394883, 0.0000000496838765685, 0.0000000501495378558, 0.0000000493346306030, 0.0000000495674612466, 0.0000000511972757522, 0.0000000514301063959, 0.0000000503823684994, 0.0000000503823684994, 0.0000000507316144649, 0.0000000509644451085, 0.0000000496838765685, 0.0000000491017999593, 0.0000000492182152811, 0.0000000486361386720, 0.0000000463078322355, 0.0000000458421709482, 0.0000000449108483735, 0.0000000440959411208, 0.0000000411855580751, 0.0000000403706508223, 0.0000000378095137421, 0.0000000378095137421, 0.0000000344334694091, 0.0000000326872395817, 0.0000000401378201786, 0.0000000411855580751, 0.0000000431646185461, 0.0000000432810338680, 0.0000000464242475573, 0.0000000463078322355, 0.0000000475884007756, 0.0000000471227394883, 0.0000000498002918903, 0.0000000500331225339, 0.0000000492182152811, 0.0000000496838765685, 0.0000000513136910740, 0.0000000514301063959, 0.0000000503823684994, 0.0000000504987838212, 0.0000000507316144649, 0.0000000510808604304, 0.0000000496838765685, 0.0000000491017999593, 0.0000000489853846375, 0.0000000485197233502, 0.0000000459585862700, 0.0000000457257556263, 0.0000000446780177299, 0.0000000438631104771, 0.0000000409527274314, 0.0000000400214048568, 0.0000000375766830985, 0.0000000375766830985, 0.0000000340842234436, 0.0000000324544089381, 0.0000000385080056731, 0.0000000392064976040, 0.0000000408363121096, 0.0000000421168806497, 0.0000000443287717644, 0.0000000450272636954, 0.0000000449108483735, 0.0000000456093403045, 0.0000000474719854537, 0.0000000481704773847, 0.0000000473555701319, 0.0000000486361386720, 0.0000000486361386720, 0.0000000489853846375, 0.0000000486361386720, 0.0000000489853846375, 0.0000000493346306030, 0.0000000498002918903, 0.0000000481704773847, 0.0000000475884007756, 0.0000000468899088446, 0.0000000464242475573, 0.0000000443287717644, 0.0000000433974491898, 0.0000000425825419370, 0.0000000414183887187, 0.0000000390900822822, 0.0000000382751750294, 0.0000000366453605238, 0.0000000354812073056, 0.0000000322215782944, 0.0000000312902557198, 0.0000000381587597076, 0.0000000389736669604, 0.0000000404870661441, 0.0000000417676346842, 0.0000000438631104771, 0.0000000446780177299, 0.0000000445616024081, 0.0000000452600943390, 0.0000000473555701319, 0.0000000480540620629, 0.0000000473555701319, 0.0000000484033080284, 0.0000000484033080284, 0.0000000488689693157, 0.0000000485197233502, 0.0000000488689693157, 0.0000000492182152811, 0.0000000494510459248, 0.0000000479376467410, 0.0000000473555701319, 0.0000000464242475573, 0.0000000461914169136, 0.0000000439795257989, 0.0000000431646185461, 0.0000000422332959715, 0.0000000410691427533, 0.0000000388572516385, 0.0000000378095137421, 0.0000000362961145584, 0.0000000351319613401, 0.0000000319887476508, 0.0000000310574250761, 0.0000000369946064893, 0.0000000373438524548, 0.0000000392064976040, 0.0000000392064976040, 0.0000000417676346842, 0.0000000421168806497, 0.0000000433974491898, 0.0000000437466951553, 0.0000000458421709482, 0.0000000452600943390, 0.0000000460750015918, 0.0000000452600943390, 0.0000000479376467410, 0.0000000478212314192, 0.0000000471227394883, 0.0000000470063241664, 0.0000000475884007756, 0.0000000471227394883, 0.0000000454929249827, 0.0000000445616024081, 0.0000000446780177299, 0.0000000444451870862, 0.0000000418840500060, 0.0000000411855580751, 0.0000000400214048568, 0.0000000397885742132, 0.0000000364125298802, 0.0000000360632839147, 0.0000000344334694091, 0.0000000337349774782, 0.0000000301261025015, 0.0000000290783646051, 0.0000000367617758457, 0.0000000371110218111, 0.0000000389736669604, 0.0000000389736669604, 0.0000000415348040406, 0.0000000418840500060, 0.0000000430482032243, 0.0000000432810338680, 0.0000000456093403045, 0.0000000450272636954, 0.0000000456093403045, 0.0000000449108483735, 0.0000000475884007756, 0.0000000474719854537, 0.0000000467734935228, 0.0000000466570782010, 0.0000000472391548101, 0.0000000466570782010, 0.0000000452600943390, 0.0000000442123564426, 0.0000000442123564426, 0.0000000439795257989, 0.0000000415348040406, 0.0000000408363121096, 0.0000000397885742132, 0.0000000395557435695, 0.0000000361796992365, 0.0000000357140379492, 0.0000000340842234436, 0.0000000335021468345, 0.0000000297768565360, 0.0000000287291186396 diff --git a/F3:F303/MLX90640test/eeprom.csv b/F3:F303/MLX90640test/eeprom.csv new file mode 100644 index 0000000..e6e55af --- /dev/null +++ b/F3:F303/MLX90640test/eeprom.csv @@ -0,0 +1 @@ +0x00AE,0x499A,0x0000,0x2061,0x0005,0x0320,0x03E0,0x1710,0xA224,0x0185,0x0499,0x0000,0x1901,0x0000,0x0000,0xB533,0x4210,0xFFC2,0x0202,0x0202,0xF202,0xF1F2,0xD1E1,0xAFC0,0xFF00,0xF002,0xF103,0xE103,0xE1F5,0xD1E4,0xC1D5,0x91C2,0x8895,0x30D9,0xEDCB,0x110F,0x3322,0x2233,0x0011,0xCCEE,0xFFED,0x1100,0x2222,0x3333,0x2233,0x0022,0xDEF0,0x9ACC,0x15CC,0x2FA4,0x2555,0x9C78,0x7666,0x01C8,0x3B38,0x3534,0x2452,0x0463,0x13BB,0x0623,0xEC00,0x9797,0x9797,0x2AFB,0x00AE,0xFBE0,0x1B70,0xF3BE,0x000E,0xF86E,0x1B7E,0xF3CE,0xFFCE,0xF41E,0x102E,0xEC0E,0xFFDE,0xEC3E,0x139E,0xEF9E,0xFB9E,0xF77E,0x13E0,0xE7EE,0xF7AE,0xF750,0x0C30,0xEBEE,0xF730,0xF010,0x0B50,0xE430,0xF420,0xF370,0x07C0,0xE450,0x0470,0xFBCE,0xFF5C,0x0F90,0x07D0,0xFC3E,0xFF6C,0x0F90,0x03A0,0xFC0E,0xF40C,0x0BF0,0x03A0,0xF41E,0xF78C,0x0B70,0xFF72,0xFF6E,0xF7DE,0x07C0,0xFFA2,0x0330,0xF42E,0x0BC0,0xFF22,0xFC00,0xF75E,0x0410,0x0022,0x0350,0xF3A0,0x0832,0x04DE,0xFBF0,0x1BCE,0xF00E,0xFC5E,0xFC80,0x1BF0,0xF02E,0x0002,0xF81E,0x142E,0xEC9E,0x07DE,0xF09E,0x17CE,0xF3AE,0xFFC0,0xFBB0,0x1080,0xEBFE,0xFFE0,0xFF90,0x1460,0xE4AE,0xFBC0,0xF840,0x0FE0,0xE860,0xF8C0,0xF400,0x0842,0xE4B0,0x0890,0x03BE,0xFF9C,0x0FD0,0x0020,0x0450,0xFFCC,0x0FE0,0x07D0,0x03FE,0xFBEE,0x0C60,0x0B80,0xF86E,0xFB8E,0x1370,0x0782,0x038E,0xF85E,0x0FC2,0x07C2,0x037E,0xF84E,0x0880,0x0392,0x0420,0xF7CE,0x0C42,0xFCB2,0xFFE0,0xF020,0x0490,0x107E,0x03D0,0x1F90,0xFBCE,0x089E,0x0080,0x1820,0xF40E,0x0800,0xFC30,0x141E,0xF06E,0x0400,0xFFA0,0x17CE,0xF7B0,0x07D0,0xFFB0,0x1830,0xF3FE,0x0002,0xFFE0,0x14D0,0xECB0,0xFBE2,0xFCB0,0x13B0,0xECA0,0xF8DE,0xF432,0x0832,0xE8D0,0x1420,0xFF8E,0xFF6E,0x1380,0x0840,0x005E,0xFBEC,0x0FB0,0x0BB2,0xFFFE,0xFBDE,0x0820,0x0BC0,0x0360,0xFB8C,0x0F70,0x0794,0x036E,0xFBFE,0x0FA0,0x0BC4,0x0390,0xF89E,0x0C72,0xFFB2,0xFC70,0xFB7E,0x0470,0xFCB0,0xFFF0,0xF3F0,0x04A0,0x049E,0x03B0,0x1F90,0xF7D0,0x042E,0x0070,0x1F70,0xFBBE,0x0F00,0x03B0,0x142E,0xF01E,0x07B0,0xFFB0,0x1B60,0xF37E,0xFBD0,0xFF90,0x1410,0xF3C0,0xFC00,0x0370,0x1482,0xF030,0xF800,0xFC50,0x13C2,0xF050,0x0070,0xF812,0x0C02,0xEC80,0x00D0,0xFBFE,0xFBCC,0x0810,0xFC60,0xFCB0,0xFBCE,0x0FE0,0x0B40,0xFFFE,0xF05C,0x0840,0x07D0,0xFFD0,0xF79E,0x0FB0,0xF802,0xFFD0,0xF44E,0x0BF0,0xFC32,0x07A0,0xF4BE,0x0C60,0xF822,0x0080,0xF01E,0x0892,0x00B4,0xF850,0xF040,0x04B2,0x085E,0x0782,0x1F70,0xFBEE,0x001E,0x0420,0x1F80,0xFBB0,0x03B0,0x0390,0x17F0,0xF04E,0x0770,0xFFE0,0x1B40,0xF76E,0xFFC0,0xFFB0,0x17E0,0xEC1E,0x03A0,0x03A0,0x10C0,0xEC60,0xFBC2,0xFC80,0x0C00,0xEC60,0x0050,0xF800,0x0802,0xEC90,0x0080,0xF7B0,0xF7AE,0x0410,0xFC32,0xFC50,0xF7BE,0x07F0,0xFFD2,0xFBC0,0xF02E,0x0460,0x0382,0xF410,0xF36E,0x0BA0,0xFBF2,0xFBC0,0xF01C,0x0440,0xFFE2,0xFBE0,0xF0EE,0x08A2,0xF804,0xFCB0,0xEC3E,0x04A2,0x0082,0xF830,0xE830,0x04B2,0x13F0,0x0380,0x1F40,0xFBB0,0x0F90,0x0420,0x17A0,0xF7AE,0x0F40,0xFFE2,0x13AE,0xF03E,0x0F12,0xFF60,0x0F50,0xF340,0x0362,0xFF30,0x1760,0xEFD0,0x0762,0x0360,0x1072,0xEC50,0xF7B2,0xF852,0x07B0,0xE480,0xF820,0xF7C2,0x03C2,0xE490,0x1422,0x03AE,0x036E,0x13C2,0x13B2,0x0440,0xFFCE,0x13D2,0x1362,0x0002,0xFBDE,0x0C40,0x1732,0x0390,0xFF8E,0x1760,0x0B82,0x0750,0x039E,0x1000,0x0F82,0x0B80,0xFCAE,0x1080,0x0BD4,0x0470,0xFBCE,0x0C92,0x0832,0x07E0,0xF7FE,0x0CA2,0x0010,0x0380,0x13D0,0xF7A0,0xFFBE,0x0052,0x1380,0xF770,0xFF70,0xFFA0,0x0FC0,0xF3BE,0x0340,0xFF60,0x0FC0,0xF370,0xFB30,0xFB80,0x0C10,0xE40E,0xFBA0,0xFBB0,0x0C42,0xE860,0xFB92,0xF4A2,0x0B82,0xE850,0xF832,0xFBA2,0x0002,0xE470,0x0022,0xF7A0,0xEFFE,0x0BC0,0x03D2,0xF860,0xF79E,0x0F92,0x0390,0xFFB0,0xF3FE,0x0FC0,0x0762,0xFF70,0xEFFE,0x1380,0x0362,0xFFB0,0xF42E,0x0810,0x07A2,0x07C0,0xF87E,0x0C82,0x0B94,0x0490,0xFB90,0x1062,0x0842,0x07B0,0xEC10,0x0C82,0x0850,0x13E2,0x2360,0x0420,0x0460,0x10B0,0x1FB0,0x03E0,0x0B80,0x0BF0,0x1430,0xFC00,0x0F90,0x0BC2,0x1BA0,0xFFC0,0x07C2,0x0B82,0x1BF0,0xF44E,0x0BB2,0x0FD2,0x14C2,0xF8A0,0x0792,0x0852,0x13E2,0xF850,0x00A0,0x0032,0x0C22,0xF0D0,0xF452,0xEFE0,0xEF7E,0xFC32,0xF072,0xF4C0,0xEBCE,0x03F0,0xFBA2,0xF400,0xE45E,0x0410,0xFFA2,0xF7D0,0xEBBE,0x0BD0,0xFBC2,0xFB80,0xF00E,0x0050,0x03D2,0x03D0,0xF0E0,0x0CA0,0x0384,0x0440,0xF3EE,0x0C52,0x00A2,0x0030,0xEC20,0x04C0,0x1022,0x0FD2,0x1F80,0x03F0,0x0830,0x0C82,0x17E0,0xFFB0,0x0410,0x0432,0x0870,0xF48E,0x0BD0,0x07B2,0x0F90,0xFBB0,0xFFF0,0x07A2,0x1410,0xF410,0x0022,0x0BC2,0x0CE0,0xF850,0xFFB2,0x0490,0x0BC0,0xECC0,0xFC70,0x0012,0x0400,0xF0B2,0x0402,0xF7D0,0xF37E,0x0BF2,0x0022,0xFC90,0xEFFE,0x0FC2,0xFC12,0xF84E,0xE87E,0x0480,0x07E2,0xFFB0,0xF7AE,0x0FC0,0x0002,0x07A0,0xF81E,0x1002,0x0422,0x0FD0,0xF8CE,0x1842,0x07A4,0x0880,0xFBB0,0x0CB0,0x0C62,0x0BF0,0xFBF0,0x10A0,0xF030,0x07D2,0x0BE0,0xF800,0xECA0,0x0482,0x0830,0xFBE0,0xF040,0xFC80,0x0810,0xF030,0xF410,0xF830,0x0BA0,0xF7A0,0xF3D2,0xFFF2,0x0840,0xEFF0,0xF400,0x03B2,0x0872,0xF030,0xEFB2,0x0042,0x03B2,0xEC40,0xFFE0,0xFFE2,0x0012,0xF420,0xF422,0xF7B0,0xE7CE,0x0BD2,0xF080,0x0070,0xEC2E,0x0FE2,0xF850,0x0070,0xF00E,0x0C42,0x0020,0x0030,0xF7AE,0x17B2,0x03D2,0x0400,0xF84E,0x17F0,0x0BE2,0x13A0,0xFC4E,0x1820,0x0792,0x1020,0xFB9E,0x1C10,0x1BC2,0x13C0,0xFBE0,0x2002,0xF040,0x13A2,0x0F80,0xFC30,0xF46E,0x0CC2,0x17B2,0x0010,0xFC10,0x0872,0x1000,0xF8B0,0x07BE,0x0BE2,0x13B0,0xFFE0,0xF410,0x0450,0x0C70,0xF420,0x03C0,0x0F82,0x1060,0xFFE0,0xFB70,0x13D2,0x0F90,0xF820,0xFC40,0x0FA2,0x0BE2,0xFC60,0xF012,0xFB80,0xEB5E,0x0802,0xF420,0x0090,0xF78E,0x13E2,0xFC02,0x0060,0xF40E,0x1090,0x0F90,0x0BD0,0xFBAE,0x1FD2,0x0002,0x0820,0xF85E,0x1800,0x0F82,0x1B60,0xFC3E,0x23C2,0x0B42,0x1BA0,0xFF7E,0x27E0,0x1012,0x1B70,0xFFC0,0x2040,0xFC70,0x1BA2,0x0FA0,0x0BA0,0x0002,0x1432,0x0FE0,0x0010,0xF83E,0x13E0,0x085E,0x07E0,0x005E,0x0842,0x0FEE,0x03D0,0xFC20,0x0FE2,0x1400,0x0780,0x0B90,0x1772,0x1410,0x07B0,0xFB10,0x17F2,0x0B20,0x03F0,0xFC1E,0x17B2,0x07CE,0x0830,0xE050,0xEF80,0xD38E,0x0382,0xEBE0,0xF810,0xDFBE,0x07D0,0xEC10,0xFFC0,0xE01E,0x0BB0,0xF820,0xF810,0xEBBE,0x0BA0,0xFBF0,0x07A0,0xF3EE,0x1B50,0x0752,0x0F30,0xF7EE,0x1B80,0x02F2,0x0FD0,0xF70E,0x13C0,0x0BE0,0x1390,0xF79E,0x1C00 diff --git a/F3:F303/MLX90640test/frame0.csv b/F3:F303/MLX90640test/frame0.csv new file mode 100644 index 0000000..fddb302 --- /dev/null +++ b/F3:F303/MLX90640test/frame0.csv @@ -0,0 +1 @@ +0xFFB3,0xFFAC,0xFFB4,0xFFAA,0xFFB3,0xFFAC,0xFFB6,0xFFA9,0xFFB2,0xFFA8,0xFFB4,0xFFA6,0xFFB1,0xFFA5,0xFFB4,0xFFA2,0xFFB4,0xFFA5,0xFFB4,0xFFA4,0xFFB6,0xFFA7,0xFFB5,0xFFA4,0xFFBA,0xFFA6,0xFFB8,0xFFA5,0xFFB6,0xFFAA,0xFFBD,0xFFA4,0xFFA9,0xFFA8,0xFFA6,0xFFA8,0xFFA9,0xFFA6,0xFFA6,0xFFA5,0xFFAA,0xFFA2,0xFFA5,0xFFA2,0xFFA9,0xFF9F,0xFFA5,0xFFA1,0xFFAD,0xFFA0,0xFFA6,0xFFA2,0xFFAB,0xFFA3,0xFFA8,0xFFA4,0xFFB2,0xFFA2,0xFFAB,0xFFA3,0xFFB0,0xFFA4,0xFFAF,0xFFA3,0xFFB2,0xFFAC,0xFFB4,0xFFAB,0xFFB1,0xFFAC,0xFFB1,0xFFA8,0xFFB1,0xFFA9,0xFFB3,0xFFA5,0xFFB2,0xFFA5,0xFFB1,0xFFA3,0xFFB5,0xFFA5,0xFFB1,0xFFA3,0xFFB6,0xFFA7,0xFFB5,0xFFA2,0xFFB8,0xFFA7,0xFFB7,0xFFA3,0xFFB6,0xFFA8,0xFFB9,0xFFA2,0xFFA7,0xFFA7,0xFFA4,0xFFA7,0xFFA9,0xFFA5,0xFFA4,0xFFA6,0xFFA8,0xFFA3,0xFFA4,0xFFA2,0xFFAC,0xFF9F,0xFFA2,0xFFA3,0xFFAD,0xFFA0,0xFFA4,0xFFA2,0xFFAC,0xFFA2,0xFFA8,0xFFA1,0xFFB1,0xFFA3,0xFFA8,0xFFA3,0xFFAD,0xFFA1,0xFFAC,0xFFA1,0xFFB3,0xFFAD,0xFFB5,0xFFA9,0xFFB2,0xFFAB,0xFFB2,0xFFA8,0xFFB4,0xFFA9,0xFFB1,0xFFA4,0xFFB1,0xFFA6,0xFFB3,0xFFA2,0xFFB5,0xFFA7,0xFFB2,0xFFA3,0xFFB2,0xFFA5,0xFFB4,0xFFA2,0xFFB6,0xFFA5,0xFFB8,0xFFA5,0xFFB4,0xFFA7,0xFFB9,0xFFA0,0xFFAA,0xFFA5,0xFFA4,0xFFA6,0xFFAA,0xFFA4,0xFFA2,0xFFA4,0xFFA9,0xFFA1,0xFFA2,0xFFA3,0xFFAA,0xFFA1,0xFFA3,0xFFA0,0xFFAD,0xFF9F,0xFFA4,0xFFA3,0xFFAB,0xFFA0,0xFFA3,0xFFA1,0xFFAD,0xFF9E,0xFFA9,0xFFA1,0xFFAB,0xFFA0,0xFFAA,0xFF9D,0xFFB0,0xFFAD,0xFFB2,0xFFAA,0xFFB2,0xFFAB,0xFFB3,0xFFA9,0xFFB8,0xFFAA,0xFFB6,0xFFA4,0xFFB2,0xFFA6,0xFFB1,0xFFA4,0xFFB2,0xFFA4,0xFFB2,0xFFA4,0xFFB2,0xFFA7,0xFFB5,0xFFA4,0xFFB2,0xFFA5,0xFFB4,0xFFA2,0xFFB4,0xFFA6,0xFFB9,0xFFA2,0xFFA5,0xFFA4,0xFFA1,0xFFA4,0xFFA6,0xFFA0,0xFFA1,0xFFA3,0xFFA8,0xFFA7,0xFFA1,0xFFAA,0xFFA6,0xFFA1,0xFFA1,0xFFA1,0xFFA8,0xFF9D,0xFFA2,0xFF9F,0xFFA8,0xFF9F,0xFFA2,0xFF9F,0xFFAB,0xFF9E,0xFFA4,0xFFA0,0xFFAB,0xFF9F,0xFFA8,0xFF9B,0xFFAF,0xFFAE,0xFFB3,0xFFA9,0xFFAF,0xFFAB,0xFFB4,0xFFA8,0xFFBB,0xFFAA,0xFFC6,0xFFA6,0xFFC0,0xFFA8,0xFFB6,0xFFA2,0xFFB0,0xFFA5,0xFFB1,0xFFA2,0xFFB3,0xFFA6,0xFFB2,0xFFA2,0xFFB4,0xFFA2,0xFFB4,0xFFA2,0xFFB4,0xFFA6,0xFFB7,0xFFA1,0xFFA3,0xFFA2,0xFF9F,0xFFA1,0xFFA5,0xFFA2,0xFFA2,0xFFA4,0xFFAA,0xFFB2,0xFFA4,0xFFB4,0xFFA8,0xFFAD,0xFFA1,0xFFA6,0xFFA8,0xFF9D,0xFFA2,0xFF9D,0xFFAB,0xFF9D,0xFFA3,0xFF9F,0xFFAD,0xFF9C,0xFFA3,0xFF9F,0xFFAB,0xFF9D,0xFFA6,0xFF9C,0xFFB3,0xFFAD,0xFFB3,0xFFA9,0xFFB4,0xFFAC,0xFFB5,0xFFA9,0xFFC8,0xFFAE,0xFFC8,0xFFAB,0xFFC9,0xFFAE,0xFFC2,0xFFA6,0xFFBD,0xFFA9,0xFFB5,0xFFA8,0xFFB2,0xFFAC,0xFFB0,0xFFA4,0xFFB3,0xFFA4,0xFFB2,0xFFA1,0xFFB2,0xFFA4,0xFFB4,0xFF9C,0xFFA4,0xFFA1,0xFF9F,0xFFA2,0xFFA7,0xFFA1,0xFFA2,0xFFAA,0xFFAD,0xFFB7,0xFFA7,0xFFB8,0xFFAD,0xFFB5,0xFFA3,0xFFB1,0xFFAF,0xFFA8,0xFFAA,0xFFA0,0xFFB2,0xFF9B,0xFFA5,0xFF9D,0xFFAC,0xFF9A,0xFFA4,0xFF9D,0xFFAB,0xFF9C,0xFFA5,0xFF9A,0xFFAE,0xFFAD,0xFFAD,0xFFA8,0xFFB1,0xFFAD,0xFFBB,0xFFAE,0xFFCB,0xFFB2,0xFFCE,0xFFAE,0xFFCB,0xFFB0,0xFFC5,0xFFAB,0xFFC6,0xFFB2,0xFFBD,0xFFB0,0xFFB2,0xFFB1,0xFFB0,0xFFA8,0xFFB3,0xFFAA,0xFFB1,0xFFA4,0xFFB1,0xFFA5,0xFFB4,0xFF9D,0xFF9F,0xFF9E,0xFF98,0xFF9F,0xFFA3,0xFFA0,0xFFA2,0xFFB3,0xFFAC,0xFFBB,0xFFA7,0xFFBF,0xFFAE,0xFFB7,0xFFA5,0xFFB3,0xFFB4,0xFFB0,0xFFAE,0xFFA6,0xFFB6,0xFF9B,0xFFAB,0xFF99,0xFFB4,0xFF9A,0xFFA7,0xFF9D,0xFFAC,0xFF9D,0xFFA5,0xFF9A,0xFFAC,0xFFAD,0xFFB0,0xFFA8,0xFFB1,0xFFAD,0xFFC3,0xFFAF,0xFFCA,0xFFB3,0xFFCD,0xFFAD,0xFFCA,0xFFB0,0xFFC8,0xFFAD,0xFFC6,0xFFB8,0xFFB9,0xFFB1,0xFFB2,0xFFB5,0xFFAF,0xFFAD,0xFFB3,0xFFAF,0xFFB0,0xFFA9,0xFFB0,0xFFA6,0xFFB4,0xFF9D,0xFF9E,0xFF9C,0xFF9C,0xFF9F,0xFFA1,0xFFA4,0xFFA0,0xFFB3,0xFFAB,0xFFB5,0xFFA4,0xFFB9,0xFFAC,0xFFB3,0xFFA7,0xFFB2,0xFFB5,0xFFAF,0xFFB1,0xFF9D,0xFFB7,0xFF9B,0xFFAD,0xFF9A,0xFFB6,0xFF9A,0xFFA8,0xFF9C,0xFFAA,0xFF9B,0xFFA5,0xFF9A,0xFFAE,0xFFAC,0xFFB0,0xFFAB,0xFFB6,0xFFAE,0xFFC0,0xFFAD,0xFFC3,0xFFB0,0xFFC2,0xFFAB,0xFFC4,0xFFB0,0xFFC2,0xFFB0,0xFFC4,0xFFB8,0xFFB2,0xFFB3,0xFFAE,0xFFB4,0xFFAE,0xFFAF,0xFFB0,0xFFAF,0xFFAF,0xFFA5,0xFFB2,0xFFA4,0xFFB3,0xFF9D,0xFF9E,0xFF9A,0xFF9A,0xFF9F,0xFFA1,0xFFA4,0xFF9D,0xFFAF,0xFFA7,0xFFAC,0xFF9F,0xFFAD,0xFFAA,0xFFB0,0xFFA7,0xFFAF,0xFFB5,0xFFA6,0xFFAF,0xFF9A,0xFFB5,0xFF98,0xFFAA,0xFF9B,0xFFB3,0xFF99,0xFFA5,0xFF9A,0xFFAA,0xFF9F,0xFFA5,0xFF9A,0xFFA7,0xFFAC,0xFFAA,0xFFA8,0xFFAA,0xFFAD,0xFFB0,0xFFAB,0xFFB9,0xFFAD,0xFFBF,0xFFAB,0xFFBD,0xFFAF,0xFFC0,0xFFB0,0xFFBA,0xFFB4,0xFFAE,0xFFAF,0xFFAC,0xFFB0,0xFFAC,0xFFAC,0xFFB0,0xFFAE,0xFFB0,0xFFA6,0xFFBB,0xFFA5,0xFFBC,0xFFA0,0xFF96,0xFF96,0xFF92,0xFF99,0xFF99,0xFF98,0xFF97,0xFF9E,0xFFA0,0xFFA0,0xFF9E,0xFFA7,0xFFA5,0xFFA8,0xFFA3,0xFFA9,0xFFAE,0xFF9A,0xFFA5,0xFF97,0xFFAE,0xFF95,0xFFA6,0xFF99,0xFFAF,0xFF98,0xFFA2,0xFFA0,0xFFAB,0xFFA9,0xFFA3,0xFFA6,0xFFA4,0xFFAE,0xFFA7,0xFFA5,0xFFA7,0xFFA7,0xFFA9,0xFFA6,0xFFAC,0xFFA6,0xFFB0,0xFFA3,0xFFB7,0xFFAD,0xFFB7,0xFFA9,0xFFAF,0xFFAB,0xFFA8,0xFFA8,0xFFAC,0xFFAD,0xFFAB,0xFFAA,0xFFAF,0xFFAE,0xFFB6,0xFFA7,0xFFBC,0xFFAB,0xFFC4,0xFFA4,0xFF93,0xFF95,0xFF90,0xFF94,0xFF94,0xFF93,0xFF92,0xFF96,0xFF99,0xFF93,0xFF96,0xFF97,0xFFA0,0xFF9E,0xFF9B,0xFF9E,0xFFA4,0xFF93,0xFF9D,0xFF94,0xFFA9,0xFF96,0xFF9F,0xFF96,0xFFAB,0xFF97,0xFFA1,0xFFA5,0xFFA9,0xFFAA,0xFFA4,0xFFA6,0xFFA4,0xFFAC,0xFFA4,0xFFA6,0xFFA6,0xFFA7,0xFFA6,0xFFA1,0xFFA5,0xFFA6,0xFFA4,0xFFA3,0xFFA7,0xFFA4,0xFFA7,0xFF9F,0xFFAB,0xFFA3,0xFFA9,0xFFA3,0xFFAA,0xFFA7,0xFFAB,0xFFA6,0xFFAE,0xFFAA,0xFFB7,0xFFA6,0xFFBB,0xFFAA,0xFFBB,0xFFA3,0xFF87,0xFF8A,0xFF84,0xFF8C,0xFF8A,0xFF8B,0xFF86,0xFF8B,0xFF8B,0xFF89,0xFF85,0xFF8B,0xFF8F,0xFF89,0xFF8A,0xFF8B,0xFF91,0xFF8A,0xFF8C,0xFF8D,0xFF9A,0xFF8B,0xFF95,0xFF8E,0xFF9E,0xFF93,0xFF98,0xFF9D,0xFF9E,0xFF9D,0xFF9A,0xFF99,0x4DFA,0x1A56,0x7FFF,0x1A56,0x7FFF,0x1A55,0x7FFF,0x1A55,0xFFB9,0xCE07,0x1584,0xD653,0xFFF9,0x0009,0x0000,0xFFFD,0x1976,0x03FD,0x0297,0x7FFF,0x1976,0x03FD,0x0297,0x7FFF,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0695,0x7FFF,0x1A56,0x7FFF,0x1A56,0x7FFF,0x1A55,0x7FFF,0xFFBD,0xF57A,0xCEF2,0xD8E0,0x0009,0xFFFD,0xFFFC,0x0000,0x00ED,0x0046,0x2AD6,0x0035,0x00EE,0x0046,0x2AD6,0x0035,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x1901,0x0000 diff --git a/F3:F303/MLX90640test/frame1.csv b/F3:F303/MLX90640test/frame1.csv new file mode 100644 index 0000000..137b0cf --- /dev/null +++ b/F3:F303/MLX90640test/frame1.csv @@ -0,0 +1 @@ +0xFFB3,0xFFAD,0xFFB4,0xFFAA,0xFFB3,0xFFAD,0xFFB6,0xFFA8,0xFFB2,0xFFA9,0xFFB4,0xFFA4,0xFFB1,0xFFA6,0xFFB4,0xFFA1,0xFFB4,0xFFA8,0xFFB4,0xFFA1,0xFFB6,0xFFA8,0xFFB5,0xFFA2,0xFFBA,0xFFA7,0xFFB8,0xFFA3,0xFFB6,0xFFAA,0xFFBD,0xFFA3,0xFFAC,0xFFA8,0xFFA5,0xFFA8,0xFFAC,0xFFA6,0xFFA5,0xFFA5,0xFFAA,0xFFA2,0xFFA2,0xFFA2,0xFFAB,0xFF9F,0xFFA0,0xFFA1,0xFFAB,0xFFA0,0xFFA4,0xFFA2,0xFFAB,0xFFA3,0xFFA6,0xFFA4,0xFFB1,0xFFA2,0xFFA9,0xFFA3,0xFFB0,0xFFA4,0xFFAD,0xFFA3,0xFFB2,0xFFAF,0xFFB4,0xFFA8,0xFFB1,0xFFAE,0xFFB1,0xFFA5,0xFFB1,0xFFAA,0xFFB3,0xFFA3,0xFFB2,0xFFA7,0xFFB1,0xFFA3,0xFFB5,0xFFA6,0xFFB1,0xFFA0,0xFFB6,0xFFA7,0xFFB5,0xFFA0,0xFFB8,0xFFA7,0xFFB7,0xFFA2,0xFFB6,0xFFA8,0xFFB9,0xFF9F,0xFFAA,0xFFA7,0xFFA4,0xFFA7,0xFFA9,0xFFA5,0xFFA3,0xFFA6,0xFFA9,0xFFA3,0xFFA3,0xFFA2,0xFFAA,0xFF9F,0xFFA2,0xFFA3,0xFFAD,0xFFA0,0xFFA2,0xFFA2,0xFFAD,0xFFA2,0xFFA6,0xFFA1,0xFFB1,0xFFA3,0xFFA7,0xFFA3,0xFFAD,0xFFA1,0xFFA9,0xFFA1,0xFFB3,0xFFAF,0xFFB5,0xFFAA,0xFFB2,0xFFAD,0xFFB2,0xFFA6,0xFFB4,0xFFAB,0xFFB1,0xFFA4,0xFFB1,0xFFA8,0xFFB3,0xFFA0,0xFFB5,0xFFA6,0xFFB2,0xFFA3,0xFFB2,0xFFA8,0xFFB4,0xFFA1,0xFFB6,0xFFA6,0xFFB8,0xFFA2,0xFFB4,0xFFA7,0xFFB9,0xFF9C,0xFFAB,0xFFA5,0xFFA3,0xFFA6,0xFFAA,0xFFA4,0xFFA4,0xFFA4,0xFFB0,0xFFA1,0xFFA4,0xFFA3,0xFFA9,0xFFA1,0xFFA0,0xFFA0,0xFFAE,0xFF9F,0xFFA2,0xFFA3,0xFFAD,0xFFA0,0xFFA4,0xFFA1,0xFFAE,0xFF9E,0xFFA8,0xFFA1,0xFFAC,0xFFA0,0xFFA8,0xFF9D,0xFFB0,0xFFAE,0xFFB2,0xFFA8,0xFFB2,0xFFAC,0xFFB3,0xFFA9,0xFFB8,0xFFB8,0xFFB6,0xFFAB,0xFFB2,0xFFAA,0xFFB1,0xFFA1,0xFFB2,0xFFA5,0xFFB2,0xFFA0,0xFFB2,0xFFA5,0xFFB5,0xFFA1,0xFFB2,0xFFA6,0xFFB4,0xFFA3,0xFFB4,0xFFA5,0xFFB9,0xFF9B,0xFFA6,0xFFA4,0xFFA2,0xFFA4,0xFFA7,0xFFA0,0xFFA2,0xFFA3,0xFFBB,0xFFA7,0xFFAF,0xFFAA,0xFFAF,0xFFA1,0xFFA1,0xFFA1,0xFFA9,0xFF9D,0xFFA0,0xFF9F,0xFFA8,0xFF9F,0xFFA2,0xFF9F,0xFFAC,0xFF9E,0xFFA4,0xFFA0,0xFFAC,0xFF9F,0xFFA6,0xFF9B,0xFFAF,0xFFAF,0xFFB3,0xFFA9,0xFFAF,0xFFAF,0xFFB4,0xFFB0,0xFFBB,0xFFC0,0xFFC6,0xFFB7,0xFFC0,0xFFB7,0xFFB6,0xFFA7,0xFFB0,0xFFA6,0xFFB1,0xFFA0,0xFFB3,0xFFA4,0xFFB2,0xFFA0,0xFFB4,0xFFA4,0xFFB4,0xFFA0,0xFFB4,0xFFA5,0xFFB7,0xFF9A,0xFFA6,0xFFA2,0xFF9F,0xFFA1,0xFFA8,0xFFA2,0xFFAA,0xFFA4,0xFFBE,0xFFB2,0xFFB6,0xFFB4,0xFFBE,0xFFAD,0xFFAC,0xFFA6,0xFFAC,0xFF9D,0xFFA0,0xFF9D,0xFFA9,0xFF9D,0xFFA0,0xFF9F,0xFFAA,0xFF9C,0xFFA1,0xFF9F,0xFFAC,0xFF9D,0xFFA2,0xFF9C,0xFFB3,0xFFAF,0xFFB3,0xFFAA,0xFFB4,0xFFB1,0xFFB5,0xFFBB,0xFFC8,0xFFC4,0xFFC8,0xFFBC,0xFFC9,0xFFBF,0xFFC2,0xFFB5,0xFFBD,0xFFB0,0xFFB5,0xFFA0,0xFFB2,0xFFA6,0xFFB0,0xFF9E,0xFFB3,0xFFA3,0xFFB2,0xFF9E,0xFFB2,0xFFA4,0xFFB4,0xFF9B,0xFFA8,0xFFA1,0xFF9D,0xFFA2,0xFFAC,0xFFA1,0xFFB1,0xFFAA,0xFFC7,0xFFB7,0xFFB9,0xFFB8,0xFFC0,0xFFB5,0xFFB2,0xFFB1,0xFFBB,0xFFA8,0xFFA5,0xFFA0,0xFFA7,0xFF9B,0xFF9C,0xFF9D,0xFFA9,0xFF9A,0xFFA1,0xFF9D,0xFFA9,0xFF9C,0xFFA5,0xFF9A,0xFFAE,0xFFAD,0xFFAD,0xFFA7,0xFFB1,0xFFB8,0xFFBB,0xFFC0,0xFFCB,0xFFCA,0xFFCE,0xFFC1,0xFFCB,0xFFBF,0xFFC5,0xFFB6,0xFFC6,0xFFB6,0xFFBD,0xFFA0,0xFFB2,0xFFA4,0xFFB0,0xFF9E,0xFFB3,0xFFA1,0xFFB1,0xFF9F,0xFFB1,0xFFA4,0xFFB4,0xFF9C,0xFFA3,0xFF9E,0xFF9A,0xFF9F,0xFFAE,0xFFA0,0xFFB1,0xFFB3,0xFFC1,0xFFBB,0xFFB9,0xFFBF,0xFFBF,0xFFB7,0xFFB1,0xFFB3,0xFFB8,0xFFB0,0xFFA0,0xFFA6,0xFFA7,0xFF9B,0xFF9E,0xFF99,0xFFAB,0xFF9A,0xFFA0,0xFF9D,0xFFAA,0xFF9D,0xFFA2,0xFF9A,0xFFAC,0xFFAF,0xFFB0,0xFFA9,0xFFB1,0xFFBD,0xFFC3,0xFFBA,0xFFCA,0xFFC2,0xFFCD,0xFFBC,0xFFCA,0xFFBE,0xFFC8,0xFFB7,0xFFC6,0xFFB1,0xFFB9,0xFFA0,0xFFB2,0xFFA5,0xFFAF,0xFF9D,0xFFB3,0xFFA4,0xFFB0,0xFFA0,0xFFB0,0xFFA3,0xFFB4,0xFF9B,0xFF9E,0xFF9C,0xFF9C,0xFF9F,0xFFAE,0xFFA4,0xFFAE,0xFFB3,0xFFB8,0xFFB5,0xFFAF,0xFFB9,0xFFBA,0xFFB3,0xFFAF,0xFFB2,0xFFB4,0xFFAF,0xFF9D,0xFF9D,0xFFA5,0xFF9B,0xFF9D,0xFF9A,0xFFA9,0xFF9A,0xFFA1,0xFF9C,0xFFA8,0xFF9B,0xFFA3,0xFF9A,0xFFAE,0xFFAF,0xFFB0,0xFFA8,0xFFB6,0xFFB5,0xFFC0,0xFFB5,0xFFC3,0xFFBC,0xFFC2,0xFFB6,0xFFC4,0xFFBD,0xFFC2,0xFFB0,0xFFC4,0xFFA9,0xFFB2,0xFF9E,0xFFAE,0xFFA3,0xFFAE,0xFF9E,0xFFB0,0xFFA3,0xFFAF,0xFFA1,0xFFB2,0xFFA6,0xFFB3,0xFF9E,0xFF9E,0xFF9A,0xFF98,0xFF9F,0xFFA4,0xFFA4,0xFFA2,0xFFAF,0xFFB0,0xFFAC,0xFFAA,0xFFAD,0xFFB6,0xFFB0,0xFFAA,0xFFAF,0xFFAB,0xFFA6,0xFF99,0xFF9A,0xFFA3,0xFF98,0xFF99,0xFF9B,0xFFA7,0xFF99,0xFFA2,0xFF9A,0xFFAE,0xFF9F,0xFFA3,0xFF9A,0xFFA7,0xFFAC,0xFFAA,0xFFA5,0xFFAA,0xFFAA,0xFFB0,0xFFA8,0xFFB9,0xFFB1,0xFFBF,0xFFB2,0xFFBD,0xFFB8,0xFFC0,0xFFA7,0xFFBA,0xFFA4,0xFFAE,0xFF9D,0xFFAC,0xFFA3,0xFFAC,0xFF9D,0xFFB0,0xFFA4,0xFFB0,0xFFAA,0xFFBB,0xFFB3,0xFFBC,0xFFA3,0xFF99,0xFF96,0xFF8F,0xFF99,0xFF97,0xFF98,0xFF93,0xFF9E,0xFF9E,0xFFA0,0xFF9E,0xFFA7,0xFFAC,0xFFA8,0xFF9F,0xFFA9,0xFFA1,0xFF9A,0xFF94,0xFF97,0xFFA0,0xFF95,0xFF98,0xFF99,0xFFA6,0xFF98,0xFFA5,0xFFA0,0xFFB8,0xFFA9,0xFFAD,0xFFA6,0xFFA4,0xFFAC,0xFFA7,0xFFA3,0xFFA7,0xFFA7,0xFFA9,0xFFA3,0xFFAC,0xFFA6,0xFFB0,0xFFA4,0xFFB7,0xFFAD,0xFFB7,0xFFA1,0xFFAF,0xFF9F,0xFFA8,0xFF9C,0xFFAC,0xFFA3,0xFFAB,0xFF9E,0xFFAF,0xFFAA,0xFFB6,0xFFAE,0xFFBC,0xFFBA,0xFFC4,0xFFA9,0xFF95,0xFF95,0xFF8E,0xFF94,0xFF96,0xFF93,0xFF91,0xFF96,0xFF99,0xFF93,0xFF94,0xFF97,0xFF9E,0xFF9E,0xFF94,0xFF9E,0xFF9D,0xFF93,0xFF91,0xFF94,0xFF9F,0xFF96,0xFF95,0xFF96,0xFFA8,0xFF97,0xFFA6,0xFFA5,0xFFB6,0xFFAA,0xFFAB,0xFFA6,0xFFA4,0xFFAA,0xFFA4,0xFFA2,0xFFA6,0xFFA7,0xFFA6,0xFF9E,0xFFA5,0xFFA4,0xFFA4,0xFF9F,0xFFA7,0xFFA1,0xFFA7,0xFF9B,0xFFAB,0xFFA0,0xFFA9,0xFF9D,0xFFAA,0xFFA1,0xFFAB,0xFF9F,0xFFAE,0xFFAE,0xFFB7,0xFFAD,0xFFBB,0xFFB5,0xFFBB,0xFFA3,0xFF87,0xFF8A,0xFF80,0xFF8C,0xFF8B,0xFF8B,0xFF83,0xFF8B,0xFF8B,0xFF89,0xFF86,0xFF8B,0xFF8E,0xFF89,0xFF86,0xFF8B,0xFF93,0xFF8A,0xFF87,0xFF8D,0xFF95,0xFF8B,0xFF8D,0xFF8E,0xFFA6,0xFF93,0xFFA0,0xFF9D,0xFFA9,0xFF9D,0xFF9C,0xFF99,0x4DFA,0x1A58,0x7FFF,0x1A58,0x7FFF,0x1A57,0x7FFF,0x1A57,0xFFB9,0xCE35,0x1584,0xD64E,0xFFF9,0x000B,0x0000,0xFFFE,0x1976,0x03FD,0x0297,0x7FFF,0x1976,0x03FD,0x0297,0x7FFF,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0696,0x7FFF,0x1A58,0x7FFF,0x1A58,0x7FFF,0x1A57,0x7FFF,0xFFBF,0xF57A,0xCF18,0xD8E0,0x000A,0xFFFD,0xFFFE,0x0000,0x00F1,0x0046,0x2AC3,0x0035,0x00F1,0x0046,0x2AC3,0x0035,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x1901,0x0001 diff --git a/F3:F303/MLX90640test/hardware.c b/F3:F303/MLX90640test/hardware.c new file mode 100644 index 0000000..683a743 --- /dev/null +++ b/F3:F303/MLX90640test/hardware.c @@ -0,0 +1,34 @@ +/* + * This file is part of the mlxtest project. + * Copyright 2025 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hardware.h" + +static inline void gpio_setup(){ + RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; // for USART and LEDs + for(int i = 0; i < 10000; ++i) nop(); + // USB - alternate function 14 @ pins PA11/PA12; SWD - AF0 @PA13/14 + GPIOA->AFR[1] = AFRf(14, 11) | AFRf(14, 12); + GPIOA->MODER = MODER_AF(11) | MODER_AF(12) | MODER_AF(13) | MODER_AF(14) | MODER_O(15); + GPIOB->MODER = MODER_O(0) | MODER_O(1); + GPIOB->ODR = 1; +} + +void hw_setup(){ + gpio_setup(); +} + diff --git a/F3:F303/MLX90640test/hardware.h b/F3:F303/MLX90640test/hardware.h new file mode 100644 index 0000000..5f9286a --- /dev/null +++ b/F3:F303/MLX90640test/hardware.h @@ -0,0 +1,31 @@ +/* + * This file is part of the mlxtest project. + * Copyright 2025 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#define USBPU_port GPIOA +#define USBPU_pin (1<<15) +#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin) +#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin) + +extern volatile uint32_t Tms; + +void hw_setup(); + diff --git a/F3:F303/MLX90640test/kta.csv b/F3:F303/MLX90640test/kta.csv new file mode 100644 index 0000000..110b88a --- /dev/null +++ b/F3:F303/MLX90640test/kta.csv @@ -0,0 +1 @@ +0.00671387,0.00646973,0.00720215,0.00598145,0.00671387,0.00598145,0.00671387,0.00598145,0.00671387,0.00598145,0.00671387,0.00598145,0.00671387,0.00598145,0.00671387,0.00598145,0.00671387,0.00598145,0.00720215,0.00598145,0.00671387,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00683594,0.00585938,0.00585938,0.00634766,0.00683594,0.00585938,0.00585938,0.00634766,0.00683594,0.00585938,0.00585938,0.00634766,0.00683594,0.00585938,0.00585938,0.00634766,0.00732422,0.00585938,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00683594,0.00683594,0.00671387,0.00646973,0.00671387,0.00598145,0.00671387,0.00646973,0.00720215,0.00598145,0.00769043,0.00598145,0.00671387,0.00598145,0.00671387,0.00598145,0.00671387,0.00598145,0.00720215,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00769043,0.00646973,0.00683594,0.00585938,0.00585938,0.00634766,0.00683594,0.00634766,0.00585938,0.00634766,0.00683594,0.00585938,0.00634766,0.00634766,0.00683594,0.00585938,0.00634766,0.00634766,0.00732422,0.00585938,0.00634766,0.00683594,0.00732422,0.00585938,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00683594,0.00634766,0.00671387,0.00646973,0.00720215,0.00598145,0.00671387,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00671387,0.00598145,0.00720215,0.00646973,0.00671387,0.00646973,0.00720215,0.00646973,0.00720215,0.00598145,0.00769043,0.00646973,0.00720215,0.00646973,0.00769043,0.00646973,0.00720215,0.00646973,0.00671387,0.00695801,0.00769043,0.00646973,0.00683594,0.00585938,0.00634766,0.00634766,0.00683594,0.00585938,0.00585938,0.00634766,0.00732422,0.00585938,0.00634766,0.00634766,0.00683594,0.00634766,0.00585938,0.00634766,0.00781250,0.00585938,0.00634766,0.00634766,0.00781250,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00634766,0.00683594,0.00634766,0.00683594,0.00634766,0.00671387,0.00646973,0.00720215,0.00646973,0.00671387,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00671387,0.00598145,0.00720215,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00769043,0.00646973,0.00720215,0.00646973,0.00769043,0.00646973,0.00720215,0.00695801,0.00769043,0.00646973,0.00683594,0.00585938,0.00585938,0.00634766,0.00683594,0.00634766,0.00634766,0.00634766,0.00683594,0.00585938,0.00585938,0.00634766,0.00683594,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00683594,0.00781250,0.00634766,0.00683594,0.00683594,0.00671387,0.00695801,0.00720215,0.00598145,0.00671387,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00720215,0.00646973,0.00769043,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00769043,0.00646973,0.00683594,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00585938,0.00634766,0.00732422,0.00634766,0.00634766,0.00683594,0.00781250,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00683594,0.00683594,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00598145,0.00720215,0.00695801,0.00671387,0.00598145,0.00769043,0.00646973,0.00720215,0.00646973,0.00769043,0.00646973,0.00720215,0.00646973,0.00769043,0.00646973,0.00769043,0.00646973,0.00769043,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00769043,0.00646973,0.00732422,0.00585938,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00683594,0.00732422,0.00683594,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00781250,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00683594,0.00720215,0.00646973,0.00720215,0.00646973,0.00671387,0.00695801,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00598145,0.00720215,0.00646973,0.00769043,0.00646973,0.00769043,0.00695801,0.00769043,0.00646973,0.00769043,0.00695801,0.00769043,0.00646973,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00683594,0.00683594,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00683594,0.00781250,0.00634766,0.00683594,0.00683594,0.00732422,0.00634766,0.00683594,0.00683594,0.00720215,0.00695801,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00769043,0.00695801,0.00720215,0.00598145,0.00769043,0.00695801,0.00769043,0.00646973,0.00769043,0.00695801,0.00769043,0.00646973,0.00720215,0.00695801,0.00769043,0.00646973,0.00732422,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00683594,0.00634766,0.00781250,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00683594,0.00634766,0.00769043,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00598145,0.00720215,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00769043,0.00695801,0.00720215,0.00646973,0.00769043,0.00646973,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00695801,0.00732422,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00683594,0.00732422,0.00585938,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00683594,0.00781250,0.00634766,0.00683594,0.00634766,0.00732422,0.00634766,0.00683594,0.00634766,0.00720215,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00769043,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00769043,0.00646973,0.00769043,0.00695801,0.00769043,0.00646973,0.00720215,0.00695801,0.00769043,0.00646973,0.00732422,0.00634766,0.00634766,0.00683594,0.00683594,0.00634766,0.00634766,0.00683594,0.00683594,0.00634766,0.00634766,0.00683594,0.00683594,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00683594,0.00683594,0.00720215,0.00695801,0.00720215,0.00646973,0.00671387,0.00695801,0.00769043,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00671387,0.00695801,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00769043,0.00646973,0.00732422,0.00634766,0.00634766,0.00683594,0.00683594,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00634766,0.00683594,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00683594,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00683594,0.00634766,0.00720215,0.00695801,0.00720215,0.00646973,0.00769043,0.00695801,0.00720215,0.00646973,0.00671387,0.00646973,0.00671387,0.00646973,0.00671387,0.00695801,0.00671387,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00720215,0.00695801,0.00720215,0.00646973,0.00671387,0.00695801,0.00671387,0.00646973,0.00683594,0.00634766,0.00634766,0.00683594,0.00683594,0.00634766,0.00634766,0.00634766,0.00683594,0.00634766,0.00634766,0.00634766,0.00683594,0.00634766,0.00634766,0.00634766,0.00683594,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00732422,0.00634766,0.00634766,0.00634766,0.00683594,0.00634766,0.00634766,0.00634766 diff --git a/F3:F303/MLX90640test/kv.csv b/F3:F303/MLX90640test/kv.csv new file mode 100644 index 0000000..22da24f --- /dev/null +++ b/F3:F303/MLX90640test/kv.csv @@ -0,0 +1 @@ +0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.43750000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000,0.37500000 diff --git a/F3:F303/MLX90640test/main.c b/F3:F303/MLX90640test/main.c new file mode 100644 index 0000000..f490f7b --- /dev/null +++ b/F3:F303/MLX90640test/main.c @@ -0,0 +1,56 @@ +/* + * This file is part of the mlxtest project. + * Copyright 2025 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hardware.h" +#include "proto.h" +#include "usb_dev.h" + +#define MAXSTRLEN RBINSZ + +volatile uint32_t Tms = 0; + +void sys_tick_handler(void){ + ++Tms; +} + +int main(void){ + char inbuff[MAXSTRLEN+1]; + if(StartHSE()){ + SysTick_Config((uint32_t)72000); // 1ms + }else{ + StartHSI(); + SysTick_Config((uint32_t)48000); // 1ms + } + hw_setup(); + USBPU_OFF(); + USB_setup(); + uint32_t ctr = Tms; + USBPU_ON(); + while(1){ + if(Tms - ctr > 499){ + ctr = Tms; + pin_toggle(GPIOB, 1 << 1 | 1 << 0); // toggle LED @ PB0 + } + int l = USB_receivestr(inbuff, MAXSTRLEN); + if(l < 0) USB_sendstr("ERROR: USB buffer overflow or string was too long\n"); + else if(l){ + const char *ans = parse_cmd(inbuff); + if(ans) USB_sendstr(ans); + } + } +} diff --git a/F3:F303/MLX90640test/mlx90640.c b/F3:F303/MLX90640test/mlx90640.c new file mode 100644 index 0000000..ced4497 --- /dev/null +++ b/F3:F303/MLX90640test/mlx90640.c @@ -0,0 +1,448 @@ +/* + * This file is part of the mlxtest project. + * Copyright 2022 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "strfunc.h" + +#include "mlx90640.h" +#include "mlx90640_regs.h" +#include "testdata.h" + +static const char *OK = "OK\n", *OKs = "OK ", *NOTEQ = "NOT equal!\n", *NOTEQi = "NOT equal on index "; + +// tolerance of floating point comparison +#define FP_TOLERANCE (1e-3) + +static fp_t mlx_image[MLX_PIXNO] = {0}; // ready image + +void dumpIma(const fp_t im[MLX_PIXNO]){ + for(int row = 0; row < MLX_H; ++row){ + for(int col = 0; col < MLX_W; ++col){ + printfl(*im++, 1); + USB_putbyte(' '); + } + newline(); + } +} + +#define GRAY_LEVELS (16) +// 16-level character set ordered by fill percentage (provided by user) +static const char* CHARS_16 = " .':;+*oxX#&%B$@"; +void drawIma(const fp_t im[MLX_PIXNO]){ + // Find min and max values + fp_t min_val = im[0], max_val = im[0]; + const fp_t *iptr = im; + for(int row = 0; row < MLX_H; ++row){ + for(int col = 0; col < MLX_W; ++col){ + fp_t cur = *iptr++; + if(cur < min_val) min_val = cur; + else if(cur > max_val) max_val = cur; + } + } + fp_t range = max_val - min_val; + if(fabsf(range) < 0.001) range = 1.; // solid fill -> blank + // Generate and print ASCII art + iptr = im; + newline(); + for(int row = 0; row < MLX_H; ++row){ + for(int col = 0; col < MLX_W; ++col){ + fp_t normalized = ((*iptr++) - min_val) / range; + // Map to character index (0 to 15) + int index = (int)(normalized * (GRAY_LEVELS-1) + 0.5); + // Ensure we stay within bounds + if(index < 0) index = 0; + else if(index > (GRAY_LEVELS-1)) index = (GRAY_LEVELS-1); + USB_putbyte(CHARS_16[index]); + } + newline(); + } + newline(); +} + +static void chki(const char *name, int16_t param, int16_t standard){ + USB_sendstr(name); USB_sendstr(" - "); + printi(param); USB_sendstr(" - "); + printi(standard); USB_sendstr(" - "); + if(param != standard){ + USB_sendstr(NOTEQ); + } + USB_sendstr(OK); +} +static void chkf(const char *name, fp_t param, fp_t standard){ + USB_sendstr(name); USB_sendstr(" - "); + printfl(param, 3); USB_sendstr(" - "); + printfl(standard, 3); USB_sendstr(" - "); + fp_t diff = (fabsf(param) + fabsf(standard)) * FP_TOLERANCE; + if(fabsf(param - standard) > diff){ + USB_sendstr(NOTEQ); + } + USB_sendstr(OK); +} +static void chkfa(const char *name, const fp_t *ap, const fp_t *as, int n){ + USB_sendstr(name); USB_sendstr(" - (array) - (size"); + printi(n); USB_sendstr(") - "); + for(int i = 0; i < n; ++i){ + fp_t diff = (fabsf(as[i]) + fabsf(ap[i])) * FP_TOLERANCE; + if(fabsf(ap[i] - as[i]) > diff){ + USB_sendstr(NOTEQi); printi(i); newline(); + return; + } + } + USB_sendstr(OKs); + int nmax = (n < 5) ? n : 5; + for(int i = 0; i < nmax; ++i){ + printfl(ap[i], 2); USB_putbyte(' '); + } + newline(); +} +static void chku8a(const char *name, const uint8_t *ap, const uint8_t *as, int n){ + USB_sendstr(name); USB_sendstr(" - (array) - (size"); + printi(n); USB_sendstr(") - "); + for(int i = 0; i < n; ++i){ + if(ap[i] != as[i]){ + USB_sendstr(NOTEQi); printi(i); newline(); + return; + } + } + USB_sendstr(OKs); + int nmax = (n < 5) ? n : 5; + for(int i = 0; i < nmax; ++i){ + printu(ap[i]); USB_putbyte(' '); + } + newline(); +} +void chkImage(const fp_t Image[MLX_PIXNO], const fp_t To[MLX_PIXNO]){ + chkfa("Image", Image, To, MLX_PIXNO); +} + +void dump_parameters(MLX90640_params *params, const MLX90640_params *standard){ + USB_sendstr("\n############################################\n# name - value - standard - test condition #\n"); + USB_sendstr("############################################\n"); +#define CHKI(f) do{chki(#f, params->f, standard->f);}while(0) +#define CHKF(f) do{chkf(#f, params->f, standard->f);}while(0) +#define CHKFA(f, n) do{chkfa(#f, params->f, standard->f, n);}while(0) +#define CHKU8A(f, n) do{chku8a(#f, params->f, standard->f, n);}while(0) + CHKI(kVdd); + CHKI(vdd25); + CHKF(KvPTAT); + CHKI(vPTAT25); + CHKF(alphaPTAT); + CHKI(gainEE); + CHKF(tgc); + CHKF(cpKv); + CHKF(cpKta); + CHKF(KsTa); + CHKFA(CT, 3); + CHKFA(KsTo, 4); + CHKFA(alpha, MLX_PIXNO); + CHKFA(offset, MLX_PIXNO); + CHKFA(kta, MLX_PIXNO); + CHKFA(kv, 4); + CHKFA(cpAlpha, 2); + CHKI(resolEE); + CHKI(cpOffset[0]); CHKI(cpOffset[1]); + CHKU8A(outliers, MLX_PIXNO); +#undef CHKI +#undef CHKF +} + +/***************************************************************************** + Calculate parameters & values + *****************************************************************************/ + +// fill OCC/ACC row/col arrays +static void occacc(int8_t *arr, int l, const uint16_t *regstart){ + int n = l >> 2; // divide by 4 + int8_t *p = arr; + for(int i = 0; i < n; ++i){ + register uint16_t val = *regstart++; + *p++ = (val & 0x000F) >> 0; + *p++ = (val & 0x00F0) >> 4; + *p++ = (val & 0x0F00) >> 8; + *p++ = (val ) >> 12; + } + for(int i = 0; i < l; ++i, ++arr){ + if(*arr > 0x07) *arr -= 0x10; + } +} + +// get all parameters' values from `dataarray`, return FALSE if something failed +int get_parameters(const uint16_t dataarray[MLX_DMA_MAXLEN], MLX90640_params *params){ + #define CREG_VAL(reg) dataarray[CREG_IDX(reg)] + int8_t i8; + int16_t i16; + uint16_t *pu16; + uint16_t val = CREG_VAL(REG_VDD); + i8 = (int8_t) (val >> 8); + params->kVdd = i8 * 32; // keep sign + if(params->kVdd == 0) return FALSE; + i16 = val & 0xFF; + params->vdd25 = ((i16 - 0x100) * 32) - (1<<13); + val = CREG_VAL(REG_KVTPTAT); + i16 = (val & 0xFC00) >> 10; + if(i16 > 0x1F) i16 -= 0x40; + params->KvPTAT = (fp_t)i16 / (1<<12); + i16 = (val & 0x03FF); + if(i16 > 0x1FF) i16 -= 0x400; + params->KtPTAT = (fp_t)i16 / 8.; + params->vPTAT25 = (int16_t) CREG_VAL(REG_PTAT); + val = CREG_VAL(REG_APTATOCCS) >> 12; + params->alphaPTAT = val / 4. + 8.; + params->gainEE = (int16_t)CREG_VAL(REG_GAIN); + if(params->gainEE == 0) return FALSE; + int8_t occRow[MLX_H]; + int8_t occColumn[MLX_W]; + occacc(occRow, MLX_H, &CREG_VAL(REG_OCCROW14)); + occacc(occColumn, MLX_W, &CREG_VAL(REG_OCCCOL14)); + int8_t accRow[MLX_H]; + int8_t accColumn[MLX_W]; + occacc(accRow, MLX_H, &CREG_VAL(REG_ACCROW14)); + occacc(accColumn, MLX_W, &CREG_VAL(REG_ACCCOL14)); + val = CREG_VAL(REG_APTATOCCS); + // need to do multiplication instead of bitshift, so: + fp_t occRemScale = 1<<(val&0x0F), + occColumnScale = 1<<((val>>4)&0x0F), + occRowScale = 1<<((val>>8)&0x0F); + int16_t offavg = (int16_t) CREG_VAL(REG_OSAVG); + // even/odd column/row numbers are for starting from 1, so for starting from 0 we should swap them: + // even - for 1,3,5,...; odd - for 0,2,4,... etc + int8_t ktaavg[4]; + // 0 - odd row, odd col; 1 - odd row even col; 2 - even row, odd col; 3 - even row, even col + val = CREG_VAL(REG_KTAAVGODDCOL); + ktaavg[2] = (int8_t)(val & 0xFF); // odd col (1,3,..), even row (2,4,..) -> col 0,2,..; row 1,3,.. + ktaavg[0] = (int8_t)(val >> 8); // odd col, odd row -> col 0,2,..; row 0,2,.. + val = CREG_VAL(REG_KTAAVGEVENCOL); + ktaavg[3] = (int8_t)(val & 0xFF); // even col, even row -> col 1,3,..; row 1,3,.. + ktaavg[1] = (int8_t)(val >> 8); // even col, odd row -> col 1,3,..; row 0,2,.. + // so index of ktaavg is 2*(row&1)+(col&1) + val = CREG_VAL(REG_KTAVSCALE); + uint8_t scale1 = ((val & 0xFF)>>4) + 8, scale2 = (val&0xF); + if(scale1 == 0 || scale2 == 0) return FALSE; + fp_t mul = (fp_t)(1<alpha; + uint32_t diva32 = 1 << (val >> 12); + fp_t diva = (fp_t)(diva32); + diva *= (fp_t)(1<<30); // alpha_scale + fp_t accRowScale = 1<<((val & 0x0f00)>>8), + accColumnScale = 1<<((val & 0x00f0)>>4), + accRemScale = 1<<(val & 0x0f); + pu16 = (uint16_t*)&CREG_VAL(REG_OFFAK1); + fp_t *kta = params->kta, *offset = params->offset; + uint8_t *ol = params->outliers; + for(int row = 0; row < MLX_H; ++row){ + int idx = (row&1)<<1; + for(int col = 0; col < MLX_W; ++col){ + // offset + register uint16_t rv = *pu16++; + i16 = (rv & 0xFC00) >> 10; + if(i16 > 0x1F) i16 -= 0x40; + *offset++ = (fp_t)offavg + (fp_t)occRow[row]*occRowScale + (fp_t)occColumn[col]*occColumnScale + (fp_t)i16*occRemScale; + // kta + i16 = (rv & 0xF) >> 1; + if(i16 > 0x03) i16 -= 0x08; + *kta++ = (ktaavg[idx|(col&1)] + i16*mul) / div; + // alpha + i16 = (rv & 0x3F0) >> 4; + if(i16 > 0x1F) i16 -= 0x40; + fp_t oft = (fp_t)a_r + accRow[row]*accRowScale + accColumn[col]*accColumnScale +i16*accRemScale; + *a++ = oft / diva; + *ol++ = (rv&1) ? 1 : 0; + } + } + scale1 = (CREG_VAL(REG_KTAVSCALE) >> 8) & 0xF; // kvscale + div = (fp_t)(1<> 12; if(i16 > 0x07) i16 -= 0x10; + ktaavg[0] = (int8_t)i16; // odd col, odd row + i16 = (val & 0xF0) >> 4; if(i16 > 0x07) i16 -= 0x10; + ktaavg[1] = (int8_t)i16; // even col, odd row + i16 = (val & 0x0F00) >> 8; if(i16 > 0x07) i16 -= 0x10; + ktaavg[2] = (int8_t)i16; // odd col, even row + i16 = val & 0x0F; if(i16 > 0x07) i16 -= 0x10; + ktaavg[3] = (int8_t)i16; // even col, even row + for(int i = 0; i < 4; ++i) params->kv[i] = ktaavg[i] / div; + val = CREG_VAL(REG_CPOFF); + params->cpOffset[0] = (val & 0x03ff); + if(params->cpOffset[0] > 0x1ff) params->cpOffset[0] -= 0x400; + params->cpOffset[1] = val >> 10; + if(params->cpOffset[1] > 0x1f) params->cpOffset[1] -= 0x40; + params->cpOffset[1] += params->cpOffset[0]; + val = ((CREG_VAL(REG_KTAVSCALE) & 0xF0) >> 4) + 8; + i8 = (int8_t)(CREG_VAL(REG_KVTACP) & 0xFF); + params->cpKta = (fp_t)i8 / (1<> 8; + i16 = CREG_VAL(REG_KVTACP) >> 8; + if(i16 > 0x7F) i16 -= 0x100; + params->cpKv = (fp_t)i16 / (1< 0x7F) i16 -= 0x100; + params->tgc = (fp_t)i16; + params->tgc /= 32.; + val = (CREG_VAL(REG_SCALEACC)>>12); // alpha_scale_CP + i16 = CREG_VAL(REG_ALPHA)>>10; // cp_P1_P0_ratio + if(i16 > 0x1F) i16 -= 0x40; + div = (fp_t)(1<cpAlpha[0] = (fp_t)(CREG_VAL(REG_ALPHA) & 0x03FF) / div; + div = (fp_t)(1<<7); + params->cpAlpha[1] = params->cpAlpha[0] * (1. + (fp_t)i16/div); + i8 = (int8_t)(CREG_VAL(REG_KSTATGC) >> 8); + params->KsTa = (fp_t)i8/(1<<13); + div = 1<<((CREG_VAL(REG_CT34) & 0x0F) + 8); // kstoscale + val = CREG_VAL(REG_KSTO12); + i8 = (int8_t)(val & 0xFF); + params->KsTo[0] = i8 / div; + i8 = (int8_t)(val >> 8); + params->KsTo[1] = i8 / div; + val = CREG_VAL(REG_KSTO34); + i8 = (int8_t)(val & 0xFF); + params->KsTo[2] = i8 / div; + i8 = (int8_t)(val >> 8); + params->KsTo[3] = i8 / div; + // CT1 = -40, CT2 = 0 -> start from zero index, so CT[0] is CT2, CT[1] is CT3, CT[2] is CT4 + params->CT[0] = 0.; // 0degr - between ranges 1 and 2 + val = CREG_VAL(REG_CT34); + mul = ((val & 0x3000)>>12)*10.; // step + params->CT[1] = ((val & 0xF0)>>4)*mul; // CT3 - between ranges 2 and 3 + params->CT[2] = ((val & 0x0F00) >> 8)*mul + params->CT[1]; // CT4 - between ranges 3 and 4 + // alphacorr for each range: 11.1.11 + params->alphacorr[0] = 1./(1. + params->KsTo[0] * 40.); + params->alphacorr[1] = 1.; + params->alphacorr[2] = (1. + params->KsTo[1] * params->CT[1]); + params->alphacorr[3] = (1. + params->KsTo[2] * (params->CT[2] - params->CT[1])) * params->alphacorr[2]; + params->resolEE = (uint8_t)((CREG_VAL(REG_KTAVSCALE) & 0x3000) >> 12); + // Don't forget to check 'outlier' flags for wide purpose + return TRUE; +#undef CREG_VAL +} + +/** + * @brief process_subpage - calculate all parameters from `dataarray` into `mlx_image` + * @param subpageno - number of subpage + * @param simpleimage == 0 - simplest, 1 - narrow range, 2 - extended range + */ +fp_t *process_subpage(MLX90640_params *params, const int16_t Frame[MLX_DMA_MAXLEN], int subpageno, int simpleimage){ +#define IMD_VAL(reg) Frame[IMD_IDX(reg)] + // 11.2.2.1. Resolution restore + // temporary: + fp_t resol_corr = (fp_t)(1<resolEE) / (1<<2); // calibrated resol/current resol + //fp_t resol_corr = (fp_t)(1<resolEE) / (1<<((reg_control_val[subpageno]&0x0C00)>>10)); // calibrated resol/current resol + //DBG("resolEE=%d, resolCur=%d", params->resolEE, ((reg_control_val[subpageno]&0x0C00)>>10)); + // 11.2.2.2. Supply voltage value calculation + int16_t i16a = (int16_t)IMD_VAL(REG_IVDDPIX); + fp_t dvdd = resol_corr*i16a - params->vdd25; + dvdd /= params->kVdd; + fp_t dV = i16a - params->vdd25; // for next step + dV /= params->kVdd; + // 11.2.2.3. Ambient temperature calculation + i16a = (int16_t)IMD_VAL(REG_ITAPTAT); + int16_t i16b = (int16_t)IMD_VAL(REG_ITAVBE); + fp_t dTa = (fp_t)i16a / (i16a * params->alphaPTAT + i16b); // vptatart + dTa *= (fp_t)(1<<18); + dTa = (dTa / (1. + params->KvPTAT*dV)) - params->vPTAT25; + dTa = dTa / params->KtPTAT; // without 25degr - Ta0 + // 11.2.2.4. Gain parameter calculation + i16a = (int16_t)IMD_VAL(REG_IGAIN); + fp_t Kgain = params->gainEE / (fp_t)i16a; + fp_t pixOS[2]; // pix_gain_CP_SPx + // 11.2.2.6.1 + pixOS[0] = ((int16_t)IMD_VAL(REG_ICPSP0))*Kgain; // pix_OS_CP_SPx + pixOS[1] = ((int16_t)IMD_VAL(REG_ICPSP1))*Kgain; + for(int i = 0; i < 2; ++i){ // calc pixOS by gain + // 11.2.2.6.2 + pixOS[i] -= params->cpOffset[i]*(1. + params->cpKta*dTa)*(1. + params->cpKv*dvdd); + } + // now make first approximation to image + uint16_t pixno = 0; // current pixel number - for indexing in parameters etc + for(int row = 0, rowidx = 0; row < MLX_H; ++row, rowidx ^= 2){ + for(int col = 0, idx = rowidx; col < MLX_W; ++col, ++pixno, idx ^= 1){ + uint8_t sp = (row&1)^(col&1); // subpage of current pixel + if(sp != subpageno) continue; + // 11.2.2.5.1 + fp_t curval = (fp_t)(Frame[pixno]) * Kgain; // gain compensation + // 11.2.2.5.3 + curval -= params->offset[pixno] * (1. + params->kta[pixno]*dTa) * + (1. + params->kv[idx]*dvdd); // add offset + // now `curval` is pix_OS == V_IR_emiss_comp (we can divide it by `emissivity` to compensate for it) + // 11.2.2.7: 'Pattern' is just subpage number! + fp_t IRcompens = curval - params->tgc * pixOS[subpageno]; // 11.2.2.8. Normalizing to sensitivity + if(simpleimage == 0){ // 13.3. Using the device in ?image mode? + curval = IRcompens; + }else{ + // 11.2.2.8 + fp_t alphaComp = params->alpha[pixno] - params->tgc * params->cpAlpha[subpageno]; + alphaComp *= 1. + params->KsTa * dTa; + // 11.2.2.9: calculate To for basic range + fp_t Tar = dTa + 273.15 + 25.; // Ta+273.15 + Tar = Tar*Tar*Tar*Tar; // T_aK4 (when \epsilon==1 this is T_{a-r} too) + fp_t ac3 = alphaComp*alphaComp*alphaComp; + fp_t Sx = ac3*IRcompens + alphaComp*ac3*Tar; + Sx = params->KsTo[1] * SQRT(SQRT(Sx)); + fp_t To4 = IRcompens / (alphaComp * (1. - 273.15*params->KsTo[1]) + Sx) + Tar; + curval = SQRT(SQRT(To4)) - 273.15; + if(simpleimage == 2){ // 11.2.2.9.1.3. Extended To range calculation + int r = 0; // range 1 by default + fp_t ctx = -40.; + if(curval > params->CT[2]){ // range 4 + r = 3; ctx = params->CT[2]; + }else if(curval > params->CT[1]){ // range 3 + r = 2; ctx = params->CT[1]; + }else if(curval > params->CT[0]){ // range 2, default + r = 1; ctx = params->CT[0]; + } + if(r != 1){ // recalculate for extended range if we are out of standard range + To4 = IRcompens / (alphaComp * params->alphacorr[r] * (1. + params->KsTo[r]*(curval - ctx))) + Tar; + curval = SQRT(SQRT(To4)) - 273.15; + } + } + } + mlx_image[pixno] = curval; + } + } + return mlx_image; +#undef IMD_VAL +} + +int MLXtest(){ + MLX90640_params p; + USB_sendstr(" Extract parameters - "); + if(!get_parameters(EEPROM, &p)) return 2; + USB_sendstr(OK); + dump_parameters(&p, &extracted_parameters); + fp_t *sp; + for(int i = 0; i < 2; ++i){ + USB_sendstr(" 100 times process subpage - "); printi(i); USB_putbyte(' '); + uint32_t Tstart = Tms; + for(int _ = 0; _ < 100; ++_){ + sp = process_subpage(&p, DataFrame[i], i, 2); + if(!sp) return 1; + } + USB_sendstr(OKs); printfl((Tms - Tstart)/100.f, 3); USB_sendstr(" ms\n"); + dumpIma(sp); + chkImage(sp, ToFrame[i]); + } + drawIma(sp); + return 0; +} diff --git a/F3:F303/MLX90640test/mlx90640.h b/F3:F303/MLX90640test/mlx90640.h new file mode 100644 index 0000000..9ca9c8b --- /dev/null +++ b/F3:F303/MLX90640test/mlx90640.h @@ -0,0 +1,68 @@ +/* + * This file is part of the mlxtest project. + * Copyright 2022 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +// floating type & sqrt operator +typedef float fp_t; +#define SQRT(x) sqrtf((x)) + +// amount of pixels +#define MLX_W (32) +#define MLX_H (24) +#define MLX_PIXNO (MLX_W*MLX_H) +// pixels + service data +#define MLX_PIXARRSZ (MLX_PIXNO + 64) + +typedef struct{ + int16_t kVdd; + int16_t vdd25; + fp_t KvPTAT; + fp_t KtPTAT; + int16_t vPTAT25; + fp_t alphaPTAT; + int16_t gainEE; + fp_t tgc; + fp_t cpKv; // K_V_CP + fp_t cpKta; // K_Ta_CP + fp_t KsTa; + fp_t CT[3]; // range borders (0, 160, 320 degrC?) + fp_t KsTo[4]; // K_S_To for each range * 273.15 + fp_t alphacorr[4]; // Alpha_corr for each range + fp_t alpha[MLX_PIXNO]; // full - with alpha_scale + fp_t offset[MLX_PIXNO]; + fp_t kta[MLX_PIXNO]; // full K_ta - with scale1&2 + fp_t kv[4]; // full - with scale; 0 - odd row, odd col; 1 - odd row even col; 2 - even row, odd col; 3 - even row, even col + fp_t cpAlpha[2]; // alpha_CP_subpage 0 and 1 + uint8_t resolEE; // resolution_EE + int16_t cpOffset[2]; + uint8_t outliers[MLX_PIXNO]; // outliers - bad pixels (if == 1) +} MLX90640_params; + +// full amount of IMAGE data + EXTRA data (counts of uint16_t!) +#define MLX_DMA_MAXLEN (834) + +int get_parameters(const uint16_t dataarray[MLX_DMA_MAXLEN], MLX90640_params *params); +void dump_parameters(MLX90640_params *params, const MLX90640_params *standard); +fp_t *process_subpage(MLX90640_params *params, const int16_t Frame[MLX_DMA_MAXLEN], int subpageno, int simpleimage); +void chkImage(const fp_t Image[MLX_PIXNO], const fp_t ToFrame[MLX_PIXNO]); +void dumpIma(const fp_t im[MLX_PIXNO]); +void drawIma(const fp_t im[MLX_PIXNO]); +int MLXtest(); diff --git a/F3:F303/MLX90640test/mlx90640_regs.h b/F3:F303/MLX90640test/mlx90640_regs.h new file mode 100644 index 0000000..859e69c --- /dev/null +++ b/F3:F303/MLX90640test/mlx90640_regs.h @@ -0,0 +1,90 @@ +/* + * This file is part of the mlxtest project. + * Copyright 2022 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#define REG_STATUS 0x8000 +#define REG_STATUS_OVWEN (1<<4) +#define REG_STATUS_NEWDATA (1<<3) +#define REG_STATUS_SPNO (1<<0) +#define REG_STATUS_SPMASK (3<<0) +#define REG_CONTROL 0x800D +#define REG_CONTROL_CHESS (1<<12) +#define REG_CONTROL_RES16 (0<<10) +#define REG_CONTROL_RES17 (1<<10) +#define REG_CONTROL_RES18 (2<<10) +#define REG_CONTROL_RES19 (3<<10) +#define REG_CONTROL_RESMASK (3<<10) +#define REG_CONTROL_REFR_05HZ (0<<7) +#define REG_CONTROL_REFR_1HZ (1<<7) +#define REG_CONTROL_REFR_2HZ (2<<7) +#define REG_CONTROL_REFR_4HZ (3<<7) +#define REG_CONTROL_REFR_8HZ (4<<7) +#define REG_CONTROL_REFR_16HZ (5<<7) +#define REG_CONTROL_REFR_32HZ (6<<7) +#define REG_CONTROL_REFR_64HZ (7<<7) +#define REG_CONTROL_SUBP1 (1<<4) +#define REG_CONTROL_SUBPMASK (3<<4) +#define REG_CONTROL_SUBPSEL (1<<3) +#define REG_CONTROL_DATAHOLD (1<<2) +#define REG_CONTROL_SUBPEN (1<<0) + +// default value +#define REG_CONTROL_DEFAULT (REG_CONTROL_CHESS|REG_CONTROL_RES18|REG_CONTROL_REFR_2HZ|REG_CONTROL_SUBPEN) + +// calibration data start & len +#define REG_CALIDATA 0x2400 +#define REG_CALIDATA_LEN 832 + +#define REG_APTATOCCS 0x2410 +#define REG_OSAVG 0x2411 +#define REG_OCCROW14 0x2412 +#define REG_OCCCOL14 0x2418 +#define REG_SCALEACC 0x2420 +#define REG_SENSIVITY 0x2421 +#define REG_ACCROW14 0x2422 +#define REG_ACCCOL14 0x2428 +#define REG_GAIN 0x2430 +#define REG_PTAT 0x2431 +#define REG_KVTPTAT 0x2432 +#define REG_VDD 0x2433 +#define REG_KVAVG 0x2434 +#define REG_ILCHESS 0x2435 +#define REG_KTAAVGODDCOL 0x2436 +#define REG_KTAAVGEVENCOL 0x2437 +#define REG_KTAVSCALE 0x2438 +#define REG_ALPHA 0x2439 +#define REG_CPOFF 0x243A +#define REG_KVTACP 0x243B +#define REG_KSTATGC 0x243C +#define REG_KSTO12 0x243D +#define REG_KSTO34 0x243E +#define REG_CT34 0x243F +#define REG_OFFAK1 0x2440 +// index of register in array (from REG_CALIDATA) +#define CREG_IDX(addr) ((addr)-REG_CALIDATA) + +#define REG_IMAGEDATA 0x0400 +#define REG_ITAVBE 0x0700 +#define REG_ICPSP0 0x0708 +#define REG_IGAIN 0x070A +#define REG_ITAPTAT 0x0720 +#define REG_ICPSP1 0x0728 +#define REG_IVDDPIX 0x072A +// index of register in array (from REG_IMAGEDATA) +#define IMD_IDX(addr) ((addr)-REG_IMAGEDATA) diff --git a/F3:F303/MLX90640test/mlxtest.bin b/F3:F303/MLX90640test/mlxtest.bin new file mode 100755 index 0000000000000000000000000000000000000000..e3d3f3521d2b08e1ac421d598da90659b530bb51 GIT binary patch literal 30116 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 + + + + + EnvironmentId + {7bd84e39-ca37-46d3-be9d-99ebea85bc0d} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + true + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + false + 0 + 80 + true + true + 1 + 0 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + false + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + false + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 2 + false + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + true + Desktop + Desktop + {65a14f9e-e008-4c1b-89df-4eaa4774b6e3} + 0 + 0 + 0 + + /Big/Data/00__Electronics/STM32/F303-nolib/blink + + + + all + + true + GenericProjectManager.GenericMakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + GenericProjectManager.GenericMakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Default + GenericProjectManager.GenericBuildConfiguration + 0 + 0 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + true + + 1 + + 1 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/F3:F303/MLX90640test/mlxtest.cxxflags b/F3:F303/MLX90640test/mlxtest.cxxflags new file mode 100644 index 0000000..6435dfc --- /dev/null +++ b/F3:F303/MLX90640test/mlxtest.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/F3:F303/MLX90640test/mlxtest.files b/F3:F303/MLX90640test/mlxtest.files new file mode 100644 index 0000000..21ffdaa --- /dev/null +++ b/F3:F303/MLX90640test/mlxtest.files @@ -0,0 +1,22 @@ +hardware.c +hardware.h +main.c +mlx90640.c +mlx90640.h +mlx90640_regs.h +proto.c +proto.h +ringbuffer.c +ringbuffer.h +strfunc.c +strfunc.h +testdata.h +usb.c +usb.h +usb_descr.c +usb_descr.h +usb_dev.c +usb_dev.h +usb_lib.c +usb_lib.h +usbhw.h diff --git a/F3:F303/MLX90640test/mlxtest.includes b/F3:F303/MLX90640test/mlxtest.includes new file mode 100644 index 0000000..06d1130 --- /dev/null +++ b/F3:F303/MLX90640test/mlxtest.includes @@ -0,0 +1,6 @@ +. +../inc +../inc/Fx +../inc/cm +../inc/ld +../inc/startup diff --git a/F3:F303/MLX90640test/offset.csv b/F3:F303/MLX90640test/offset.csv new file mode 100644 index 0000000..d79d26b --- /dev/null +++ b/F3:F303/MLX90640test/offset.csv @@ -0,0 +1 @@ +-54,-56,-50,-60,-50,-56,-48,-60,-49,-57,-48,-61,-49,-59,-48,-63,-46,-59,-48,-65,-49,-61,-49,-66,-47,-64,-50,-69,-53,-66,-51,-75,-61,-64,-65,-61,-57,-63,-63,-61,-56,-63,-63,-62,-56,-65,-63,-64,-53,-65,-63,-65,-55,-66,-63,-66,-53,-69,-63,-69,-58,-70,-64,-74,-53,-56,-50,-60,-51,-55,-48,-60,-48,-56,-47,-61,-47,-58,-47,-62,-45,-58,-48,-64,-47,-59,-47,-67,-46,-62,-49,-68,-52,-65,-50,-75,-60,-62,-65,-61,-58,-61,-63,-61,-55,-62,-62,-61,-54,-64,-62,-62,-51,-64,-62,-63,-53,-66,-62,-66,-52,-67,-63,-67,-59,-71,-64,-75,-50,-54,-49,-58,-48,-54,-48,-59,-46,-55,-47,-60,-47,-55,-47,-61,-43,-57,-46,-62,-46,-59,-47,-65,-46,-61,-48,-67,-52,-65,-50,-74,-57,-63,-65,-60,-56,-62,-64,-61,-54,-63,-62,-62,-54,-62,-62,-63,-51,-64,-62,-63,-52,-66,-62,-65,-53,-69,-62,-69,-59,-71,-64,-75,-53,-54,-49,-59,-49,-54,-47,-58,-45,-54,-47,-60,-47,-55,-46,-62,-46,-57,-47,-62,-47,-58,-47,-64,-46,-61,-48,-66,-50,-64,-49,-73,-62,-64,-66,-62,-59,-63,-64,-61,-54,-63,-64,-62,-55,-63,-63,-63,-54,-65,-63,-64,-55,-65,-63,-65,-54,-68,-64,-68,-58,-72,-64,-75,-52,-53,-49,-58,-50,-53,-47,-58,-48,-54,-47,-60,-47,-55,-46,-61,-45,-57,-47,-63,-46,-58,-48,-65,-46,-61,-49,-67,-50,-64,-50,-73,-62,-65,-67,-63,-59,-63,-65,-63,-57,-64,-64,-63,-56,-65,-64,-64,-54,-66,-64,-65,-55,-68,-64,-66,-54,-69,-65,-69,-58,-72,-66,-75,-50,-54,-49,-58,-47,-53,-49,-59,-45,-55,-48,-60,-45,-55,-49,-62,-44,-57,-47,-63,-45,-58,-48,-65,-47,-62,-51,-69,-52,-65,-52,-75,-61,-66,-68,-64,-58,-65,-67,-64,-56,-66,-66,-65,-55,-66,-65,-65,-54,-67,-64,-66,-55,-68,-65,-68,-54,-71,-66,-71,-60,-73,-67,-77,-54,-54,-52,-59,-51,-54,-50,-59,-49,-55,-49,-60,-48,-55,-49,-62,-46,-58,-49,-65,-48,-60,-49,-66,-46,-63,-50,-68,-52,-64,-52,-75,-66,-69,-73,-66,-62,-68,-69,-65,-60,-67,-68,-65,-59,-67,-69,-66,-56,-69,-67,-68,-57,-69,-66,-69,-54,-71,-66,-70,-60,-73,-69,-77,-56,-54,-52,-59,-53,-54,-51,-60,-50,-56,-51,-61,-49,-56,-50,-63,-47,-58,-50,-65,-48,-59,-51,-66,-47,-62,-52,-68,-54,-66,-53,-76,-69,-71,-73,-69,-66,-69,-72,-68,-62,-69,-71,-67,-61,-69,-70,-68,-58,-70,-68,-70,-58,-70,-68,-69,-56,-71,-68,-71,-62,-74,-69,-79,-54,-55,-53,-60,-52,-55,-53,-61,-51,-57,-54,-63,-50,-57,-53,-64,-49,-59,-51,-65,-50,-60,-53,-66,-49,-63,-54,-71,-55,-66,-55,-76,-69,-73,-76,-70,-66,-71,-75,-69,-65,-72,-74,-71,-63,-71,-71,-71,-60,-71,-70,-70,-61,-71,-70,-70,-59,-74,-70,-75,-63,-76,-70,-80,-62,-57,-58,-62,-59,-57,-56,-62,-56,-59,-54,-64,-55,-60,-54,-65,-52,-61,-54,-67,-53,-62,-54,-68,-53,-64,-56,-71,-55,-67,-56,-75,-77,-77,-83,-74,-74,-74,-79,-73,-70,-74,-76,-73,-68,-74,-75,-73,-64,-75,-74,-73,-64,-74,-73,-74,-63,-76,-74,-75,-64,-78,-74,-80,-66,-58,-61,-65,-61,-59,-57,-64,-57,-60,-56,-66,-55,-60,-56,-67,-55,-63,-57,-69,-54,-63,-56,-69,-54,-64,-57,-72,-59,-67,-58,-77,-82,-80,-86,-78,-77,-78,-81,-76,-73,-78,-79,-76,-69,-76,-78,-75,-68,-78,-78,-76,-67,-76,-77,-76,-66,-78,-77,-77,-70,-80,-77,-84,-67,-60,-65,-66,-62,-61,-63,-68,-62,-62,-62,-67,-60,-64,-61,-70,-57,-65,-59,-69,-56,-65,-59,-71,-58,-67,-62,-74,-63,-69,-63,-78,-94,-91,-100,-88,-88,-88,-95,-87,-85,-87,-92,-86,-82,-88,-90,-88,-78,-87,-88,-84,-77,-87,-87,-86,-76,-89,-87,-90,-80,-90,-87,-93 diff --git a/F3:F303/MLX90640test/openocd.cfg b/F3:F303/MLX90640test/openocd.cfg new file mode 100644 index 0000000..56ccc2e --- /dev/null +++ b/F3:F303/MLX90640test/openocd.cfg @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# script for stm32f3x family + +# +# stm32 devices support both JTAG and SWD transports. +# +source [find interface/stlink-v2-1.cfg] +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME stm32f3x +} + +set _ENDIAN little + +# Work-area is a space in RAM used for flash programming +# By default use 16kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x4000 +} + +# JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz +# +# Since we may be running of an RC oscilator, we crank down the speed a +# bit more to be on the safe side. Perhaps superstition, but if are +# running off a crystal, we can run closer to the limit. Note +# that there can be a pretty wide band where things are more or less stable. +adapter speed 1000 + +adapter srst delay 100 +if {[using_jtag]} { + jtag_ntrst_delay 100 +} + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + if { [using_jtag] } { + # See STM Document RM0316 + # Section 29.6.3 - corresponds to Cortex-M4 r0p1 + set _CPUTAPID 0x4ba00477 + } { + set _CPUTAPID 0x2ba01477 + } +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +if {[using_jtag]} { + jtag newtap $_CHIPNAME bs -irlen 5 +} + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME stm32f1x 0 0 0 0 $_TARGETNAME + +reset_config srst_nogate + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +proc stm32f3x_default_reset_start {} { + # Reset clock is HSI (8 MHz) + adapter speed 1000 +} + +proc stm32f3x_default_examine_end {} { + # Enable debug during low power modes (uses more power) + mmw 0xe0042004 0x00000007 0 ;# DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP + + # Stop watchdog counters during halt + mmw 0xe0042008 0x00001800 0 ;# DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP +} + +proc stm32f3x_default_reset_init {} { + # Configure PLL to boost clock to HSI x 8 (64 MHz) + mww 0x40021004 0x00380400 ;# RCC_CFGR = PLLMUL[3:1] | PPRE1[2] + mmw 0x40021000 0x01000000 0 ;# RCC_CR |= PLLON + mww 0x40022000 0x00000012 ;# FLASH_ACR = PRFTBE | LATENCY[1] + sleep 10 ;# Wait for PLL to lock + mmw 0x40021004 0x00000002 0 ;# RCC_CFGR |= SW[1] + + # Boost JTAG frequency + adapter speed 8000 +} + +# Default hooks +$_TARGETNAME configure -event examine-end { stm32f3x_default_examine_end } +$_TARGETNAME configure -event reset-start { stm32f3x_default_reset_start } +$_TARGETNAME configure -event reset-init { stm32f3x_default_reset_init } + +tpiu create $_CHIPNAME.tpiu -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0xE0040000 + +lappend _telnet_autocomplete_skip _proc_pre_enable_$_CHIPNAME.tpiu +proc _proc_pre_enable_$_CHIPNAME.tpiu {_targetname} { + targets $_targetname + + # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync + # change this value accordingly to configure trace pins + # assignment + mmw 0xe0042004 0x00000020 0 +} + +$_CHIPNAME.tpiu configure -event pre-enable "_proc_pre_enable_$_CHIPNAME.tpiu $_TARGETNAME" diff --git a/F3:F303/MLX90640test/proto.c b/F3:F303/MLX90640test/proto.c new file mode 100644 index 0000000..1664ea2 --- /dev/null +++ b/F3:F303/MLX90640test/proto.c @@ -0,0 +1,49 @@ +/* + * This file is part of the mlxtest project. + * Copyright 2025 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "mlx90640.h" +#include "strfunc.h" +#include "usb_dev.h" +#include "version.inc" + +const char *helpstring = + "https://github.com/eddyem/stm32samples/tree/master/F3:F303/USB_template build#" BUILD_NUMBER " @ " BUILD_DATE "\n" + "T - print current Tms\n" + "R - run MLX test\n" +; + +const char *parse_cmd(const char *buf){ + if(buf[1]) return buf; // echo wrong data + switch(*buf){ + case 'T': + USB_sendstr("T="); + USB_sendstr(u2str(Tms)); + newline(); + break; + case 'R': + if(MLXtest()) USB_sendstr("error!\n"); + break; + default: // help + USB_sendstr(helpstring); + break; + } + return NULL; +} diff --git a/F3:F303/MLX90640test/proto.h b/F3:F303/MLX90640test/proto.h new file mode 100644 index 0000000..5227d56 --- /dev/null +++ b/F3:F303/MLX90640test/proto.h @@ -0,0 +1,22 @@ +/* + * This file is part of the mlxtest project. + * Copyright 2025 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +char *parse_cmd(char *buf); + diff --git a/F3:F303/MLX90640test/ringbuffer.c b/F3:F303/MLX90640test/ringbuffer.c new file mode 100644 index 0000000..b0ffe8e --- /dev/null +++ b/F3:F303/MLX90640test/ringbuffer.c @@ -0,0 +1,166 @@ +/* + * Copyright 2023 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ringbuffer.h" + +static int datalen(ringbuffer *b){ + if(b->tail >= b->head) return (b->tail - b->head); + else return (b->length - b->head + b->tail); +} + +// stored data length +int RB_datalen(ringbuffer *b){ + if(b->busy) return -1; + b->busy = 1; + int l = datalen(b); + b->busy = 0; + return l; +} + +static int hasbyte(ringbuffer *b, uint8_t byte){ + if(b->head == b->tail) return -1; // no data in buffer + int startidx = b->head; + if(b->head > b->tail){ // + for(int found = b->head; found < b->length; ++found) + if(b->data[found] == byte) return found; + startidx = 0; + } + for(int found = startidx; found < b->tail; ++found) + if(b->data[found] == byte) return found; + return -1; +} + +/** + * @brief RB_hasbyte - check if buffer has given byte stored + * @param b - buffer + * @param byte - byte to find + * @return index if found, -1 if none or busy + */ +int RB_hasbyte(ringbuffer *b, uint8_t byte){ + if(b->busy) return -1; + b->busy = 1; + int ret = hasbyte(b, byte); + b->busy = 0; + return ret; +} + +// poor memcpy +static void mcpy(uint8_t *targ, const uint8_t *src, int l){ + while(l--) *targ++ = *src++; +} + +// increment head or tail +TRUE_INLINE void incr(ringbuffer *b, volatile int *what, int n){ + *what += n; + if(*what >= b->length) *what -= b->length; +} + +static int read(ringbuffer *b, uint8_t *s, int len){ + int l = datalen(b); + if(!l) return 0; + if(l > len) l = len; + int _1st = b->length - b->head; + if(_1st > l) _1st = l; + if(_1st > len) _1st = len; + mcpy(s, b->data + b->head, _1st); + if(_1st < len && l > _1st){ + mcpy(s+_1st, b->data, l - _1st); + incr(b, &b->head, l); + return l; + } + incr(b, &b->head, _1st); + return _1st; +} + +/** + * @brief RB_read - read data from ringbuffer + * @param b - buffer + * @param s - array to write data + * @param len - max len of `s` + * @return bytes read or -1 if busy + */ +int RB_read(ringbuffer *b, uint8_t *s, int len){ + if(b->busy) return -1; + b->busy = 1; + int r = read(b, s, len); + b->busy = 0; + return r; +} + +static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ + int idx = hasbyte(b, byte); + if(idx < 0) return 0; + int partlen = idx + 1 - b->head; + // now calculate length of new data portion + if(idx < b->head) partlen += b->length; + if(partlen > len) return -read(b, s, len); + return read(b, s, partlen); +} + +/** + * @brief RB_readto fill array `s` with data until byte `byte` (with it) + * @param b - ringbuffer + * @param byte - check byte + * @param s - buffer to write data + * @param len - length of `s` + * @return amount of bytes written (negative, if lenbusy) return -1; + b->busy = 1; + int n = readto(b, byte, s, len); + b->busy = 0; + return n; +} + +static int write(ringbuffer *b, const uint8_t *str, int l){ + int r = b->length - 1 - datalen(b); // rest length + if(l > r || !l) return 0; + int _1st = b->length - b->tail; + if(_1st > l) _1st = l; + mcpy(b->data + b->tail, str, _1st); + if(_1st < l){ // add another piece from start + mcpy(b->data, str+_1st, l-_1st); + } + incr(b, &b->tail, l); + return l; +} + +/** + * @brief RB_write - write some data to ringbuffer + * @param b - buffer + * @param str - data + * @param l - length + * @return amount of bytes written or -1 if busy + */ +int RB_write(ringbuffer *b, const uint8_t *str, int l){ + if(b->busy) return -1; + b->busy = 1; + int w = write(b, str, l); + b->busy = 0; + return w; +} + +// just delete all information in buffer `b` +int RB_clearbuf(ringbuffer *b){ + if(b->busy) return -1; + b->busy = 1; + b->head = 0; + b->tail = 0; + b->busy = 0; + return 1; +} diff --git a/F3:F303/MLX90640test/ringbuffer.h b/F3:F303/MLX90640test/ringbuffer.h new file mode 100644 index 0000000..ed2cf95 --- /dev/null +++ b/F3:F303/MLX90640test/ringbuffer.h @@ -0,0 +1,41 @@ +/* + * Copyright 2023 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#if defined STM32F0 +#include +#elif defined STM32F1 +#include +#elif defined STM32F3 +#include +#endif + +typedef struct{ + uint8_t *data; // data buffer + const int length; // its length + int head; // head index + int tail; // tail index + volatile int busy; // == TRUE if buffer is busy now +} ringbuffer; + +int RB_read(ringbuffer *b, uint8_t *s, int len); +int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len); +int RB_hasbyte(ringbuffer *b, uint8_t byte); +int RB_write(ringbuffer *b, const uint8_t *str, int l); +int RB_datalen(ringbuffer *b); +int RB_clearbuf(ringbuffer *b); diff --git a/F3:F303/MLX90640test/strfunc.c b/F3:F303/MLX90640test/strfunc.c new file mode 100644 index 0000000..4d60401 --- /dev/null +++ b/F3:F303/MLX90640test/strfunc.c @@ -0,0 +1,334 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "usb_dev.h" +/** + * @brief hexdump - dump hex array by 16 bytes in string + * @param arr - array to dump + * @param len - length of `arr` + */ +void hexdump(uint8_t *arr, uint16_t len){ + char buf[52], *bptr = buf; + for(uint16_t l = 0; l < len; ++l, ++arr){ + for(int16_t j = 1; j > -1; --j){ + register uint8_t half = (*arr >> (4*j)) & 0x0f; + if(half < 10) *bptr++ = half + '0'; + else *bptr++ = half - 10 + 'a'; + } + if(l % 16 == 15){ + *bptr++ = '\n'; + *bptr = 0; + USB_sendstr(buf); + bptr = buf; + }else *bptr++ = ' '; + } + if(bptr != buf){ + *bptr++ = '\n'; + *bptr = 0; + USB_sendstr(buf); + } +} + +/** + * @brief _2str - convert value into string buffer + * @param val - |value| + * @param minus - ==0 if value > 0 + * @return buffer with number + */ +static char *_2str(uint32_t val, uint8_t minus){ + static char strbuf[12]; + char *bufptr = &strbuf[11]; + *bufptr = 0; + if(!val){ + *(--bufptr) = '0'; + }else{ + while(val){ + uint32_t x = val / 10; + *(--bufptr) = (val - 10*x) + '0'; + val = x; + } + } + if(minus) *(--bufptr) = '-'; + return bufptr; +} + +// return string with number `val` +char *u2str(uint32_t val){ + return _2str(val, 0); +} +char *i2str(int32_t i){ + uint8_t minus = 0; + uint32_t val; + if(i < 0){ + minus = 1; + val = -i; + }else val = i; + return _2str(val, minus); +} + +/** + * @brief uhex2str - print 32bit unsigned int as hex + * @param val - value + * @return string with number + */ +char *uhex2str(uint32_t val){ + static char buf[12] = "0x"; + int npos = 2; + uint8_t *ptr = (uint8_t*)&val + 3; + int8_t i, j, z=1; + for(i = 0; i < 4; ++i, --ptr){ + if(*ptr == 0){ // omit leading zeros + if(i == 3) z = 0; + if(z) continue; + } + else z = 0; + for(j = 1; j > -1; --j){ + uint8_t half = (*ptr >> (4*j)) & 0x0f; + if(half < 10) buf[npos++] = half + '0'; + else buf[npos++] = half - 10 + 'a'; + } + } + buf[npos] = 0; + return buf; +} + +/** + * @brief omit_spaces - eliminate leading spaces and other trash in string + * @param buf - string + * @return - pointer to first character in `buf` > ' ' + */ +const char *omit_spaces(const char *buf){ + while(*buf){ + if(*buf > ' ') break; + ++buf; + } + return buf; +} + +/** + * @brief getdec - read decimal number & return pointer to next non-number symbol + * @param buf - string + * @param N - number read + * @return Next non-number symbol. In case of overflow return `buf` and N==0xffffffff + */ +static const char *getdec(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '9'){ + break; + } + if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow + *N = 0xffffff; + return start; + } + num *= 10; + num += c - '0'; + ++buf; + } + *N = num; + return buf; +} +// read hexadecimal number (without 0x prefix!) +static const char *gethex(const char *buf, uint32_t *N){ + const char *start = buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + uint8_t M = 0; + if(c >= '0' && c <= '9'){ + M = '0'; + }else if(c >= 'A' && c <= 'F'){ + M = 'A' - 10; + }else if(c >= 'a' && c <= 'f'){ + M = 'a' - 10; + } + if(M){ + if(num & 0xf0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 4; + num += c - M; + }else{ + break; + } + ++buf; + } + *N = num; + return buf; +} +// read octal number (without 0 prefix!) +static const char *getoct(const char *buf, uint32_t *N){ + const char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '7'){ + break; + } + if(num & 0xe0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 3; + num += c - '0'; + ++buf; + } + *N = num; + return buf; +} +// read binary number (without b prefix!) +static const char *getbin(const char *buf, uint32_t *N){ + const char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '1'){ + break; + } + if(num & 0x80000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 1; + if(c == '1') num |= 1; + ++buf; + } + *N = num; + return buf; +} + +/** + * @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111) + * @param buf - buffer with number and so on + * @param N - the number read + * @return pointer to first non-number symbol in buf + * (if it is == buf, there's no number or if *N==0xffffffff there was overflow) + */ +const char *getnum(const char *txt, uint32_t *N){ + const char *nxt = NULL; + const char *s = omit_spaces(txt); + if(*s == '0'){ // hex, oct or 0 + if(s[1] == 'x' || s[1] == 'X'){ // hex + nxt = gethex(s+2, N); + if(nxt == s+2) nxt = (char*)txt; + }else if(s[1] > '0'-1 && s[1] < '8'){ // oct + nxt = getoct(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ // 0 + nxt = s+1; + *N = 0; + } + }else if(*s == 'b' || *s == 'B'){ + nxt = getbin(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ + nxt = getdec(s, N); + if(nxt == s) nxt = (char*)txt; + } + return nxt; +} + +// get signed integer +const char *getint(const char *txt, int32_t *I){ + const char *s = omit_spaces(txt); + int32_t sign = 1; + uint32_t U; + if(*s == '-'){ + sign = -1; + ++s; + } + const char *nxt = getnum(s, &U); + if(nxt == s) return txt; + if(U & 0x80000000) return txt; // overfull + *I = sign * (int32_t)U; + return nxt; +} + +// be careful: if pow10 would be bigger you should change str[] size! +static const float pwr10[] = {1.f, 10.f, 100.f, 1000.f, 10000.f}; +static const float rounds[] = {0.5f, 0.05f, 0.005f, 0.0005f, 0.00005f}; +#define P10L (sizeof(pwr10)/sizeof(uint32_t) - 1) +char *float2str(float x, uint8_t prec){ + static char str[16] = {0}; // -117.5494E-36\0 - 14 symbols max! + if(prec > P10L) prec = P10L; + if(isnan(x)){ memcpy(str, "NAN", 4); return str;} + else{ + int i = isinf(x); + if(i){memcpy(str, "-INF", 5); if(i == 1) return str+1; else return str;} + } + char *s = str + 14; // go to end of buffer + uint8_t minus = 0; + if(x < 0){ + x = -x; + minus = 1; + } + int pow = 0; // xxxEpow + // now convert float to 1.xxxE3y + while(x > 1000.f){ + x /= 1000.f; + pow += 3; + } + if(x > 0.) while(x < 1.){ + x *= 1000.f; + pow -= 3; + } + // print Eyy + if(pow){ + uint8_t m = 0; + if(pow < 0){pow = -pow; m = 1;} + while(pow){ + register int p10 = pow/10; + *s-- = '0' + (pow - 10*p10); + pow = p10; + } + if(m) *s-- = '-'; + *s-- = 'E'; + } + // now our number is in [1, 1000] + uint32_t units; + if(prec){ + units = (uint32_t) x; + uint32_t decimals = (uint32_t)((x-units+rounds[prec])*pwr10[prec]); + // print decimals + while(prec){ + register int d10 = decimals / 10; + *s-- = '0' + (decimals - 10*d10); + decimals = d10; + --prec; + } + // decimal point + *s-- = '.'; + }else{ // without decimal part + units = (uint32_t) (x + 0.5); + } + // print main units + if(units == 0) *s-- = '0'; + else while(units){ + register uint32_t u10 = units / 10; + *s-- = '0' + (units - 10*u10); + units = u10; + } + if(minus) *s-- = '-'; + return s+1; +} diff --git a/F3:F303/MLX90640test/strfunc.h b/F3:F303/MLX90640test/strfunc.h new file mode 100644 index 0000000..f7aff02 --- /dev/null +++ b/F3:F303/MLX90640test/strfunc.h @@ -0,0 +1,47 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include "usb_dev.h" + +extern volatile uint32_t Tms; + +#define STR_HELPER(s) #s +#define STR(s) STR_HELPER(s) + +#ifdef EBUG +#define DBG(str) do{USB_sendstr(__FILE__ " (L" STR(__LINE__) "): " str); newline();}while(0) +#else +#define DBG(str) +#endif + +#define printu(x) do{USB_sendstr(u2str(x));}while(0) +#define printi(x) do{USB_sendstr(i2str(x));}while(0) +#define printuhex(x) do{USB_sendstr(uhex2str(x));}while(0) +#define printfl(x,n) do{USB_sendstr(float2str(x, n));}while(0) + +void hexdump(int ifno, uint8_t *arr, uint16_t len); +const char *u2str(uint32_t val); +const char *i2str(int32_t i); +const char *uhex2str(uint32_t val); +const char *getnum(const char *txt, uint32_t *N); +const char *omit_spaces(const char *buf); +const char *getint(const char *txt, int32_t *I); +char *float2str(float x, uint8_t prec); diff --git a/F3:F303/MLX90640test/testdata.h b/F3:F303/MLX90640test/testdata.h new file mode 100644 index 0000000..d1b31f2 --- /dev/null +++ b/F3:F303/MLX90640test/testdata.h @@ -0,0 +1,82 @@ +/* + * This file is part of the mlxtest project. + * Copyright 2025 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// data from MLX documentation for algorithms testing +// this file should be included only once! + +#ifdef _TESTDATA_H__ +#error "Don't include this file several times!" +#endif +#define _TESTDATA_H__ + +#include "mlx90640.h" + +static const uint16_t EEPROM[MLX_DMA_MAXLEN] = { + #include "eeprom.csv" +}; + +static const int16_t DataFrame[2][MLX_DMA_MAXLEN] = { + { + #include "frame0.csv" + }, + { + #include "frame1.csv" + } +}; + +static const MLX90640_params extracted_parameters = { + .kVdd = -3200 + ,.vdd25 = -12544 + ,.KvPTAT = 0.002197 + ,.KtPTAT = 42.625000 + ,.vPTAT25 = 12196 + ,.alphaPTAT = 9.0 + ,.gainEE = 5580 + ,.tgc = 0.000000 + ,.cpKv = 0.3750 + ,.cpKta = 0.004272 +// ,.calibrationModeEE = 128 + ,.KsTa = -0.002441 + ,.CT = {0., 300., 500.} + ,.KsTo = {-0.0002, -0.0002, -0.0002, -0.0002} + ,.alphacorr = {} + ,.alpha = { + #include "alpha.csv" + } + ,.offset = { + #include "offset.csv" + } + ,.kta = { + #include "kta.csv" + } + ,.kv = {0.4375, 0.3750, 0.3750, 0.3750} + ,.cpAlpha = {0.0000000028812792152, 0.0000000029037892091} + ,.resolEE = 2 + ,.cpOffset = {-69, -65} + ,.outliers = {0} +}; + +static const fp_t ToFrame[2][MLX_PIXNO] = { + { +#include "to_frame0.csv" + }, + { +#include "to_frame1.csv" + } +}; + diff --git a/F3:F303/MLX90640test/to_frame0.csv b/F3:F303/MLX90640test/to_frame0.csv new file mode 100644 index 0000000..d054181 --- /dev/null +++ b/F3:F303/MLX90640test/to_frame0.csv @@ -0,0 +1 @@ +28.711,0.000,28.178,0.000,28.313,0.000,28.631,0.000,28.295,0.000,28.586,0.000,28.336,0.000,28.683,0.000,28.248,0.000,28.573,0.000,29.127,0.000,28.629,0.000,29.070,0.000,28.894,0.000,28.883,0.000,29.687,0.000,0.000,28.618,0.000,28.134,0.000,28.517,0.000,27.982,0.000,28.092,0.000,27.914,0.000,28.156,0.000,28.261,0.000,28.198,0.000,28.528,0.000,28.837,0.000,28.730,0.000,28.814,0.000,28.558,0.000,28.605,0.000,29.005,28.513,0.000,28.482,0.000,28.428,0.000,27.946,0.000,28.248,0.000,28.387,0.000,28.340,0.000,28.128,0.000,28.544,0.000,28.321,0.000,28.986,0.000,28.445,0.000,28.728,0.000,28.778,0.000,29.035,0.000,28.639,0.000,0.000,28.116,0.000,28.237,0.000,28.173,0.000,28.519,0.000,28.303,0.000,28.049,0.000,28.246,0.000,28.466,0.000,28.247,0.000,28.378,0.000,28.835,0.000,28.480,0.000,28.828,0.000,28.428,0.000,28.528,0.000,29.030,28.163,0.000,28.719,0.000,28.268,0.000,28.439,0.000,28.607,0.000,28.199,0.000,28.440,0.000,28.730,0.000,28.361,0.000,28.256,0.000,28.253,0.000,28.563,0.000,28.593,0.000,28.962,0.000,28.746,0.000,28.917,0.000,0.000,28.112,0.000,27.955,0.000,28.365,0.000,28.291,0.000,28.335,0.000,28.610,0.000,28.281,0.000,28.303,0.000,28.246,0.000,28.710,0.000,28.723,0.000,28.532,0.000,28.493,0.000,28.686,0.000,28.565,0.000,28.197,28.489,0.000,28.295,0.000,28.610,0.000,28.497,0.000,29.183,0.000,29.365,0.000,28.763,0.000,28.320,0.000,28.594,0.000,28.641,0.000,28.629,0.000,28.950,0.000,27.980,0.000,28.349,0.000,28.453,0.000,28.852,0.000,0.000,28.364,0.000,28.244,0.000,28.023,0.000,28.247,0.000,29.572,0.000,30.034,0.000,28.667,0.000,28.642,0.000,28.316,0.000,28.311,0.000,28.444,0.000,28.168,0.000,28.403,0.000,28.438,0.000,28.800,0.000,27.913,28.091,0.000,28.598,0.000,28.313,0.000,28.813,0.000,30.533,0.000,32.362,0.000,31.328,0.000,29.314,0.000,28.126,0.000,28.517,0.000,28.644,0.000,28.679,0.000,28.485,0.000,28.714,0.000,28.549,0.000,28.739,0.000,0.000,28.275,0.000,27.955,0.000,28.448,0.000,28.965,0.000,31.879,0.000,32.094,0.000,31.286,0.000,29.814,0.000,28.593,0.000,28.303,0.000,28.808,0.000,28.596,0.000,28.363,0.000,28.585,0.000,28.420,0.000,28.341,28.595,0.000,28.668,0.000,28.724,0.000,29.526,0.000,32.332,0.000,32.878,0.000,32.587,0.000,32.080,0.000,30.319,0.000,29.259,0.000,28.347,0.000,28.371,0.000,28.591,0.000,28.779,0.000,28.650,0.000,28.577,0.000,0.000,28.330,0.000,28.480,0.000,28.753,0.000,30.412,0.000,33.225,0.000,33.175,0.000,32.848,0.000,31.967,0.000,30.751,0.000,29.090,0.000,28.461,0.000,28.636,0.000,28.437,0.000,28.707,0.000,28.479,0.000,28.493,28.450,0.000,28.205,0.000,28.945,0.000,30.841,0.000,33.628,0.000,34.155,0.000,33.454,0.000,32.621,0.000,32.219,0.000,31.181,0.000,28.945,0.000,28.535,0.000,28.354,0.000,28.338,0.000,28.487,0.000,28.645,0.000,0.000,28.420,0.000,28.235,0.000,29.189,0.000,32.258,0.000,34.054,0.000,34.386,0.000,33.366,0.000,32.502,0.000,32.534,0.000,30.553,0.000,28.703,0.000,28.123,0.000,28.465,0.000,28.435,0.000,28.666,0.000,28.458,28.412,0.000,28.618,0.000,29.437,0.000,32.515,0.000,33.633,0.000,34.348,0.000,33.460,0.000,33.297,0.000,32.441,0.000,30.583,0.000,28.901,0.000,28.751,0.000,28.455,0.000,28.551,0.000,28.674,0.000,28.816,0.000,0.000,28.379,0.000,28.929,0.000,30.135,0.000,32.781,0.000,33.364,0.000,33.703,0.000,33.035,0.000,32.681,0.000,32.508,0.000,29.271,0.000,28.813,0.000,28.176,0.000,28.281,0.000,28.308,0.000,28.441,0.000,28.851,28.266,0.000,28.759,0.000,30.103,0.000,32.329,0.000,32.560,0.000,32.963,0.000,32.587,0.000,32.781,0.000,32.408,0.000,29.431,0.000,28.536,0.000,28.849,0.000,28.187,0.000,28.597,0.000,29.227,0.000,28.880,0.000,0.000,28.259,0.000,28.992,0.000,30.442,0.000,32.244,0.000,32.250,0.000,32.312,0.000,32.854,0.000,32.680,0.000,31.065,0.000,28.621,0.000,28.344,0.000,28.447,0.000,28.667,0.000,28.698,0.000,29.718,0.000,28.963,28.429,0.000,28.570,0.000,29.163,0.000,29.828,0.000,31.671,0.000,32.379,0.000,32.265,0.000,32.592,0.000,31.175,0.000,29.218,0.000,28.587,0.000,28.508,0.000,28.957,0.000,29.226,0.000,31.199,0.000,31.547,0.000,0.000,28.137,0.000,28.463,0.000,28.557,0.000,29.704,0.000,30.460,0.000,31.603,0.000,31.990,0.000,32.004,0.000,29.626,0.000,28.473,0.000,28.220,0.000,28.694,0.000,28.703,0.000,29.831,0.000,32.548,0.000,32.176,28.473,0.000,28.264,0.000,28.662,0.000,28.372,0.000,29.225,0.000,29.797,0.000,30.999,0.000,31.244,0.000,29.575,0.000,28.510,0.000,28.530,0.000,28.449,0.000,28.642,0.000,30.602,0.000,32.418,0.000,34.239,0.000,0.000,28.322,0.000,28.078,0.000,28.183,0.000,28.517,0.000,28.593,0.000,29.005,0.000,30.394,0.000,30.257,0.000,28.746,0.000,28.295,0.000,28.561,0.000,28.250,0.000,28.593,0.000,31.333,0.000,33.254,0.000,33.224,28.516,0.000,28.317,0.000,28.465,0.000,28.845,0.000,28.642,0.000,28.464,0.000,28.858,0.000,28.979,0.000,29.039,0.000,28.832,0.000,28.280,0.000,28.837,0.000,29.056,0.000,31.946,0.000,33.101,0.000,32.988,0.000,0.000,28.161,0.000,28.257,0.000,28.346,0.000,28.301,0.000,28.101,0.000,28.288,0.000,28.615,0.000,28.926,0.000,28.512,0.000,28.178,0.000,28.392,0.000,28.412,0.000,30.166,0.000,32.614,0.000,32.530,0.000,32.028 diff --git a/F3:F303/MLX90640test/to_frame1.csv b/F3:F303/MLX90640test/to_frame1.csv new file mode 100644 index 0000000..47b57ce --- /dev/null +++ b/F3:F303/MLX90640test/to_frame1.csv @@ -0,0 +1 @@ +28.711,27.792,28.178,28.268,28.313,28.450,28.631,28.353,28.295,28.221,28.586,28.024,28.336,28.298,28.683,27.972,28.248,28.537,28.573,28.238,29.127,28.777,28.629,28.172,29.070,28.718,28.894,28.509,28.883,29.076,29.687,29.163,28.942,28.618,28.332,28.134,28.541,28.517,28.394,27.982,28.318,28.092,28.151,27.914,28.753,28.156,27.861,28.261,28.118,28.198,28.582,28.528,28.359,28.837,28.618,28.730,28.610,28.814,28.605,28.558,28.881,28.605,29.019,29.005,28.513,28.605,28.482,28.154,28.428,28.766,27.946,28.048,28.248,28.450,28.387,28.199,28.340,28.594,28.128,28.421,28.544,28.256,28.321,28.073,28.986,28.410,28.445,28.408,28.728,28.530,28.778,28.326,29.035,28.677,28.639,28.351,28.483,28.116,28.430,28.237,28.430,28.173,28.300,28.519,28.179,28.303,28.405,28.049,28.329,28.246,28.347,28.466,28.346,28.247,28.304,28.378,28.597,28.835,28.656,28.480,28.723,28.828,28.500,28.428,28.796,28.528,28.297,29.030,28.163,28.340,28.719,28.336,28.268,28.561,28.439,28.254,28.607,28.734,28.199,28.376,28.440,28.248,28.730,27.926,28.361,28.278,28.256,28.490,28.253,28.898,28.563,28.491,28.593,28.432,28.962,28.417,28.746,28.817,28.917,27.554,28.126,28.112,28.473,27.955,28.466,28.365,28.968,28.291,29.580,28.335,28.803,28.610,28.409,28.281,28.132,28.303,28.803,28.246,28.443,28.710,28.649,28.723,28.537,28.532,28.564,28.493,28.667,28.686,28.746,28.565,28.278,28.197,28.489,28.339,28.295,28.444,28.610,28.566,28.497,28.802,29.183,31.090,29.365,29.834,28.763,28.843,28.320,28.427,28.594,28.279,28.641,28.140,28.629,28.230,28.950,28.392,27.980,28.579,28.349,28.584,28.453,28.300,28.852,27.232,28.490,28.364,28.630,28.244,28.633,28.023,28.703,28.247,31.642,29.572,31.352,30.034,29.809,28.667,28.683,28.642,28.605,28.316,28.433,28.311,28.448,28.444,28.483,28.168,28.580,28.403,28.510,28.438,28.743,28.800,27.995,27.913,28.091,28.460,28.598,28.515,28.313,28.996,28.813,30.302,30.533,32.592,32.362,32.093,31.328,31.273,29.314,29.422,28.126,28.591,28.517,28.460,28.644,28.192,28.679,28.554,28.485,28.324,28.714,28.284,28.549,28.354,28.739,27.168,28.536,28.275,28.361,27.955,28.948,28.448,30.536,28.965,32.884,31.879,32.682,32.094,32.728,31.286,30.920,29.814,29.226,28.593,28.639,28.303,28.674,28.808,28.445,28.596,28.308,28.363,28.237,28.585,28.762,28.420,27.634,28.341,28.595,28.757,28.668,28.844,28.724,29.482,29.526,32.560,32.332,33.558,32.878,32.994,32.587,32.664,32.080,32.187,30.319,30.384,29.259,28.561,28.347,28.620,28.371,28.259,28.591,28.458,28.779,28.458,28.650,28.496,28.577,28.159,28.835,28.330,28.219,28.480,29.530,28.753,32.294,30.412,34.299,33.225,33.583,33.175,32.902,32.848,32.213,31.967,31.870,30.751,29.610,29.090,28.328,28.461,27.930,28.636,28.181,28.437,28.476,28.707,28.600,28.479,28.681,28.493,28.450,28.323,28.205,28.425,28.945,31.092,30.841,33.522,33.628,34.564,34.155,33.856,33.454,32.664,32.621,32.372,32.219,31.654,31.181,28.926,28.945,28.697,28.535,28.474,28.354,28.337,28.338,28.403,28.487,28.216,28.645,28.384,28.889,28.420,28.804,28.235,30.758,29.189,32.667,32.258,33.935,34.054,33.947,34.386,33.459,33.366,32.776,32.502,31.703,32.534,29.363,30.553,28.741,28.703,28.474,28.123,28.522,28.465,28.276,28.435,28.844,28.666,28.557,28.458,28.412,28.779,28.618,28.839,29.437,31.981,32.515,32.602,33.633,33.339,34.348,33.200,33.460,32.708,33.297,32.716,32.441,30.769,30.583,28.879,28.901,28.662,28.751,28.224,28.455,28.549,28.551,28.501,28.674,28.491,28.816,28.358,28.403,28.379,29.006,28.929,31.579,30.135,32.674,32.781,32.740,33.364,32.741,33.703,32.951,33.035,32.577,32.681,31.359,32.508,28.893,29.271,28.502,28.813,28.726,28.176,28.417,28.281,28.839,28.308,28.837,28.441,28.693,28.851,28.266,28.880,28.759,28.696,30.103,30.616,32.329,31.805,32.560,32.485,32.963,32.454,32.587,32.690,32.781,31.630,32.408,29.459,29.431,28.422,28.536,28.365,28.849,28.236,28.187,28.445,28.597,29.407,29.227,29.049,28.880,29.072,28.191,28.259,28.706,28.992,29.507,30.442,30.965,32.244,31.855,32.250,32.388,32.312,32.607,32.854,31.842,32.680,30.104,31.065,28.447,28.621,28.679,28.344,28.156,28.447,28.570,28.667,29.436,28.698,30.319,29.718,28.776,28.963,28.429,28.555,28.570,28.395,29.163,28.748,29.828,29.420,31.671,30.793,32.379,31.911,32.265,32.313,32.592,30.116,31.175,28.890,29.218,28.496,28.587,28.648,28.508,28.310,28.957,28.748,29.226,31.269,31.199,32.328,31.547,29.811,28.888,28.137,28.285,28.463,28.483,28.557,28.797,29.704,29.399,30.460,30.472,31.603,31.694,31.990,30.547,32.004,28.930,29.626,28.220,28.473,28.552,28.220,28.351,28.694,29.062,28.703,30.867,29.831,32.820,32.548,32.478,32.176,28.473,28.493,28.264,28.442,28.662,28.390,28.372,28.661,29.225,28.774,29.797,29.597,30.999,30.204,31.244,29.254,29.575,28.162,28.510,28.532,28.530,28.600,28.449,28.428,28.642,29.765,30.602,32.329,32.418,34.008,34.239,32.016,28.925,28.322,28.395,28.078,28.614,28.183,28.452,28.517,28.848,28.593,28.970,29.005,29.060,30.394,28.891,30.257,28.808,28.746,28.235,28.295,28.682,28.561,28.342,28.250,29.916,28.593,31.676,31.333,33.850,33.254,32.702,33.224,28.516,28.235,28.317,28.028,28.465,28.464,28.845,28.247,28.642,28.392,28.464,28.436,28.858,28.573,28.979,28.471,29.039,28.500,28.832,28.364,28.280,28.374,28.837,28.830,29.056,31.258,31.946,32.501,33.101,33.231,32.988,30.287,28.260,28.161,28.310,28.257,28.417,28.346,28.377,28.301,28.276,28.101,28.675,28.288,28.494,28.615,28.389,28.926,28.616,28.512,27.969,28.178,28.515,28.392,28.549,28.412,31.642,30.166,32.618,32.614,33.084,32.530,31.086,32.028 diff --git a/F3:F303/MLX90640test/usb_descr.c b/F3:F303/MLX90640test/usb_descr.c new file mode 100644 index 0000000..3e1a872 --- /dev/null +++ b/F3:F303/MLX90640test/usb_descr.c @@ -0,0 +1,210 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "usb_descr.h" + +// low/high for uint16_t +#define L16(x) (x & 0xff) +#define H16(x) (x >> 8) + +static const uint8_t USB_DeviceDescriptor[] = { + USB_DT_DEVICE_SIZE, // bLength + USB_DT_DEVICE, // bDescriptorType + L16(bcdUSB), // bcdUSB_L + H16(bcdUSB), // bcdUSB_H + USB_CLASS_MISC, // bDeviceClass + bDeviceSubClass, // bDeviceSubClass + bDeviceProtocol, // bDeviceProtocol + USB_EP0BUFSZ, // bMaxPacketSize + L16(idVendor), // idVendor_L + H16(idVendor), // idVendor_H + L16(idProduct), // idProduct_L + H16(idProduct), // idProduct_H + L16(bcdDevice_Ver), // bcdDevice_Ver_L + H16(bcdDevice_Ver), // bcdDevice_Ver_H + iMANUFACTURER_DESCR, // iManufacturer - indexes of string descriptors in array + iPRODUCT_DESCR, // iProduct + iSERIAL_DESCR, // iSerial + bNumConfigurations // bNumConfigurations +}; + +static const uint8_t USB_DeviceQualifierDescriptor[] = { + USB_DT_QUALIFIER_SIZE, //bLength + USB_DT_QUALIFIER, // bDescriptorType + L16(bcdUSB), // bcdUSB_L + H16(bcdUSB), // bcdUSB_H + USB_CLASS_PER_INTERFACE, // bDeviceClass + bDeviceSubClass, // bDeviceSubClass + bDeviceProtocol, // bDeviceProtocol + USB_EP0BUFSZ, // bMaxPacketSize0 + bNumConfigurations, // bNumConfigurations + 0 // Reserved +}; + +#define wTotalLength (USB_DT_CONFIG_SIZE + (bNumInterfaces * USB_DT_INTERFACE_SIZE) + (bTotNumEndpoints * USB_DT_ENDPOINT_SIZE) + (bNumCsInterfaces * USB_DT_CS_INTERFACE_SIZE) - 1) + +static const uint8_t USB_ConfigDescriptor[] = { + // Configuration Descriptor + USB_DT_CONFIG_SIZE, // bLength: Configuration Descriptor size + USB_DT_CONFIG, // bDescriptorType: Configuration + L16(wTotalLength), // wTotalLength.L :no of returned bytes + H16(wTotalLength), // wTotalLength.H + bNumInterfaces, // bNumInterfaces + 1, // bConfigurationValue: Current configuration value + 0, // iConfiguration: Index of string descriptor describing the configuration or 0 + BusPowered, // bmAttributes - Bus powered + 50, // MaxPower in 2mA units + //--------------------------------------------------------------------------- + // Virtual command Interface Descriptor + USB_DT_INTERFACE_SIZE, // bLength: Interface Descriptor size + USB_DT_INTERFACE, // bDescriptorType: Interface + 0, // bInterfaceNumber: Number of Interface + 0, // bAlternateSetting: Alternate setting + 1, // bNumEndpoints: one for this + USB_CLASS_COMM, // bInterfaceClass + 2, // bInterfaceSubClass: ACM + 1, // bInterfaceProtocol: Common AT commands + iINTERFACE_DESCR1, // iInterface + // ---- CS Interfaces + USB_DT_CS_INTERFACE_SIZE, // bLength + USB_DT_CS_INTERFACE, // bDescriptorType: CS_INTERFACE + 0, // bDescriptorSubtype: Header Func Desc + 0x10, // bcdCDC: spec release number + 1, // bDataInterface + USB_DT_CS_INTERFACE_SIZE, // bLength + USB_DT_CS_INTERFACE, // bDescriptorType: CS_INTERFACE + 1, // bDescriptorSubtype: Call Management Func Desc + 0, // bmCapabilities: D0+D1 + 1, // bDataInterface + USB_DT_CS_INTERFACE_SIZE-1, // bLength + USB_DT_CS_INTERFACE, // bDescriptorType: CS_INTERFACE + 2, // bDescriptorSubtype: Abstract Control Management desc + 2, // bmCapabilities + USB_DT_CS_INTERFACE_SIZE, // bLength + USB_DT_CS_INTERFACE, // bDescriptorType: CS_INTERFACE + 6, // bDescriptorSubtype: Union func desc + 0, // bMasterInterface: Communication class interface + 1, // bSlaveInterface0: Data Class Interface + // Virtual endpoint 1 Descriptor + USB_DT_ENDPOINT_SIZE, // bLength: Endpoint Descriptor size + USB_DT_ENDPOINT, // bDescriptorType: Endpoint + 0x8A, // bEndpointAddress IN10 + USB_BM_ATTR_INTERRUPT, // bmAttributes: Interrupt + L16(USB_EP1BUFSZ), // wMaxPacketSize LO + H16(USB_EP1BUFSZ), // wMaxPacketSize HI + 0x10, // bInterval: 16ms + //--------------------------------------------------------------------------- + // Data interface + USB_DT_INTERFACE_SIZE, // bLength: Interface Descriptor size + USB_DT_INTERFACE, // bDescriptorType: Interface + 1, // bInterfaceNumber: Number of Interface + 0, // bAlternateSetting: Alternate setting + 2, // bNumEndpoints: in and out + USB_CLASS_DATA, // bInterfaceClass + 2, // bInterfaceSubClass: ACM + 0, // bInterfaceProtocol + 0, // iInterface + //Endpoint IN1 Descriptor + USB_DT_ENDPOINT_SIZE, // bLength: Endpoint Descriptor size + USB_DT_ENDPOINT, // bDescriptorType: Endpoint + 0x81, // bEndpointAddress: IN1 + USB_BM_ATTR_BULK, // bmAttributes: Bulk + L16(USB_TXBUFSZ), // wMaxPacketSize LO + H16(USB_TXBUFSZ), // wMaxPacketSize HI + 0, // bInterval: ignore for Bulk transfer + // Endpoint OUT1 Descriptor + USB_DT_ENDPOINT_SIZE, // bLength: Endpoint Descriptor size + USB_DT_ENDPOINT, // bDescriptorType: Endpoint + 0x01, // bEndpointAddress: OUT1 + USB_BM_ATTR_BULK, // bmAttributes: Bulk + L16(USB_RXBUFSZ), // wMaxPacketSize LO + H16(USB_RXBUFSZ), // wMaxPacketSize HI + 0, // bInterval: ignore for Bulk transfer + +}; + +//const uint8_t HID_ReportDescriptor[]; + +_USB_LANG_ID_(LD, LANG_US); +_USB_STRING_(SD, u"0.0.1"); +_USB_STRING_(MD, u"eddy@sao.ru"); +_USB_STRING_(PD, u"USB-CDC"); +_USB_STRING_(ID, u"usbcdc"); + +static const void* const StringDescriptor[iDESCR_AMOUNT] = { + [iLANGUAGE_DESCR] = &LD, + [iMANUFACTURER_DESCR] = &MD, + [iPRODUCT_DESCR] = &PD, + [iSERIAL_DESCR] = &SD, + [iINTERFACE_DESCR1] = &ID +}; + +static void wr0(const uint8_t *buf, uint16_t size, uint16_t askedsize){ + if(askedsize < size) size = askedsize; // shortened request + if(size < USB_EP0BUFSZ){ + EP_WriteIRQ(0, buf, size); + return; + } + while(size){ + uint16_t l = size; + if(l > USB_EP0BUFSZ) l = USB_EP0BUFSZ; + EP_WriteIRQ(0, buf, l); + buf += l; + size -= l; + uint8_t needzlp = (l == USB_EP0BUFSZ) ? 1 : 0; + if(size || needzlp){ // send last data buffer + uint16_t epstatus = KEEP_DTOG(USB->EPnR[0]); + // keep DTOGs, clear CTR_RX,TX, set TX VALID, leave stat_Rx + USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX|USB_EPnR_STAT_RX)) + ^ USB_EPnR_STAT_TX; + uint32_t ctr = 1000000; + while(--ctr && (USB->ISTR & USB_ISTR_CTR) == 0){IWDG->KR = IWDG_REFRESH;}; + if((USB->ISTR & USB_ISTR_CTR) == 0){ + return; + } + if(needzlp) EP_WriteIRQ(0, NULL, 0); + } + } +} + +void get_descriptor(config_pack_t *pack){ + uint8_t descrtype = pack->wValue >> 8, + descridx = pack->wValue & 0xff; + switch(descrtype){ + case DEVICE_DESCRIPTOR: + wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor), pack->wLength); + break; + case CONFIGURATION_DESCRIPTOR: + wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor), pack->wLength); + break; + case STRING_DESCRIPTOR: + if(descridx < iDESCR_AMOUNT){ + wr0((const uint8_t *)StringDescriptor[descridx], *((uint8_t*)StringDescriptor[descridx]), pack->wLength); + }else{ + EP_WriteIRQ(0, NULL, 0); + } + break; + case DEVICE_QUALIFIER_DESCRIPTOR: + wr0(USB_DeviceQualifierDescriptor, sizeof(USB_DeviceQualifierDescriptor), pack->wLength); + break; + /* case HID_REPORT_DESCRIPTOR: + wr0(HID_ReportDescriptor, sizeof(HID_ReportDescriptor), pack->wLength); + break;*/ + default: + break; + } +} diff --git a/F3:F303/MLX90640test/usb_descr.h b/F3:F303/MLX90640test/usb_descr.h new file mode 100644 index 0000000..d260af2 --- /dev/null +++ b/F3:F303/MLX90640test/usb_descr.h @@ -0,0 +1,62 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +#include "usb_lib.h" + +// definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor +// bcdUSB: 1.10 +#define bcdUSB 0x0110 +// Class - Misc (EF), subclass - common (2), protocol - interface association descr (1) +#define bDeviceSubClass 0x02 +#define bDeviceProtocol 0x01 +#define idVendor 0x0483 +#define idProduct 0x5740 +#define bcdDevice_Ver 0x0200 +#define bNumConfigurations 1 + +// amount of interfaces and endpoints (except 0) used +#define bNumInterfaces 2 +#define bTotNumEndpoints 3 +#define bNumCsInterfaces 4 + +// powered +#define BusPowered (1<<7) +#define SelfPowered (1<<6) +#define RemoteWakeup (1<<5) + +// buffer sizes +// for USB FS EP0 buffers are from 8 to 64 bytes long +#define USB_EP0BUFSZ 64 +#define USB_EP1BUFSZ 10 +// Rx/Tx EPs +#define USB_RXBUFSZ 64 +#define USB_TXBUFSZ 64 + +// string descriptors +enum{ + iLANGUAGE_DESCR, + iMANUFACTURER_DESCR, + iPRODUCT_DESCR, + iSERIAL_DESCR, + iINTERFACE_DESCR1, + iDESCR_AMOUNT +}; + +void get_descriptor(config_pack_t *pack); diff --git a/F3:F303/MLX90640test/usb_dev.c b/F3:F303/MLX90640test/usb_dev.c new file mode 100644 index 0000000..8e519e4 --- /dev/null +++ b/F3:F303/MLX90640test/usb_dev.c @@ -0,0 +1,240 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "ringbuffer.h" +#include "usb_descr.h" +#include "usb_dev.h" + +// Class-Specific Control Requests +#define SEND_ENCAPSULATED_COMMAND 0x00 // unused +#define GET_ENCAPSULATED_RESPONSE 0x01 // unused +#define SET_COMM_FEATURE 0x02 // unused +#define GET_COMM_FEATURE 0x03 // unused +#define CLEAR_COMM_FEATURE 0x04 // unused +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 +#define SEND_BREAK 0x23 + +// control line states +#define CONTROL_DTR 0x01 +#define CONTROL_RTS 0x02 + +// inbuf overflow when receiving +static volatile uint8_t bufovrfl = 0; + +// receive buffer: hold data until chkin() call +static uint8_t volatile rcvbuf[USB_RXBUFSZ]; +static uint8_t volatile rcvbuflen = 0; +// line coding +usb_LineCoding WEAK lineCoding = {115200, 0, 0, 8}; +// CDC configured and ready to use +volatile uint8_t CDCready = 0; + +// ring buffers for incoming and outgoing data +static uint8_t obuf[RBOUTSZ], ibuf[RBINSZ]; +static volatile ringbuffer rbout = {.data = obuf, .length = RBOUTSZ, .head = 0, .tail = 0}; +static volatile ringbuffer rbin = {.data = ibuf, .length = RBINSZ, .head = 0, .tail = 0}; +// last send data size +static volatile int lastdsz = 0; + +static void chkin(){ + if(bufovrfl) return; // allow user to know that previous buffer was overflowed and cleared + if(!rcvbuflen) return; + int w = RB_write((ringbuffer*)&rbin, (uint8_t*)rcvbuf, rcvbuflen); + if(w < 0){ + return; + } + if(w != rcvbuflen) bufovrfl = 1; + rcvbuflen = 0; + uint16_t status = KEEP_DTOG(USB->EPnR[1]); // don't change DTOG + USB->EPnR[1] = (status & ~(USB_EPnR_STAT_TX|USB_EPnR_CTR_RX)) ^ USB_EPnR_STAT_RX; // prepare to get next data portion +} + +// called from transmit EP to send next data portion or by user - when new transmission starts +static void send_next(){ + uint8_t usbbuff[USB_TXBUFSZ]; + int buflen = RB_read((ringbuffer*)&rbout, (uint8_t*)usbbuff, USB_TXBUFSZ); + if(buflen == 0){ + if(lastdsz == 64) EP_Write(1, NULL, 0); // send ZLP after 64 bits packet when nothing more to send + lastdsz = 0; + return; + }else if(buflen < 0){ + lastdsz = 0; + return; + } + EP_Write(1, (uint8_t*)usbbuff, buflen); + lastdsz = buflen; +} + +// data IN/OUT handler +static void rxtx_handler(){ + uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]); + if(RX_FLAG(epstatus)){ // receive data + if(rcvbuflen){ + bufovrfl = 1; // lost last data + rcvbuflen = 0; + } + rcvbuflen = EP_Read(1, (uint8_t*)rcvbuf); + USB->EPnR[1] = epstatus & ~(USB_EPnR_CTR_RX | USB_EPnR_STAT_RX | USB_EPnR_STAT_TX); // keep RX in STALL state until read data + chkin(); // try to write current data into RXbuf if it's not busy + }else{ // tx successfull + USB->EPnR[1] = (epstatus & ~(USB_EPnR_CTR_TX | USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX; + send_next(); + } +} + +// weak handlers: change them somewhere else if you want to setup USART +// SET_LINE_CODING +void WEAK linecoding_handler(usb_LineCoding *lc){ + lineCoding = *lc; +} + +// SET_CONTROL_LINE_STATE +void WEAK clstate_handler(uint16_t val){ + CDCready = val; // CONTROL_DTR | CONTROL_RTS -> interface connected; 0 -> disconnected +} + +// SEND_BREAK +void WEAK break_handler(){ + CDCready = 0; +} + + +// USB is configured: setup endpoints +void set_configuration(){ + EP_Init(1, EP_TYPE_BULK, USB_TXBUFSZ, USB_RXBUFSZ, rxtx_handler); // IN1 and OUT1 +} + +// PL2303 CLASS request +void usb_class_request(config_pack_t *req, uint8_t *data, uint16_t datalen){ + uint8_t recipient = REQUEST_RECIPIENT(req->bmRequestType); + uint8_t dev2host = (req->bmRequestType & 0x80) ? 1 : 0; + switch(recipient){ + case REQ_RECIPIENT_INTERFACE: + switch(req->bRequest){ + case SET_LINE_CODING: + if(!data || !datalen) break; // wait for data + if(datalen == sizeof(usb_LineCoding)) + linecoding_handler((usb_LineCoding*)data); + break; + case GET_LINE_CODING: + EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); + break; + case SET_CONTROL_LINE_STATE: + clstate_handler(req->wValue); + break; + case SEND_BREAK: + break_handler(); + break; + default: + break; + } + break; + default: + if(dev2host) EP_WriteIRQ(0, NULL, 0); + } + if(!dev2host) EP_WriteIRQ(0, NULL, 0); +} + +// blocking send full content of ring buffer +int USB_sendall(){ + while(lastdsz > 0){ + if(!CDCready) return FALSE; + } + return TRUE; +} + +// put `buf` into queue to send +int USB_send(const uint8_t *buf, int len){ + if(!buf || !CDCready || !len) return FALSE; + while(len){ + int a = RB_write((ringbuffer*)&rbout, buf, len); + if(a > 0){ + len -= a; + buf += a; + } else if (a < 0) continue; // do nothing if buffer is in reading state + if(lastdsz == 0) send_next(); // need to run manually - all data sent, so no IRQ on IN + } + return TRUE; +} + +int USB_putbyte(uint8_t byte){ + if(!CDCready) return FALSE; + int l = 0; + while((l = RB_write((ringbuffer*)&rbout, &byte, 1)) != 1){ + if(l < 0) continue; + } + if(lastdsz == 0) send_next(); // need to run manually - all data sent, so no IRQ on IN + return TRUE; +} + +int USB_sendstr(const char *string){ + if(!string || !CDCready) return FALSE; + int len = 0; + const char *b = string; + while(*b++) ++len; + if(!len) return FALSE; + return USB_send((const uint8_t*)string, len); +} + +/** + * @brief USB_receive - get binary data from receiving ring-buffer + * @param buf (i) - buffer for received data + * @param len - length of `buf` + * @return amount of received bytes (negative, if overfull happened) + */ +int USB_receive(uint8_t *buf, int len){ + chkin(); + if(bufovrfl){ + while(1 != RB_clearbuf((ringbuffer*)&rbin)); + bufovrfl = 0; + return -1; + } + int sz = RB_read((ringbuffer*)&rbin, buf, len); + if(sz < 0) return 0; // buffer in writting state + return sz; +} + +/** + * @brief USB_receivestr - get string up to '\n' and replace '\n' with 0 + * @param buf - receiving buffer + * @param len - its length + * @return strlen or negative value indicating overflow (if so, string won't be ends with 0 and buffer should be cleared) + */ +int USB_receivestr(char *buf, int len){ + chkin(); + if(bufovrfl){ + while(1 != RB_clearbuf((ringbuffer*)&rbin)); + bufovrfl = 0; + return -1; + } + int l = RB_readto((ringbuffer*)&rbin, '\n', (uint8_t*)buf, len); + if(l < 1){ + if(rbin.length == RB_datalen((ringbuffer*)&rbin)){ // buffer is full but no '\n' found + while(1 != RB_clearbuf((ringbuffer*)&rbin)); + return -1; + } + return 0; + } + if(l == 0) return 0; + buf[l-1] = 0; // replace '\n' with strend + return l; +} + diff --git a/F3:F303/MLX90640test/usb_dev.h b/F3:F303/MLX90640test/usb_dev.h new file mode 100644 index 0000000..1f8003c --- /dev/null +++ b/F3:F303/MLX90640test/usb_dev.h @@ -0,0 +1,57 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include +#include "usb_lib.h" + +typedef struct { + uint32_t dwDTERate; + uint8_t bCharFormat; +#define USB_CDC_1_STOP_BITS 0 +#define USB_CDC_1_5_STOP_BITS 1 +#define USB_CDC_2_STOP_BITS 2 + uint8_t bParityType; +#define USB_CDC_NO_PARITY 0 +#define USB_CDC_ODD_PARITY 1 +#define USB_CDC_EVEN_PARITY 2 +#define USB_CDC_MARK_PARITY 3 +#define USB_CDC_SPACE_PARITY 4 + uint8_t bDataBits; +} __attribute__ ((packed)) usb_LineCoding; + +extern usb_LineCoding lineCoding; +extern volatile uint8_t CDCready; + +void break_handler(); +void clstate_handler(uint16_t val); +void linecoding_handler(usb_LineCoding *lc); + + +// sizes of ringbuffers for outgoing and incoming data +#define RBOUTSZ (1024) +#define RBINSZ (1024) + +#define newline() USB_putbyte('\n') +#define USND(s) do{USB_sendstr(s); USB_putbyte('\n');}while(0) + +int USB_sendall(); +int USB_send(const uint8_t *buf, int len); +int USB_putbyte(uint8_t byte); +int USB_sendstr(const char *string); +int USB_receive(uint8_t *buf, int len); +int USB_receivestr(char *buf, int len); diff --git a/F3:F303/MLX90640test/usb_lib.c b/F3:F303/MLX90640test/usb_lib.c new file mode 100644 index 0000000..9f01a8f --- /dev/null +++ b/F3:F303/MLX90640test/usb_lib.c @@ -0,0 +1,368 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include + +#include "usb_lib.h" +#include "usb_descr.h" +#include "usb_dev.h" + +static ep_t endpoints[STM32ENDPOINTS]; + +static uint16_t USB_Addr = 0; +static uint8_t setupdatabuf[EP0DATABUF_SIZE]; +static config_pack_t *setup_packet = (config_pack_t*) setupdatabuf; +volatile uint8_t usbON = 0; // device is configured and active + +static uint16_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) +static inline void std_d2h_req(){ + uint16_t st = 0; + switch(setup_packet->bRequest){ + case GET_DESCRIPTOR: + get_descriptor(setup_packet); + break; + case GET_STATUS: + EP_WriteIRQ(0, (uint8_t *)&st, 2); // send status: Bus Powered + break; + case GET_CONFIGURATION: + EP_WriteIRQ(0, (uint8_t*)&configuration, 1); + break; + default: + EP_WriteIRQ(0, NULL, 0); + break; + } +} + +static inline void std_h2d_req(){ + switch(setup_packet->bRequest){ + case SET_ADDRESS: + // new address will be assigned later - after acknowlegement or request to host + USB_Addr = setup_packet->wValue; + break; + case SET_CONFIGURATION: + // Now device configured + configuration = setup_packet->wValue; + set_configuration(); + usbON = 1; + break; + default: + break; + } +} + +void WEAK usb_standard_request(){ + uint8_t recipient = REQUEST_RECIPIENT(setup_packet->bmRequestType); + uint8_t dev2host = (setup_packet->bmRequestType & 0x80) ? 1 : 0; + switch(recipient){ + case REQ_RECIPIENT_DEVICE: + if(dev2host){ + std_d2h_req(); + }else{ + std_h2d_req(); + } + break; + case REQ_RECIPIENT_INTERFACE: + if(dev2host && setup_packet->bRequest == GET_DESCRIPTOR){ + get_descriptor(setup_packet); + } + break; + case REQ_RECIPIENT_ENDPOINT: + if(setup_packet->bRequest == CLEAR_FEATURE){ + }else{ /* wrong */ } + break; + default: + break; + } + if(!dev2host) EP_WriteIRQ(0, NULL, 0); +} + +void WEAK usb_class_request(config_pack_t *req, uint8_t _U_ *data, uint16_t _U_ datalen){ + switch(req->bRequest){ + case GET_INTERFACE: + break; + case SET_CONFIGURATION: // set featuring by req->wValue + break; + default: + break; + } + if(0 == (setup_packet->bmRequestType & 0x80)) // host2dev + EP_WriteIRQ(0, NULL, 0); +} + +void WEAK usb_vendor_request(config_pack_t _U_ *packet, uint8_t _U_ *data, uint16_t _U_ datalen){ + if(0 == (setup_packet->bmRequestType & 0x80)) // host2dev + EP_WriteIRQ(0, NULL, 0); +} + +/* +bmRequestType: 76543210 +7 direction: 0 - host->device, 1 - device->host +65 type: 0 - standard, 1 - class, 2 - vendor +4..0 getter: 0 - device, 1 - interface, 2 - endpoint, 3 - other +*/ +/** + * Endpoint0 (control) handler + */ +static void EP0_Handler(){ + uint8_t ep0dbuflen = 0; + uint8_t ep0databuf[EP0DATABUF_SIZE]; + uint16_t epstatus = KEEP_DTOG(USB->EPnR[0]); // EP0R on input -> return this value after modifications + int rxflag = RX_FLAG(epstatus); + //if(rxflag){ } + // check direction + if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit) + if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack + EP_Read(0, setupdatabuf); + // interrupt handler will be called later + }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf + //if(endpoints[0].rx_cnt){ } + ep0dbuflen = EP_Read(0, ep0databuf); + } + } + if(rxflag){ + uint8_t reqtype = REQUEST_TYPE(setup_packet->bmRequestType); + switch(reqtype){ + case REQ_TYPE_STANDARD: + if(SETUP_FLAG(epstatus)){ + usb_standard_request(); + }else{ } + break; + case REQ_TYPE_CLASS: + usb_class_request(setup_packet, ep0databuf, ep0dbuflen); + break; + case REQ_TYPE_VENDOR: + usb_vendor_request(setup_packet, ep0databuf, ep0dbuflen); + break; + default: + EP_WriteIRQ(0, NULL, 0); + break; + } + } + if(TX_FLAG(epstatus)){ + // now we can change address after enumeration + if ((USB->DADDR & USB_DADDR_ADD) != USB_Addr){ + USB->DADDR = USB_DADDR_EF | USB_Addr; + usbON = 0; + } + } + //epstatus = KEEP_DTOG(USB->EPnR[0]); + if(rxflag) epstatus ^= USB_EPnR_STAT_TX; // start ZLP or data transmission + else epstatus &= ~USB_EPnR_STAT_TX; // or leave unchanged + // keep DTOGs, clear CTR_RX,TX, set RX VALID + USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_RX; +} + +/** + * Write data to EP buffer (called from IRQ handler) + * @param number - EP number + * @param *buf - array with data + * @param size - its size + */ +void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ + if(size > endpoints[number].txbufsz) size = endpoints[number].txbufsz; + uint16_t N2 = (size + 1) >> 1; + // the buffer is 16-bit, so we should copy data as it would be uint16_t + uint16_t *buf16 = (uint16_t *)buf; +#if defined USB1_16 + // very bad: what if `size` is odd? + uint32_t *out = (uint32_t *)endpoints[number].tx_buf; + for(int i = 0; i < N2; ++i, ++out){ + *out = buf16[i]; + } +#elif defined USB2_16 + // use memcpy instead? + for(int i = 0; i < N2; i++){ + endpoints[number].tx_buf[i] = buf16[i]; + } +#else +#error "Define USB1_16 or USB2_16" +#endif + USB_BTABLE->EP[number].USB_COUNT_TX = size; +} + +/** + * Write data to EP buffer (called outside IRQ handler) + * @param number - EP number + * @param *buf - array with data + * @param size - its size + */ +void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){ + EP_WriteIRQ(number, buf, size); + uint16_t epstatus = KEEP_DTOG(USB->EPnR[number]); + // keep DTOGs and RX stat, clear CTR_TX & set TX VALID to start transmission + USB->EPnR[number] = (epstatus & ~(USB_EPnR_CTR_TX | USB_EPnR_STAT_RX)) ^ USB_EPnR_STAT_TX; +} + +/* + * Copy data from EP buffer into user buffer area + * @param *buf - user array for data + * @return amount of data read + */ +int EP_Read(uint8_t number, uint8_t *buf){ + int sz = endpoints[number].rx_cnt; + if(!sz) return 0; + endpoints[number].rx_cnt = 0; +#if defined USB1_16 + int n = (sz + 1) >> 1; + uint32_t *in = (uint32_t*)endpoints[number].rx_buf; + uint16_t *out = (uint16_t*)buf; + for(int i = 0; i < n; ++i, ++in) + out[i] = *(uint16_t*)in; +#elif defined USB2_16 + // use memcpy instead? + for(int i = 0; i < sz; ++i) + buf[i] = endpoints[number].rx_buf[i]; +#else +#error "Define USB1_16 or USB2_16" +#endif + return sz; +} + + +static uint16_t lastaddr = LASTADDR_DEFAULT; +/** + * Endpoint initialisation + * @param number - EP num (0...7) + * @param type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT) + * @param txsz - transmission buffer size @ USB/CAN buffer + * @param rxsz - reception buffer size @ USB/CAN buffer + * @param uint16_t (*func)(ep_t *ep) - EP handler function + * @return 0 if all OK + */ +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)(ep_t ep)){ + if(number >= STM32ENDPOINTS) return 4; // out of configured amount + if(txsz > USB_BTABLE_SIZE/ACCESSZ || rxsz > USB_BTABLE_SIZE/ACCESSZ) return 1; // buffer too large + if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE/ACCESSZ) return 2; // out of btable + USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); + USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1; + if(rxsz & 1) return 3; // wrong rx buffer size + uint16_t countrx = 0; + if(rxsz < 64) countrx = rxsz / 2; + else{ + if(rxsz & 0x1f) return 3; // should be multiple of 32 + countrx = 31 + rxsz / 32; + } + USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; + endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); + endpoints[number].txbufsz = txsz; + lastaddr += txsz; + USB_BTABLE->EP[number].USB_COUNT_TX = 0; + USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; + endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); + lastaddr += rxsz; + USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; + endpoints[number].func = func; + return 0; +} + +// standard IRQ handler +void USB_IRQ(){ + uint32_t CNTR = USB->CNTR; + USB->CNTR = 0; + if(USB->ISTR & USB_ISTR_RESET){ + usbON = 0; + // Reinit registers + CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM; + // Endpoint 0 - CONTROL + // ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes! + lastaddr = LASTADDR_DEFAULT; + // clear address, leave only enable bit + USB->DADDR = USB_DADDR_EF; + USB->ISTR = ~USB_ISTR_RESET; + if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0BUFSZ, USB_EP0BUFSZ, EP0_Handler)){ + return; + }; + } + if(USB->ISTR & USB_ISTR_CTR){ + // EP number + uint8_t n = USB->ISTR & USB_ISTR_EPID; + // copy received bytes amount + endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter + // call EP handler + if(endpoints[n].func) endpoints[n].func(); + } + if(USB->ISTR & USB_ISTR_WKUP){ // wakeup +#ifndef STM32F0 + CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE | USB_CNTR_WKUPM); // clear suspend flags +#else + CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM); +#endif + USB->ISTR = ~USB_ISTR_WKUP; + } + if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep + usbON = 0; +#ifndef STM32F0 + CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE | USB_CNTR_WKUPM; +#else + CNTR |= USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM; +#endif + CNTR &= ~(USB_CNTR_SUSPM); + USB->ISTR = ~USB_ISTR_SUSP; + } + USB->CNTR = CNTR; // rewoke interrupts +} + +// here we suppose that all PIN settings done in hw_setup earlier +void USB_setup(){ +#if defined STM32F3 + NVIC_DisableIRQ(USB_LP_IRQn); + // remap USB LP & Wakeup interrupts to 75 and 76 - works only on pure F303 + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // enable tacting of SYSCFG + SYSCFG->CFGR1 |= SYSCFG_CFGR1_USB_IT_RMP; +#elif defined STM32F1 + NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); + NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn); +#elif defined STM32F0 + NVIC_DisableIRQ(USB_IRQn); + RCC->APB1ENR |= RCC_APB1ENR_CRSEN; + RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB + RCC->CR2 |= RCC_CR2_HSI48ON; // turn ON HSI48 + uint32_t tmout = 16000000; + while(!(RCC->CR2 & RCC_CR2_HSI48RDY)){if(--tmout == 0) break;} + FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; + CRS->CFGR &= ~CRS_CFGR_SYNCSRC; + CRS->CFGR |= CRS_CFGR_SYNCSRC_1; // USB SOF selected as sync source + CRS->CR |= CRS_CR_AUTOTRIMEN; // enable auto trim + CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only + RCC->CFGR |= RCC_CFGR_SW; +#endif + RCC->APB1ENR |= RCC_APB1ENR_USBEN; + //?? + USB->CNTR = USB_CNTR_FRES; // Force USB Reset + for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms + USB->CNTR = 0; + USB->BTABLE = 0; + USB->DADDR = 0; + USB->ISTR = 0; + USB->CNTR = USB_CNTR_RESETM; // allow only reset interrupts +#if defined STM32F3 + NVIC_EnableIRQ(USB_LP_IRQn); +#elif defined STM32F1 + NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); +#elif defined STM32F0 + USB->BCDR |= USB_BCDR_DPPU; + NVIC_EnableIRQ(USB_IRQn); +#endif +} + + +#if defined STM32F3 +void usb_lp_isr() __attribute__ ((alias ("USB_IRQ"))); +#elif defined STM32F1 +void usb_lp_can_rx0_isr() __attribute__ ((alias ("USB_IRQ"))); +#elif defined STM32F0 +void usb_isr() __attribute__ ((alias ("USB_IRQ"))); +#endif diff --git a/F3:F303/MLX90640test/usb_lib.h b/F3:F303/MLX90640test/usb_lib.h new file mode 100644 index 0000000..d55c83f --- /dev/null +++ b/F3:F303/MLX90640test/usb_lib.h @@ -0,0 +1,328 @@ +/* + * Copyright 2024 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include +#include + +#ifndef _U_ +#define _U_ __attribute__((unused)) +#endif + +/****************************************************************** + * Hardware registers etc * + *****************************************************************/ +#if defined STM32F0 +#include +#elif defined STM32F1 +#include +// there's no this define in standard header +#define USB_BASE ((uint32_t)0x40005C00) +#elif defined STM32F3 +#include +#endif + +// max endpoints number +#define STM32ENDPOINTS 8 +/** + * Buffers size definition + **/ + +// F0 - USB2_16; F1 - USB1_16; F3 - 1/2 depending on series +#if !defined USB1_16 && !defined USB2_16 +#if defined STM32F0 +#define USB2_16 +#elif defined STM32F1 +#define USB1_16 +#else +#error "Can't determine USB1_16 or USB2_16, define by hands" +#endif +#endif + +// BTABLE_SIZE FOR STM32F3: +// In STM32F303/302xB/C, 512 bytes SRAM is not shared with CAN. +// In STM32F302x6/x8 and STM32F30xxD/E, 726 bytes dedicated SRAM and 256 bytes shared SRAM with CAN i.e. +// 1Kbytes dedicated SRAM in case CAN is disabled. +// remember, that USB_BTABLE_SIZE will be divided by ACCESSZ, so don't divide it twice for 32-bit addressing + +#ifdef NOCAN +#if defined STM32F0 +#define USB_BTABLE_SIZE 1024 +#elif defined STM32F3 +#define USB_BTABLE_SIZE 726 +//#warning "Please, check real buffer size due to docs" +#else +#error "define STM32F0 or STM32F3" +#endif +#else // !NOCAN: F0/F3 with CAN or F1 (can't simultaneously run CAN and USB) +#if defined STM32F0 +#define USB_BTABLE_SIZE 768 +#elif defined STM32F3 +#define USB_BTABLE_SIZE 726 +//#warning "Please, check real buffer size due to docs" +#else // STM32F103: 1024 bytes but with 32-bit addressing +#define USB_BTABLE_SIZE 1024 +#endif +#endif // NOCAN + +// first 64 bytes of USB_BTABLE are registers! + +#define USB_BTABLE_BASE 0x40006000 +#define USB ((USB_TypeDef *) USB_BASE) + +#ifdef USB_BTABLE +#undef USB_BTABLE +#endif +#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE)) +#define USB_ISTR_EPID 0x0000000F +#define USB_FNR_LSOF_0 0x00000800 +#define USB_FNR_lSOF_1 0x00001000 +#define USB_LPMCSR_BESL_0 0x00000010 +#define USB_LPMCSR_BESL_1 0x00000020 +#define USB_LPMCSR_BESL_2 0x00000040 +#define USB_LPMCSR_BESL_3 0x00000080 +#define USB_EPnR_CTR_RX 0x00008000 +#define USB_EPnR_DTOG_RX 0x00004000 +#define USB_EPnR_STAT_RX 0x00003000 +#define USB_EPnR_STAT_RX_0 0x00001000 +#define USB_EPnR_STAT_RX_1 0x00002000 +#define USB_EPnR_SETUP 0x00000800 +#define USB_EPnR_EP_TYPE 0x00000600 +#define USB_EPnR_EP_TYPE_0 0x00000200 +#define USB_EPnR_EP_TYPE_1 0x00000400 +#define USB_EPnR_EP_KIND 0x00000100 +#define USB_EPnR_CTR_TX 0x00000080 +#define USB_EPnR_DTOG_TX 0x00000040 +#define USB_EPnR_STAT_TX 0x00000030 +#define USB_EPnR_STAT_TX_0 0x00000010 +#define USB_EPnR_STAT_TX_1 0x00000020 +#define USB_EPnR_EA 0x0000000F +#define USB_COUNTn_RX_BLSIZE 0x00008000 +#define USB_COUNTn_NUM_BLOCK 0x00007C00 +#define USB_COUNTn_RX 0x0000003F + +#define USB_TypeDef USB_TypeDef_custom + +typedef struct { + __IO uint32_t EPnR[STM32ENDPOINTS]; + __IO uint32_t RESERVED[STM32ENDPOINTS]; + __IO uint32_t CNTR; + __IO uint32_t ISTR; + __IO uint32_t FNR; + __IO uint32_t DADDR; + __IO uint32_t BTABLE; +#ifdef STM32F0 + __IO uint32_t LPMCSR; + __IO uint32_t BCDR; +#endif +} USB_TypeDef; + +// F303 D/E have 2x16 access scheme +typedef struct{ +#if defined USB2_16 + __IO uint16_t USB_ADDR_TX; + __IO uint16_t USB_COUNT_TX; + __IO uint16_t USB_ADDR_RX; + __IO uint16_t USB_COUNT_RX; +#define ACCESSZ (1) +#define BUFTYPE uint8_t +#elif defined USB1_16 + __IO uint32_t USB_ADDR_TX; + __IO uint32_t USB_COUNT_TX; + __IO uint32_t USB_ADDR_RX; + __IO uint32_t USB_COUNT_RX; +#define ACCESSZ (2) +#define BUFTYPE uint16_t +#else +#error "Define USB1_16 or USB2_16" +#endif +} USB_EPDATA_TypeDef; + + +typedef struct{ + __IO USB_EPDATA_TypeDef EP[STM32ENDPOINTS]; +} USB_BtableDef; + +#define EP0DATABUF_SIZE (64) +#define LASTADDR_DEFAULT (STM32ENDPOINTS * 8) + +/****************************************************************** + * Defines from usb.h * + *****************************************************************/ + +/* + * Device and/or Interface Class codes + */ +#define USB_CLASS_PER_INTERFACE 0 +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_PTP 6 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_DATA 10 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_VENDOR_SPEC 0xff + +/* + * Descriptor types + */ +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_QUALIFIER 0x06 +#define USB_DT_IAD 0x0B + +#define USB_DT_HID 0x21 +#define USB_DT_REPORT 0x22 +#define USB_DT_PHYSICAL 0x23 +#define USB_DT_CS_INTERFACE 0x24 +#define USB_DT_HUB 0x29 + +/* + * Descriptor sizes per descriptor type + */ +#define USB_DT_DEVICE_SIZE 18 +#define USB_DT_CONFIG_SIZE 9 +#define USB_DT_INTERFACE_SIZE 9 +#define USB_DT_HID_SIZE 9 +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_QUALIFIER_SIZE 10 +#define USB_DT_CS_INTERFACE_SIZE 5 +#define USB_DT_IAD_SIZE 8 + + +// bmRequestType & 0x80 == dev2host (1) or host2dev (0) +// recipient: bmRequestType & 0x1f +#define REQUEST_RECIPIENT(b) (b & 0x1f) +#define REQ_RECIPIENT_DEVICE 0 +#define REQ_RECIPIENT_INTERFACE 1 +#define REQ_RECIPIENT_ENDPOINT 2 +#define REQ_RECIPIENT_OTHER 3 +// type: [bmRequestType & 0x60 >> 5] +#define REQUEST_TYPE(b) ((b&0x60)>>5) +#define REQ_TYPE_STANDARD 0 +#define REQ_TYPE_CLASS 1 +#define REQ_TYPE_VENDOR 2 +#define REQ_TYPE_RESERVED 3 + + +//#define VENDOR_REQUEST 0x01 + +// standard device requests +#define GET_STATUS 0x00 +#define CLEAR_FEATURE 0x01 +#define SET_FEATURE 0x03 +#define SET_ADDRESS 0x05 +#define GET_DESCRIPTOR 0x06 +#define SET_DESCRIPTOR 0x07 +#define GET_CONFIGURATION 0x08 +#define SET_CONFIGURATION 0x09 +// and some standard interface requests +#define GET_INTERFACE 0x0A +#define SET_INTERFACE 0x0B +// and some standard endpoint requests +#define SYNC_FRAME 0x0C + +// Types of descriptors +#define DEVICE_DESCRIPTOR 0x01 +#define CONFIGURATION_DESCRIPTOR 0x02 +#define STRING_DESCRIPTOR 0x03 +#define DEVICE_QUALIFIER_DESCRIPTOR 0x06 +#define DEBUG_DESCRIPTOR 0x0a +#define HID_REPORT_DESCRIPTOR 0x22 + +// EP types for EP_init +#define EP_TYPE_BULK 0x00 +#define EP_TYPE_CONTROL 0x01 +#define EP_TYPE_ISO 0x02 +#define EP_TYPE_INTERRUPT 0x03 + +// EP types for descriptors +#define USB_BM_ATTR_CONTROL 0x00 +#define USB_BM_ATTR_ISO 0x01 +#define USB_BM_ATTR_BULK 0x02 +#define USB_BM_ATTR_INTERRUPT 0x03 + + +/****************************************************************** + * Other stuff * + *****************************************************************/ + +#define RX_FLAG(epstat) (epstat & USB_EPnR_CTR_RX) +#define TX_FLAG(epstat) (epstat & USB_EPnR_CTR_TX) +#define SETUP_FLAG(epstat) (epstat & USB_EPnR_SETUP) + +// EPnR bits manipulation +#define KEEP_DTOG_STAT(EPnR) (EPnR & ~(USB_EPnR_STAT_RX|USB_EPnR_STAT_TX|USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) +#define KEEP_DTOG(EPnR) (EPnR & ~(USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) + +#define LANG_US (uint16_t)0x0409 + +#define _USB_STRING_(name, str) \ +static const struct name \ +{ \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint16_t bString[(sizeof(str) - 2) / 2]; \ + \ +} \ +name = {sizeof(name), 0x03, str} + +#define _USB_LANG_ID_(name, lng_id) \ +static const struct name \ +{ \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint16_t bString; \ + \ +} \ +name = {0x04, 0x03, lng_id} + +// EP0 configuration packet +typedef struct { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} config_pack_t; + +// endpoints state +typedef struct{ + uint16_t *tx_buf; // transmission buffer address + uint16_t txbufsz; // transmission buffer size + uint8_t *rx_buf; // reception buffer address + void (*func)(); // endpoint action function + unsigned rx_cnt : 10; // received data counter +} ep_t; + +extern volatile uint8_t usbON; + +void USB_setup(); +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()); +void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size); +void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size); +int EP_Read(uint8_t number, uint8_t *buf); + +// could be [re]defined in usb_dev.c +extern void usb_class_request(config_pack_t *packet, uint8_t *data, uint16_t datalen); +extern void usb_vendor_request(config_pack_t *packet, uint8_t *data, uint16_t datalen); +extern void set_configuration(); diff --git a/F3:F303/MLX90640test/version.inc b/F3:F303/MLX90640test/version.inc new file mode 100644 index 0000000..a5b5d7a --- /dev/null +++ b/F3:F303/MLX90640test/version.inc @@ -0,0 +1,2 @@ +#define BUILD_NUMBER "10" +#define BUILD_DATE "2025-09-11"