7 Commits

1318 changed files with 2839 additions and 490953 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "resources/Camera_driver/alohal"]
path = resources/Camera_driver/alohal
url = git@github.com:TheColonelYoung/ALOHAL.git

View File

@ -1,5 +0,0 @@
Sun_sensor-backups/
gerbers/
bom/
replicate_layout.log
*.bak

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
{
"board": {
"active_layer": 36,
"active_layer_preset": "",
"auto_track_width": false,
"hidden_nets": [],
"high_contrast_mode": 1,
"net_color_mode": 1,
"opacity": {
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "ff4ffff_ffffffff",
"zone_display_mode": 0
},
"meta": {
"filename": "Sun_sensor.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@ -1,439 +0,0 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.254
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.15,
"min_copper_edge_clearance": 0.19999999999999998,
"min_hole_clearance": 0.19999999999999998,
"min_hole_to_hole": 0.3,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.19999999999999998,
"min_track_width": 0.15,
"min_via_annular_width": 0.125,
"min_via_diameter": 0.44999999999999996,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"use_height_for_length_calcs": true
},
"track_widths": [
0.0,
0.15,
0.25,
0.5,
1.0,
1.5,
2.0
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "Sun_sensor.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.15,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.45,
"microvia_drill": 0.2,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.15,
"via_diameter": 0.45,
"via_drill": 0.2,
"wire_width": 6.0
}
],
"meta": {
"version": 2
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "Sun_sensor.step",
"vrml": ""
},
"page_layout_descr_file": "/home/petr/work/butcube/resources/kicad_page_layout.kicad_wks"
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "/home/petr/work/butcube/resources/kicad_page_layout.kicad_wks",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"b4fcae78-0ce7-4618-9b55-3d67c0b38940",
""
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +0,0 @@
(footprint "Alignment_hole" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 0)
(attr through_hole exclude_from_pos_files exclude_from_bom)
(fp_text reference "REF**" (at 0 -2 unlocked) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp fa4317a5-84bf-4bc5-a76e-39c9dc74322a)
)
(fp_text value "Alignment_hole" (at 0 3.5 unlocked) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 5c6e8499-7ddb-488e-b28a-698103ce6e3c)
)
(fp_text user "${REFERENCE}" (at 0 5 unlocked) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 15e51ca5-9eb7-44d4-880d-ebea60015cd4)
)
(pad "" thru_hole circle (at 0 0) (size 1.8 1.8) (drill 1) (layers *.Cu *.Mask) (tstamp b1f6e753-2943-4966-9a1d-84d501867e27))
)

View File

@ -1,71 +0,0 @@
(footprint "Sun_shiled_stencil" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 0)
(fp_text reference "REF**" (at 0 -7 unlocked) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp d78021b8-874f-44a3-aea0-a07c23ea80e4)
)
(fp_text value "Sun_shiled_stencil" (at 0 6.25 unlocked) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 97b32037-1b7d-4ef2-892d-7396cb521726)
)
(fp_text user "${REFERENCE}" (at 0 7.75 unlocked) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 13a74bb0-d7b5-49ef-b400-62b8dfb89ba4)
)
(fp_line (start 6.825 -11.4) (end 6.825 -6.6) (layer "Dwgs.User") (width 0.1) (tstamp 0e956636-6ecf-40f5-b446-5a28641115e4))
(fp_line (start -19.9 -0.175) (end -15.1 -0.175) (layer "Dwgs.User") (width 0.1) (tstamp 43985166-a138-4b16-8f05-eaa329c21854))
(fp_line (start -6.825 -11.4) (end -7.175 -11.4) (layer "Dwgs.User") (width 0.1) (tstamp 562392bc-7fdc-42fb-acf8-8f876fb4baee))
(fp_line (start -23 -13) (end -23 13) (layer "Dwgs.User") (width 0.1) (tstamp 6093230f-7da9-436b-a565-22d094506fe8))
(fp_line (start 4.25 10) (end -4.25 10) (layer "Dwgs.User") (width 0.1) (tstamp 640cd49d-8be5-4b08-b630-e5f8f8377094))
(fp_line (start -21 15) (end 21 15) (layer "Dwgs.User") (width 0.1) (tstamp 6c0fac88-9a87-4a51-b33d-184c9ee1cbe4))
(fp_line (start -6.25 -0.5) (end -6.25 8) (layer "Dwgs.User") (width 0.1) (tstamp 7126884e-33f6-4742-990f-12a47d411edf))
(fp_line (start -19.9 -0.175) (end -19.9 0.175) (layer "Dwgs.User") (width 0.1) (tstamp 730eedee-9a7c-4f43-8635-69482b5c5018))
(fp_line (start -15.1 -0.175) (end -15.1 0.175) (layer "Dwgs.User") (width 0.1) (tstamp 7f8d4600-f7b7-4961-826b-537479190fec))
(fp_line (start 19.9 -0.175) (end 19.9 0.175) (layer "Dwgs.User") (width 0.1) (tstamp 809ec121-7a00-407b-9216-a6d943033b14))
(fp_line (start 7.175 -11.4) (end 6.825 -11.4) (layer "Dwgs.User") (width 0.1) (tstamp a222aa4e-c344-46b7-bf55-3c6a0aa0a374))
(fp_line (start 7.175 -6.6) (end 6.825 -6.6) (layer "Dwgs.User") (width 0.1) (tstamp a2af30a0-1af5-4580-a31f-0dd5c5ff6734))
(fp_line (start -21 -15) (end 21 -15) (layer "Dwgs.User") (width 0.1) (tstamp aa48cd2b-dfd1-49b6-83ee-da5bce84fcd5))
(fp_line (start 4.25 -2.5) (end -4.25 -2.5) (layer "Dwgs.User") (width 0.1) (tstamp aca2d6e2-fe5d-4a12-a499-e4f77b3547cc))
(fp_line (start 23 -13) (end 23 13) (layer "Dwgs.User") (width 0.1) (tstamp ae18f94e-c1fd-4c12-8c06-ff09a4e6e190))
(fp_line (start 15.1 -0.175) (end 19.9 -0.175) (layer "Dwgs.User") (width 0.1) (tstamp bea27199-2194-4f85-a1b7-c8be78ada6e8))
(fp_line (start 15.1 0.175) (end 19.9 0.175) (layer "Dwgs.User") (width 0.1) (tstamp c9dd16cc-624b-413b-a0b9-6f812f8a3f7d))
(fp_line (start 7.175 -11.4) (end 7.175 -6.6) (layer "Dwgs.User") (width 0.1) (tstamp d71880c6-495a-4f68-ae0e-ff186b05c077))
(fp_line (start 15.1 -0.175) (end 15.1 0.175) (layer "Dwgs.User") (width 0.1) (tstamp e7b98613-f8b3-4a0f-a012-c3972828c1f8))
(fp_line (start -19.9 0.175) (end -15.1 0.175) (layer "Dwgs.User") (width 0.1) (tstamp ebde6eb6-c376-45f3-8cf1-68b9dd545362))
(fp_line (start -7.175 -11.4) (end -7.175 -6.6) (layer "Dwgs.User") (width 0.1) (tstamp f8a2ccf5-c0e1-49c1-a842-399a9e338537))
(fp_line (start 6.25 -0.5) (end 6.25 8) (layer "Dwgs.User") (width 0.1) (tstamp fce5c3c5-c70c-4ae2-bcfa-1f6bf6b5df83))
(fp_line (start -6.825 -6.6) (end -7.175 -6.6) (layer "Dwgs.User") (width 0.1) (tstamp fe4338d1-8013-48f5-8247-78ece50c7ade))
(fp_line (start -6.825 -11.4) (end -6.825 -6.6) (layer "Dwgs.User") (width 0.1) (tstamp fedfbe41-eacd-4c64-8365-aaee91c517dc))
(fp_arc (start 6.25 8) (mid 5.664214 9.414214) (end 4.25 10) (layer "Dwgs.User") (width 0.1) (tstamp 02f7b83b-69e5-402a-97cd-2ab9ae004365))
(fp_arc (start -21 15) (mid -22.414214 14.414214) (end -23 13) (layer "Dwgs.User") (width 0.1) (tstamp 139f406e-f1be-4460-bd37-ea8577c4c405))
(fp_arc (start 21 -15) (mid 22.414214 -14.414214) (end 23 -13) (layer "Dwgs.User") (width 0.1) (tstamp 1f015c40-87c5-446d-9682-a71c8c78a240))
(fp_arc (start -4.25 10) (mid -5.664214 9.414214) (end -6.25 8) (layer "Dwgs.User") (width 0.1) (tstamp 40bed328-bcff-4a79-862f-05ffa9f0851e))
(fp_arc (start 4.25 -2.5) (mid 5.664214 -1.914214) (end 6.25 -0.5) (layer "Dwgs.User") (width 0.1) (tstamp 413987a6-e7ff-431f-a102-4d44d813b7bf))
(fp_arc (start -23 -13) (mid -22.414214 -14.414214) (end -21 -15) (layer "Dwgs.User") (width 0.1) (tstamp 4d123677-82ba-40d7-b06e-329a209c99e5))
(fp_arc (start -6.25 -0.5) (mid -5.664214 -1.914214) (end -4.25 -2.5) (layer "Dwgs.User") (width 0.1) (tstamp ed372a68-ac06-4910-b679-3abb459c4053))
(fp_arc (start 23 13) (mid 22.414214 14.414214) (end 21 15) (layer "Dwgs.User") (width 0.1) (tstamp f397ea00-77b3-4e52-8c1f-f40fbefb4c5a))
(fp_circle (center 19.5 -11.5) (end 21.25 -11.5) (layer "Dwgs.User") (width 0.1) (fill none) (tstamp 44be3ae8-2900-4186-bdf3-aa0df1b60494))
(fp_circle (center -19.5 -11.5) (end -17.75 -11.5) (layer "Dwgs.User") (width 0.1) (fill none) (tstamp 69d5781c-ea7a-40e7-b059-5c794936e027))
(fp_circle (center 19.5 11.5) (end 21.25 11.5) (layer "Dwgs.User") (width 0.1) (fill none) (tstamp e2e72bf3-dc42-417c-ad1e-89b7265ae9a4))
(fp_circle (center -19.5 11.5) (end -17.75 11.5) (layer "Dwgs.User") (width 0.1) (fill none) (tstamp f8dcb164-b515-4358-89d4-593010f27b67))
(fp_rect (start -7.175 -11.4) (end -6.825 -6.6) (layer "User.2") (width 0.01) (fill solid) (tstamp 15cec376-0cc5-4fb9-9546-200acbadd4c3))
(fp_rect (start 6.825 -11.4) (end 7.175 -6.6) (layer "User.2") (width 0.01) (fill solid) (tstamp 2b145196-0d0e-4b3a-a10d-f603e04431b2))
(fp_rect (start 15.1 0.175) (end 19.9 -0.175) (layer "User.2") (width 0.01) (fill solid) (tstamp 65179cb2-be1e-4398-a5c0-b1ccfeb04f75))
(fp_rect (start -4.25 -2.5) (end 4.25 10) (layer "User.2") (width 0.01) (fill solid) (tstamp 7a34eea2-a6e8-4a3b-96ce-95ae0942333a))
(fp_rect (start -19.9 0.175) (end -15.1 -0.175) (layer "User.2") (width 0.01) (fill solid) (tstamp 94f3ef5d-a92b-4037-9ba0-96a63bb9f2cf))
(fp_rect (start -6.25 -0.5) (end 6.25 8) (layer "User.2") (width 0.01) (fill solid) (tstamp 97e33b51-4c2e-434b-811f-517d98fdabf8))
(fp_circle (center 19.5 11.5) (end 21.25 11.5) (layer "User.2") (width 0.01) (fill solid) (tstamp 02ebc153-06e5-42e5-ae0e-95cf53d2686e))
(fp_circle (center -19.5 -11.5) (end -17.75 -11.5) (layer "User.2") (width 0.01) (fill solid) (tstamp 1d2e485c-13d9-491b-b9b1-d7cdb1ddacd4))
(fp_circle (center 19.5 -11.5) (end 21.25 -11.5) (layer "User.2") (width 0.01) (fill solid) (tstamp 4f064766-fcbe-42b2-9cf1-e3ce1c52823d))
(fp_circle (center 4.25 8) (end 6.25 8) (layer "User.2") (width 0.01) (fill solid) (tstamp b2368e7f-0f40-4282-af0f-69e4749fe499))
(fp_circle (center -19.5 11.5) (end -17.75 11.5) (layer "User.2") (width 0.01) (fill solid) (tstamp b4e0236b-b4d5-4fe0-a283-ecee8bcceaba))
(fp_circle (center 4.25 -0.5) (end 6.25 -0.5) (layer "User.2") (width 0.01) (fill solid) (tstamp b5fb8139-8b3b-4c94-9ad9-eb356c47c480))
(fp_circle (center -4.25 8.000001) (end -2.25 8.000001) (layer "User.2") (width 0.01) (fill solid) (tstamp c8e2cfaa-51bd-4851-a6ce-1afe5d99229f))
(fp_circle (center -4.25 -0.5) (end -2.25 -0.5) (layer "User.2") (width 0.01) (fill solid) (tstamp f2088203-ec06-4532-9ae1-2f2a4395cba9))
(model "/home/petr/work/butcube/modules/Sun_sensor/Stencil.step"
(offset (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
(fp_lib_table
(lib (name "Sun_shield")(type "KiCad")(uri "${KIPRJMOD}/Sun_shield.pretty")(options "")(descr ""))
)

View File

@ -1 +0,0 @@
build/

File diff suppressed because one or more lines are too long

View File

@ -1,19 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"cwd": "${workspaceRoot}",
"executable": "${workspaceRoot}/build/Sun_sensor.elf",
"name": "GDB + OpenOCD",
"device": "STM32L432",
"configFiles": [
"interface/stlink.cfg",
"target/stm32l4x.cfg"
]
}
]
}

View File

@ -1,78 +0,0 @@
#include "MLX75306.hpp"
MLX75306::MLX75306(SPI_HandleTypeDef SPI_handle, Chip_select_pin SPI_CS) :
SPI_handle(SPI_handle), SPI_CS(SPI_CS){ }
void MLX75306::Init(){
Reset();
}
void MLX75306::Reset(){
Command(Commands::Chip_reset, { 0, 0 });
}
void MLX75306::Wake_up(){
Command(Commands::Wake_up, { 0, 0 });
}
void MLX75306::Zebra_pattern_1(){
Command(Commands::Test_zebra_pattern_1, { 0, 0 });
}
array<uint8_t, 159> MLX75306::Read_all_8bit(){
// Command is set to read all pixels
return Command<159>(Commands::Read_out_8b, { 0x02, 0x8f });
}
void MLX75306::Integrate(double time_us){
const unsigned int f_RCO = 10000000;
const double min_time_us = 0.1;
const double max_time_us = 100000;
int64_t integration_register = 0;
// Cap values
if (time_us < min_time_us) {
time_us = min_time_us;
}
if (time_us > max_time_us) {
time_us = max_time_us;
}
// Calculate value for short integration
integration_register = ((time_us / 1000000) * f_RCO) + 4;
// If integration time is longer then maximal short integration time used long integration command
if (integration_register > ((1 << 16) - (11 * 16))) {
integration_register = (((time_us / 1000000) * f_RCO) - 11) / 16;
// Handle overflow and underflow of integration register
if (integration_register > (1 << 16)) {
integration_register = (1 << 16) - 1;
} else if (integration_register < 0) {
integration_register = 1;
}
// Long integration
Command(Commands::Start_integration_long,
{
static_cast<uint8_t>((integration_register & 0xff00) >> 8),
static_cast<uint8_t>(integration_register & 0xff)
}
);
} else {
// Short integration
Command(Commands::Start_integration,
{
static_cast<uint8_t>((integration_register & 0xff00) >> 8),
static_cast<uint8_t>(integration_register & 0xff)
}
);
}
} // MLX75306::Integrate
MLX75306::Status_byte MLX75306::Status(){
array<uint8_t, 2> payload = { 0, 0 };
auto status = Command(Commands::Idle, payload)[0];
Status_byte status_struct = *((Status_byte *) &(status));
return status_struct;
}

View File

@ -1,186 +0,0 @@
/**
* @file SPI_camera.hpp
* @author Petr Malaník (TheColonelYoung(at)gmail(dot)com)
* @brief
* @version 0.1
* @date 1.03.2023
*/
#pragma once
#include "stm32l4xx_hal.h"
#include <array>
using namespace std;
typedef unsigned int uint;
/**
* @brief Linear optical sensor array, including a 142 x 1 array of photodiodes
* associated charge amplifier circuitry and a pixel data-hold function that
* provides simultaneous integration start and stop times for all pixels.
*/
class MLX75306
{
public:
/**
* @brief Describes GPIO which serves as SPI chip select pin
*/
struct Chip_select_pin {
GPIO_TypeDef *port;
uint16_t pin;
};
/**
* @brief Command for MLX75306, whole command composes of 3 bytes, first byte is from enum below
* Other two bytes are payload which could be command specific or empty
*/
enum class Commands: uint8_t {
Idle = 0b00000000,
Chip_reset = 0b11110000,
Read_thresholds = 0b11011000,
Write_thresholds = 0b11001100,
Start_integration = 0b10111000,
Start_integration_long = 0b10110100,
Read_out_1b = 0b10011100,
Read_out_1b5 = 0b10010110,
Read_out_4b = 0b10010011,
Read_out_8b = 0b10011001,
Test_zebra_pattern_1 = 0b11101000,
Test_zebra_pattern_2 = 0b11100100,
Test_zebra_pattern_12 = 0b11100010,
Test_zebra_pattern_0 = 0b11100001,
Sleep_mode = 0b11000110,
Wake_up = 0b11000011,
};
/**
* @brief Structure of MLX75306 status byte
*/
struct __attribute__((packed)) __attribute__((__may_alias__)) Status_byte{
uint8_t command_counter : 5; // Counter of valid commands
uint8_t device_mode : 1; // Device mode: 0-Test 1-User
uint8_t power_up_in_progress : 1; // Set after first Chip_reset command, clear after power-up
uint8_t operational_mode : 1; // Device operational mode: 0-Sleep 1-Normal
};
protected:
/*
* @brief HAL handle of SPI to which is ArduChip connected
*/
SPI_HandleTypeDef SPI_handle;
/**
* @brief GPIO description which serves as SPI Chip select
*/
Chip_select_pin SPI_CS;
public:
/**
* @brief Construct a new MLX75306 object
*
* @param SPI_handle HAL handle of SPI to which is sensor connected
* @param SPI_CS GPIO description which serves as SPI Chip select
*/
MLX75306(SPI_HandleTypeDef SPI_handle, Chip_select_pin SPI_CS);
/**
* @brief Initialize sensor by reset
*/
void Init();
/**
* @brief Reset sensor, reset must be done after power-up, reset all registers
*/
void Reset();
/**
* @brief Change operational mode of sensor to Normal
* During normal mode an integration and readout could be performed.
*/
void Wake_up();
/**
* @brief Change operational mode of sensor to Sleep
* During sleep mode an integration and readout could not be performed.
* But power draw of sensor is reduced.
*/
void Sleep_mode();
/**
* @brief Sensor will charge photodiodes to defined levels to create test pattern
* Every odd pixel is charged to high level of charge, even pixel to low level of charge
* This command is used instead of Integration start
*/
void Zebra_pattern_1();
/**
* @brief Time in micro second to integrate charge photodiodes
* The shortest time is 0.1 us, the longest is 100 ms, values above or below are capped
*/
void Integrate(double time_us);
/**
* @brief Reads Status byte of sensor by using Idle command
*
* @return Status_byte Structured status byte of sensor
*/
Status_byte Status();
/**
* @brief Perform readout of all output registers and pixels from sensor
*
* @return array<uint8_t, 159> Output registers of sensor containing metadata and pixels
*/
array<uint8_t, 159> Read_all_8bit();
protected:
/**
* @brief Send command to sensor and return answer (mostly status byte and empty bytes)
*
* @tparam array_size Size of returned answer on bytes, default is 3
* @param command Command from available Commands of sensor
* @param payload Payload (parameters) of command, mostly empty but could contain integration time, atc.
* @return array<uint8_t, array_size> Answer to command, example: status byte, readout bytes, etc.
*/
template <size_t array_size = 3>
array<uint8_t, array_size> Command(Commands command, array<uint8_t, 2> payload){
array<uint8_t, array_size> byte_stream = { 0 };
byte_stream[0] = (uint8_t) command;
byte_stream[1] = payload[0];
byte_stream[2] = payload[1];
return Transmit_and_receive(byte_stream);
}
/**
* @brief Transmit bytes to sensor and receive answer
*
* @tparam array_size Amount of bytes to transfer and receive
* @param byte_stream Array of bytes to transmit
* @return array<uint8_t, array_size> Array of received bytes
*/
template <size_t array_size>
array<uint8_t, array_size> Transmit_and_receive(array<uint8_t, array_size> &byte_stream){
array<uint8_t, array_size> received = { 0 };
CS_enable();
HAL_SPI_TransmitReceive(&SPI_handle, byte_stream.data(), received.data(), byte_stream.size(), byte_stream.size());
CS_disable();
return received;
}
/**
* @brief Enables communication with sensor via SPI, CS signal is active low
*/
void CS_enable(){ HAL_GPIO_WritePin(SPI_CS.port, SPI_CS.pin, GPIO_PIN_RESET); };
/**
* @brief Disables communication with sensor via SPI, CS signal is active low
*/
void CS_disable(){ HAL_GPIO_WritePin(SPI_CS.port, SPI_CS.pin, GPIO_PIN_SET); };
};

View File

@ -1,410 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "MLX75306.hpp"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan1;
SPI_HandleTypeDef hspi1;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN1_Init(void);
static void MX_SPI1_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void UART_print(string message){
message += "\r\n";
HAL_UART_Transmit(&huart2, (const uint8_t *) message.c_str(), message.length(), message.length());
}
void Print_status(MLX75306::Status_byte status){
UART_print("MLX75306 Status:");
string op_mode = status.operational_mode ? "Normal" : "Sleep";
UART_print("Operational Mode: " + op_mode);
string power_up_state = status.power_up_in_progress ? "Done" : "In progress";
UART_print("Power up: " + power_up_state);
string device_mode = status.device_mode ? "User" : "Test";
UART_print("Device mode: " + device_mode);
UART_print("Command counter " + to_string(status.command_counter));
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void){
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CAN1_Init();
MX_SPI1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
UART_print("\r\nBUTCube Sun Sensor module is ready ...\r\n");
auto sensor = new MLX75306(hspi1, MLX75306::Chip_select_pin{ GPIOA, GPIO_PIN_4 });
sensor->Init();
sensor->Wake_up();
sensor->Zebra_pattern_1();
HAL_Delay(10);
Print_status(sensor->Status());
auto readout = sensor->Read_all_8bit();
UART_print("\r\nBytes of zebra pattern 1:");
for (auto &byte:readout) {
UART_print(to_string(byte));
}
sensor->Integrate(1000);
HAL_Delay(50);
readout = sensor->Read_all_8bit();
UART_print("\r\nBytes of integrated image:");
for (auto &byte:readout) {
UART_print(to_string(byte));
}
UART_print(""); // EOL
Print_status(sensor->Status());
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_WritePin(GPIOB, LED2_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, LED1_Pin, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOB, LED2_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, LED1_Pin, GPIO_PIN_RESET);
HAL_Delay(100);
}
/* USER CODE END 3 */
} // main
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void){
RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 };
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 10;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
Error_Handler();
}
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) {
Error_Handler();
}
} // SystemClock_Config
/**
* @brief CAN1 Initialization Function
* @param None
* @retval None
*/
static void MX_CAN1_Init(void){
/* USER CODE BEGIN CAN1_Init 0 */
/* USER CODE END CAN1_Init 0 */
/* USER CODE BEGIN CAN1_Init 1 */
/* USER CODE END CAN1_Init 1 */
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 32;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_1TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN CAN1_Init 2 */
/* USER CODE END CAN1_Init 2 */
}
/**
* @brief SPI1 Initialization Function
* @param None
* @retval None
*/
static void MX_SPI1_Init(void){
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
/**
* @brief USART2 Initialization Function
* @param None
* @retval None
*/
static void MX_USART2_UART_Init(void){
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void){
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, CS__1_Pin | CS__2_Pin | CAN_RS_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, FRAM_CS_Pin | LED2_Pin | LED1_Pin | CS__3_Pin
| CS__4_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : FR_RDY__1_Pin FR_RDY__2_Pin */
GPIO_InitStruct.Pin = FR_RDY__1_Pin | FR_RDY__2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : CS__1_Pin */
GPIO_InitStruct.Pin = CS__1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(CS__1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : FRAM_CS_Pin LED2_Pin LED1_Pin CS__3_Pin
CS__4_Pin */
GPIO_InitStruct.Pin = FRAM_CS_Pin | LED2_Pin | LED1_Pin | CS__3_Pin
| CS__4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : CS__2_Pin CAN_RS_Pin */
GPIO_InitStruct.Pin = CS__2_Pin | CAN_RS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : FR_RDY__3_Pin */
GPIO_InitStruct.Pin = FR_RDY__3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(FR_RDY__3_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : FR_RDY__4_Pin */
GPIO_InitStruct.Pin = FR_RDY__4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(FR_RDY__4_GPIO_Port, &GPIO_InitStruct);
} // MX_GPIO_Init
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void){
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1) { }
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line){
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,281 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32l4xx_hal_msp.c
* @brief This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
/* USER CODE END Define */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */
/* USER CODE END Macro */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */
/* USER CODE END ExternalFunctions */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
/* System interrupt init*/
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
/**
* @brief CAN MSP Initialization
* This function configures the hardware resources used in this example
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hcan->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspInit 0 */
/* USER CODE END CAN1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**CAN1 GPIO Configuration
PA11 ------> CAN1_RX
PA12 ------> CAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN CAN1_MspInit 1 */
/* USER CODE END CAN1_MspInit 1 */
}
}
/**
* @brief CAN MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan)
{
if(hcan->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspDeInit 0 */
/* USER CODE END CAN1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_CAN1_CLK_DISABLE();
/**CAN1 GPIO Configuration
PA11 ------> CAN1_RX
PA12 ------> CAN1_TX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);
/* USER CODE BEGIN CAN1_MspDeInit 1 */
/* USER CODE END CAN1_MspDeInit 1 */
}
}
/**
* @brief SPI MSP Initialization
* This function configures the hardware resources used in this example
* @param hspi: SPI handle pointer
* @retval None
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
/**
* @brief SPI MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hspi: SPI handle pointer
* @retval None
*/
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
{
if(hspi->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspDeInit 0 */
/* USER CODE END SPI1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI1_CLK_DISABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
/* USER CODE BEGIN SPI1_MspDeInit 1 */
/* USER CODE END SPI1_MspDeInit 1 */
}
}
/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART2_MspInit 1 */
/* USER CODE END USART2_MspInit 1 */
}
}
/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
if(huart->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspDeInit 0 */
/* USER CODE END USART2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
/* USER CODE BEGIN USART2_MspDeInit 1 */
/* USER CODE END USART2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,232 +0,0 @@
#MicroXplorer Configuration settings - do not modify
CAD.formats=
CAD.pinconfig=
CAD.provider=
CAN1.BS1=CAN_BS1_1TQ
CAN1.CalculateBaudRate=833333
CAN1.CalculateTimeBit=1200
CAN1.CalculateTimeQuantum=400.0
CAN1.IPParameters=CalculateTimeQuantum,BS1,CalculateTimeBit,CalculateBaudRate,Prescaler
CAN1.Prescaler=32
File.Version=6
GPIO.groupedBy=Group By Peripherals
KeepUserPlacement=false
Mcu.CPN=STM32L432KCU3
Mcu.Family=STM32L4
Mcu.IP0=CAN1
Mcu.IP1=NVIC
Mcu.IP2=RCC
Mcu.IP3=SPI1
Mcu.IP4=SYS
Mcu.IP5=USART2
Mcu.IPNb=6
Mcu.Name=STM32L432K(B-C)Ux
Mcu.Package=UFQFPN32
Mcu.Pin0=PC14-OSC32_IN (PC14)
Mcu.Pin1=PA0
Mcu.Pin10=PA9
Mcu.Pin11=PA10
Mcu.Pin12=PA11
Mcu.Pin13=PA12
Mcu.Pin14=PA13 (JTMS-SWDIO)
Mcu.Pin15=PA14 (JTCK-SWCLK)
Mcu.Pin16=PA15 (JTDI)
Mcu.Pin17=PB3 (JTDO-TRACESWO)
Mcu.Pin18=PB4 (NJTRST)
Mcu.Pin19=PB5
Mcu.Pin2=PA1
Mcu.Pin20=PB6
Mcu.Pin21=PB7
Mcu.Pin22=PH3-BOOT0
Mcu.Pin23=VP_SYS_VS_Systick
Mcu.Pin3=PA2
Mcu.Pin4=PA3
Mcu.Pin5=PA4
Mcu.Pin6=PA5
Mcu.Pin7=PA6
Mcu.Pin8=PA7
Mcu.Pin9=PB1
Mcu.PinsNb=24
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32L432KCUx
MxCube.Version=6.2.1
MxDb.Version=DB.6.0.21
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA0.GPIOParameters=GPIO_Label
PA0.GPIO_Label=RCC_HSE
PA0.Mode=HSE-External-Clock-Source-for-LittleOrca
PA0.Signal=RCC_CK_IN
PA1.GPIOParameters=GPIO_Label
PA1.GPIO_Label=FR_RDY_\#1
PA1.Locked=true
PA1.Signal=GPIO_Input
PA10.GPIOParameters=GPIO_Label
PA10.GPIO_Label=CS_\#2
PA10.Locked=true
PA10.Signal=GPIO_Output
PA11.Mode=CAN_Activate
PA11.Signal=CAN1_RX
PA12.Mode=CAN_Activate
PA12.Signal=CAN1_TX
PA13\ (JTMS-SWDIO).Mode=Serial_Wire
PA13\ (JTMS-SWDIO).Signal=SYS_JTMS-SWDIO
PA14\ (JTCK-SWCLK).Mode=Serial_Wire
PA14\ (JTCK-SWCLK).Signal=SYS_JTCK-SWCLK
PA15\ (JTDI).GPIOParameters=GPIO_Label
PA15\ (JTDI).GPIO_Label=CAN_RS
PA15\ (JTDI).Locked=true
PA15\ (JTDI).Signal=GPIO_Output
PA2.Mode=Asynchronous
PA2.Signal=USART2_TX
PA3.Mode=Asynchronous
PA3.Signal=USART2_RX
PA4.GPIOParameters=GPIO_PuPd,GPIO_Label
PA4.GPIO_Label=CS_\#1
PA4.GPIO_PuPd=GPIO_PULLUP
PA4.Locked=true
PA4.Signal=GPIO_Output
PA5.GPIOParameters=GPIO_PuPd
PA5.GPIO_PuPd=GPIO_NOPULL
PA5.Locked=true
PA5.Mode=Full_Duplex_Master
PA5.Signal=SPI1_SCK
PA6.GPIOParameters=GPIO_PuPd
PA6.GPIO_PuPd=GPIO_NOPULL
PA6.Mode=Full_Duplex_Master
PA6.Signal=SPI1_MISO
PA7.GPIOParameters=GPIO_PuPd
PA7.GPIO_PuPd=GPIO_NOPULL
PA7.Mode=Full_Duplex_Master
PA7.Signal=SPI1_MOSI
PA9.GPIOParameters=GPIO_Label
PA9.GPIO_Label=FR_RDY_\#2
PA9.Locked=true
PA9.Signal=GPIO_Input
PB1.GPIOParameters=GPIO_Label
PB1.GPIO_Label=FRAM_CS
PB1.Locked=true
PB1.Signal=GPIO_Output
PB3\ (JTDO-TRACESWO).GPIOParameters=GPIO_Label
PB3\ (JTDO-TRACESWO).GPIO_Label=LED2
PB3\ (JTDO-TRACESWO).Locked=true
PB3\ (JTDO-TRACESWO).Signal=GPIO_Output
PB4\ (NJTRST).GPIOParameters=GPIO_Label
PB4\ (NJTRST).GPIO_Label=LED1
PB4\ (NJTRST).Locked=true
PB4\ (NJTRST).Signal=GPIO_Output
PB5.GPIOParameters=GPIO_Label
PB5.GPIO_Label=CS_\#3
PB5.Locked=true
PB5.Signal=GPIO_Output
PB6.GPIOParameters=GPIO_Label
PB6.GPIO_Label=FR_RDY_\#3
PB6.Locked=true
PB6.Signal=GPIO_Input
PB7.GPIOParameters=GPIO_Label
PB7.GPIO_Label=CS_\#4
PB7.Locked=true
PB7.Signal=GPIO_Output
PC14-OSC32_IN\ (PC14).Mode=LSE-External-Clock-Source
PC14-OSC32_IN\ (PC14).Signal=RCC_OSC32_IN
PH3-BOOT0.GPIOParameters=GPIO_Label
PH3-BOOT0.GPIO_Label=FR_RDY_\#4
PH3-BOOT0.Locked=true
PH3-BOOT0.Signal=GPIO_Input
PinOutPanel.RotationAngle=0
ProjectManager.AskForMigrate=true
ProjectManager.BackupPrevious=false
ProjectManager.CompilerOptimize=6
ProjectManager.ComputerToolchain=false
ProjectManager.CoupleFile=false
ProjectManager.CustomerFirmwarePackage=
ProjectManager.DefaultFWLocation=true
ProjectManager.DeletePrevious=true
ProjectManager.DeviceId=STM32L432KCUx
ProjectManager.FirmwarePackage=STM32Cube FW_L4 V1.17.2
ProjectManager.FreePins=false
ProjectManager.HalAssertFull=false
ProjectManager.HeapSize=0x200
ProjectManager.KeepUserCode=true
ProjectManager.LastFirmware=true
ProjectManager.LibraryCopy=0
ProjectManager.MainLocation=Src
ProjectManager.NoMain=false
ProjectManager.PreviousToolchain=
ProjectManager.ProjectBuild=false
ProjectManager.ProjectFileName=Sun_sensor.ioc
ProjectManager.ProjectName=Sun_sensor
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=Makefile
ProjectManager.ToolChainLocation=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_CAN1_Init-CAN1-false-HAL-true,4-MX_SPI1_Init-SPI1-false-HAL-true,5-MX_USART2_UART_Init-USART2-false-HAL-true
RCC.ADCFreq_Value=64000000
RCC.AHBFreq_Value=80000000
RCC.APB1Freq_Value=80000000
RCC.APB1TimFreq_Value=80000000
RCC.APB2Freq_Value=80000000
RCC.APB2TimFreq_Value=80000000
RCC.CortexFreq_Value=80000000
RCC.FCLKCortexFreq_Value=80000000
RCC.FamilyName=M
RCC.HCLKFreq_Value=80000000
RCC.HSE_VALUE=8000000
RCC.HSI48_VALUE=48000000
RCC.HSI_VALUE=16000000
RCC.I2C1Freq_Value=80000000
RCC.I2C3Freq_Value=80000000
RCC.IPParameters=ADCFreq_Value,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI48_VALUE,HSI_VALUE,I2C1Freq_Value,I2C3Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSE_VALUE,LSI_VALUE,MCO1PinFreq_Value,MSI_VALUE,PLLN,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSourceVirtual,PWRFreq_Value,RNGFreq_Value,SAI1Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USART1Freq_Value,USART2Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value
RCC.LPTIM1Freq_Value=80000000
RCC.LPTIM2Freq_Value=80000000
RCC.LPUART1Freq_Value=80000000
RCC.LSCOPinFreq_Value=32000
RCC.LSE_VALUE=32768
RCC.LSI_VALUE=32000
RCC.MCO1PinFreq_Value=80000000
RCC.MSI_VALUE=4000000
RCC.PLLN=10
RCC.PLLPoutputFreq_Value=22857142.85714286
RCC.PLLQoutputFreq_Value=80000000
RCC.PLLRCLKFreq_Value=80000000
RCC.PLLSAI1PoutputFreq_Value=18285714.285714287
RCC.PLLSAI1QoutputFreq_Value=64000000
RCC.PLLSAI1RoutputFreq_Value=64000000
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSI
RCC.PWRFreq_Value=80000000
RCC.RNGFreq_Value=64000000
RCC.SAI1Freq_Value=18285714.285714287
RCC.SWPMI1Freq_Value=80000000
RCC.SYSCLKFreq_VALUE=80000000
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
RCC.USART1Freq_Value=80000000
RCC.USART2Freq_Value=80000000
RCC.USBFreq_Value=64000000
RCC.VCOInputFreq_Value=16000000
RCC.VCOOutputFreq_Value=160000000
RCC.VCOSAI1OutputFreq_Value=128000000
SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256
SPI1.CLKPhase=SPI_PHASE_2EDGE
SPI1.CLKPolarity=SPI_POLARITY_HIGH
SPI1.CalculateBaudRate=312.5 KBits/s
SPI1.DataSize=SPI_DATASIZE_8BIT
SPI1.Direction=SPI_DIRECTION_2LINES
SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler,DataSize,CLKPolarity,CLKPhase
SPI1.Mode=SPI_MODE_MASTER
SPI1.VirtualType=VM_MASTER
USART2.IPParameters=VirtualMode-Asynchronous
USART2.VirtualMode-Asynchronous=VM_ASYNC
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
board=custom

1
resources/Camera_driver/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,18 @@
#include "butcube_imager.hpp"
int ButCube_imager::Transmit(vector<uint8_t> source){
for( auto &uart_output : uart_output_interfaces){
HAL_UART_Transmit(&uart_output, source.data(), source.size(), HAL_MAX_DELAY);
HAL_Delay(200);
}
return uart_output_interfaces.size() * source.size();
}
int ButCube_imager::Add_output(UART_HandleTypeDef uart_output){
uart_output_interfaces.emplace_back(uart_output);
return uart_output_interfaces.size();
}
void ButCube_imager::Camera_power(bool state){
HAL_GPIO_WritePin(GPIOA, CAMERA_EN_Pin, (GPIO_PinState)!state);
}

View File

@ -0,0 +1,59 @@
/**
* @file OV2640.hpp
* @author Petr Malaník (TheColonelYoung(at)gmail(dot)com)
* @brief
* @version 0.1
* @date 11.09.2022
*/
#pragma once
#include "stm32l4xx_hal.h"
#include "main.h"
#include <vector>
using namespace std;
typedef unsigned int uint;
/**
* @brief Captures image data from camera, control power to camera and transmit data on selected interfaces
* Currently is only UART interface supported
*/
class ButCube_imager
{
private:
/**
* @brief UART interfaces to which data will be exported, interfaces muse be configured in advance
*/
vector<UART_HandleTypeDef> uart_output_interfaces;
public:
/**
* @brief Construct a new ButCube_imager object
*/
ButCube_imager() = default;
/**
* @brief Add UART output to list on which data are exported
*
* @param uart_output UART output to which export data from camera
* @return int
*/
int Add_output(UART_HandleTypeDef uart_output);
/**
* @brief Transmit data from source to selected interfaces
*
* @param source Source of image data
* @return int Count of bytes exported
*/
int Transmit(vector<uint8_t> source);
/**
* @brief Enable or power to camera, controls load switch on camera power rail
*
* @param state true = Enabled, false = Disabled
*/
void Camera_power(bool state);
};

View File

@ -0,0 +1,54 @@
#include "OV2640.hpp"
void OV2640::Init(){
Sensor_write_register((uint8_t) 0xff, 0x01);
Sensor_write_register((uint8_t) 0x12, 0x80);
Sensor_write_register_bulk(OV2640_JPEG_INIT);
Sensor_write_register_bulk(OV2640_YUV422);
Sensor_write_register_bulk(OV2640_JPEG);
Sensor_write_register((uint8_t) 0xff, 0x01);
Sensor_write_register((uint8_t) 0x15, 0x00);
}
void OV2640::Init(const vector<Register_blob_8> &regs){
Init();
Sensor_write_register_bulk(regs);
// Setup camera, H-sync: High, V-sync:high, Sensor_delay: no Delay, FIFO_mode:FIFO enabled, power_mode:Low_power
ArduChip_write(0x03, 0b01010000);
}
void OV2640::Capture(){
ArduChip_write(0x04, 0x01); // Clear FIFO
ArduChip_write(0x04, 0x01);
HAL_Delay(1);
ArduChip_write(0x04, 0x02); // Start capture
HAL_Delay(1);
// wait for capture done
while (1) {
uint8_t regValue = ArduChip_read(0x41);
uint8_t captureDoneMask = 0x8;
if (regValue & captureDoneMask) break;
}
HAL_Delay(1);
uint32_t image_size = ArduChip_FIFO_length();
image_data.resize(image_size);
ArduChip_start_DMA_transfer(image_size);
// while(SPI_handle.State != HAL_SPI_STATE_READY){;}
HAL_Delay(500); // delay to ensure full dma transmission
ArduChip_CS_disable();
} // OV2640::Capture

View File

@ -0,0 +1,54 @@
/**
* @file OV2640.hpp
* @author Petr Malaník (TheColonelYoung(at)gmail(dot)com)
* @brief
* @version 0.1
* @date 11.09.2022
*/
#pragma once
#include "SPI_camera.hpp"
#include "OV2640_regs.hpp"
using namespace std;
typedef unsigned int uint;
/**
* @brief 2MP SPI based camera capable of JPEG compression, based on ArduChip
*/
class OV2640: protected SPI_camera
{
private:
/**
* @brief Initialize camera sensor for JPEG capture, without resolution settings
*/
void Init() override final;
public:
/**
* @brief Inherit constructor from parent class SPI_camera
*/
using SPI_camera::SPI_camera;
/**
* @brief Initialize camera sensor for JPEG capture
*
* @param regs Requested resolution of camera
*/
void Init(const vector<Register_blob_8> &regs);
/**
* @brief Initializes capture of image, waits for capture, transmit image into MCU memory
*/
void Capture() override final;
/**
* @brief Return pointer to last captured image data
*
* @return vector<uint8_t> Pointer to last captured image data
*/
vector<uint8_t> Image_data(){ return image_data; };
};

View File

@ -0,0 +1 @@
#include "OV2640_regs.hpp"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
#include "SPI_camera.hpp"
SPI_camera::SPI_camera(I2C_HandleTypeDef I2C_handle, uint8_t I2C_address, SPI_HandleTypeDef SPI_handle, Chip_select_pin SPI_CS) : I2C_handle(I2C_handle), I2C_address(
I2C_address), SPI_handle(SPI_handle), SPI_CS(SPI_CS){ }
int SPI_camera::Sensor_write_register(uint8_t address, uint8_t data){
return Sensor_write_register(Register_blob_8{ address, data });
}
int SPI_camera::Sensor_write_register(uint16_t address, uint8_t data){
return Sensor_write_register(Register_blob_16{ address, data });
}
int SPI_camera::Sensor_write_register(Register_blob_8 reg){
HAL_StatusTypeDef ret;
uint8_t buf[2];
buf[0] = reg.address;
buf[1] = reg.data;
ret = HAL_I2C_Master_Transmit(&I2C_handle, I2C_address, buf, 2, HAL_MAX_DELAY);
if (ret == HAL_OK) return (1);
return (0);
}
int SPI_camera::Sensor_write_register(Register_blob_16 reg){
HAL_StatusTypeDef ret;
uint8_t buf[3];
buf[0] = reg.address >> 8;
buf[1] = reg.address & 0x00ff;
buf[2] = reg.data;
ret = HAL_I2C_Master_Transmit(&I2C_handle, I2C_address, buf, 3, HAL_MAX_DELAY);
if (ret == HAL_OK) return (1);
return (0);
}
void SPI_camera::Sensor_write_register_bulk(vector<Register_blob_8> regs){
for (unsigned int i = 0; i < regs.size(); i++) {
Register_blob_8 &reg = regs[i];
if ( (reg.address == 0xff) & (reg.data == 0xff) ) {
break;
} else {
Sensor_write_register(regs[i]);
}
}
}
void SPI_camera::Sensor_write_register_bulk(vector<Register_blob_16> regs){ }
int SPI_camera::ArduChip_write(uint8_t addr, uint8_t data){
HAL_StatusTypeDef ret;
uint8_t addr_write = addr | 0x80;
ArduChip_CS_enable();
ret = HAL_SPI_Transmit(&SPI_handle, (uint8_t *) &addr_write, 1, HAL_MAX_DELAY);
if (ret != HAL_OK) {
return ret;
}
ret = HAL_SPI_Transmit(&SPI_handle, (uint8_t *) &data, 1, HAL_MAX_DELAY);
if (ret != HAL_OK) {
return ret;
}
ArduChip_CS_disable();
return 0;
}
int SPI_camera::ArduChip_read(uint8_t address){
uint8_t addrMasked = address & 0x7F;
uint8_t empty = 0x00;
uint8_t ret;
ArduChip_CS_enable();
HAL_SPI_TransmitReceive(&SPI_handle, &addrMasked, &ret, 1, HAL_MAX_DELAY);
HAL_SPI_TransmitReceive(&SPI_handle, &empty, &ret, 1, HAL_MAX_DELAY);
ArduChip_CS_disable();
return ret;
}
int SPI_camera::ArduChip_FIFO_length(){
uint32_t len1, len2, len3, len = 0;
len1 = ArduChip_read(0x42);
len2 = ArduChip_read(0x43);
len3 = ArduChip_read(0x44) & 0x7f;
len = ((len3 << 16) | (len2 << 8) | len1) & 0x07fffff;
return len;
}
void SPI_camera::ArduChip_start_burst_read(){
uint8_t BURST_FIFO_READ = 0x3c;
uint8_t empty = 0x00;
HAL_SPI_TransmitReceive(&SPI_handle, &BURST_FIFO_READ, &empty, 1, HAL_MAX_DELAY);
}
void SPI_camera::ArduChip_start_DMA_transfer(uint size){
ArduChip_CS_enable();
ArduChip_start_burst_read();
HAL_SPI_Receive_DMA(&SPI_handle, image_data.data(), size);
}

View File

@ -0,0 +1,201 @@
/**
* @file SPI_camera.hpp
* @author Petr Malaník (TheColonelYoung(at)gmail(dot)com)
* @brief
* @version 0.1
* @date 11.09.2022
*/
#pragma once
#include "stm32l4xx_hal.h"
#include <vector>
#include <array>
#include <memory>
using namespace std;
typedef unsigned int uint;
/**
* @brief Class representing SPI cameras based on Arduchip solution
* Currently is only supported OV2640
*/
class SPI_camera
{
public:
/**
* @brief Describes GPIO which serves as SPI chip select pin
*/
struct Chip_select_pin {
GPIO_TypeDef *port;
uint16_t pin;
};
/**
* @brief Represents address and data of sensor settings, 8bit address, 8 bit data for example for OV2640 sensor
*/
struct Register_blob_8 {
uint8_t address;
uint8_t data;
};
/**
* @brief Represents address and data of sensor settings, 16bit address, 8 bit data for example for OV5642 sensor
*/
struct Register_blob_16 {
uint16_t address;
uint8_t data;
};
protected:
/**
* @brief HAL handle of I2C which is connected to image sensor
*/
I2C_HandleTypeDef I2C_handle;
/**
* @brief I2C address of sensor
* Common values: 0x60 for OV2640, 0x78 for OV5642
*/
uint8_t I2C_address = 0;
/**
* @brief HAL handle of SPI to which is ArduChip connected
*/
SPI_HandleTypeDef SPI_handle;
/**
* @brief GPIO description which serves as SPI Chip select
*/
Chip_select_pin SPI_CS;
/**
* @brief Raw image data transmitted from ArduChip via SPI to MCu memory
*/
vector<uint8_t> image_data;
public:
/**
* @brief Construct a new SPI camera object
*
* @param I2C_handle HAL handle of I2C which is connected to image sensor
* @param I2C_address I2C address of sensor, Common values: 0x60 for OV2640, 0x78 for OV5642
* @param SPI_handle HAL handle of SPI to which is ArduChip connected
* @param SPI_CS GPIO description which serves as SPI Chip select
*/
SPI_camera(I2C_HandleTypeDef I2C_handle, uint8_t I2C_address, SPI_HandleTypeDef SPI_handle, Chip_select_pin SPI_CS);
/**
* @brief Virtual function for camera initialization, depends on camera model
*/
virtual void Init() = 0;
/**
* @brief Virtual function for image capture, depends on camera model
*/
virtual void Capture() = 0;
protected:
/**
* @brief Write 8-bit data to 8-bit address in image sensor via I2C, used for example in OV2640
*
* @param address Address (8-bit) to write
* @param data Data (8-bit) to write
* @return int HAL status
*/
int Sensor_write_register(uint8_t address, uint8_t data);
/**
* @brief Write 8-bit data to 16-bit address in image sensor via I2C, used for example in OV5642
*
* @param address Address (16-bit) to write
* @param data Data (8-bit) to write
* @return int HAL status
*/
int Sensor_write_register(uint16_t address, uint8_t data);
/**
* @brief Write register representation in structure (8-bit address, 8-bit data) into image sensor via I2C
* used for example in OV2640
*
* @param reg Register represented in structure (8-bit address, 8-bit data), used for example in OV2640
* @return int HAL status
*/
int Sensor_write_register(Register_blob_8 reg);
/**
* @brief Write register representation in structure (16-bit address, 8-bit data) into image sensor via I2C
* used for example in OV5642
*
* @param reg Register represented in structure (16-bit address, 8-bit data), used for example in OV5642
* @return int HAL status
*/
int Sensor_write_register(Register_blob_16 reg);
/**
* @brief Write vector of register settings (8-bit address, 8-bit data) into image sensor in bulk
* used for example in OV2640
*
* @param regs vector containing register settings (8-bit address, 8-bit data)
*/
void Sensor_write_register_bulk(vector<Register_blob_16> regs);
/**
* @brief Write vector of register settings (16-bit address, 8-bit data) into image sensor in bulk
* used for example in OV5642
*
* @param regs vector containing register settings (16-bit address, 8-bit data), used for example in OV5642
*/
void Sensor_write_register_bulk(vector<Register_blob_8> regs);
/**
* @brief Write data (8-bit) into register address (8-bit) of ArduChip via SPI
*
* @param addr Address (8-bit) to write
* @param data Data (8-bit) to write
* @return int HAL status
*/
int ArduChip_write(uint8_t addr, uint8_t data);
/**
* @brief Read data (8-bit) from register address (8-bit) of ArduChip via SPI
*
* @param address Address (8-bit) from which read
* @return int HAL status
*/
int ArduChip_read(uint8_t address);
/**
* @brief Calculates size of FIFO which is used for image data inside ArduChip
* Performs communication via SPI with ArduChip
*
* @return int Count of bytes in FIFO of ArduChip
*/
int ArduChip_FIFO_length();
/**
* @brief Initialize Burst read of FIFO containing image data via SPI from ArduChip
* Must be followed by DMA request and read, after readout is complete CS signal must be disabled
*/
void ArduChip_start_burst_read();
/**
* @brief Initialize DMA transfer of image data from ArduChip FIFO via SPI
* Burst read operation must be setup before, after readout is complete CS signal must be disabled
*
* @param size Amount of bytes to read
*/
void ArduChip_start_DMA_transfer(uint size);
/**
* @brief Enable communication with ArduChip via SPI, CS signal is active low
*/
void ArduChip_CS_enable(){ HAL_GPIO_WritePin(SPI_CS.port, SPI_CS.pin, GPIO_PIN_RESET); };
/**
* @brief Disables communication with ArduChip via SPI, CS signal is active low
*/
void ArduChip_CS_disable(){ HAL_GPIO_WritePin(SPI_CS.port, SPI_CS.pin, GPIO_PIN_SET); };
};

Some files were not shown because too many files have changed in this diff Show More