set(STM32_ALL_DEVICES
    C011D6
    C011F4
    C011F6
    C011J4
    C011J6
    C031C4
    C031C6
    C031F4
    C031F6
    C031G4
    C031G6
    C031K4
    C031K6
    F030C6
    F030C8
    F030CC
    F030F4
    F030K6
    F030R8
    F030RC
    F031C4
    F031C6
    F031E6
    F031F4
    F031F6
    F031G4
    F031G6
    F031K4
    F031K6
    F038C6
    F038E6
    F038F6
    F038G6
    F038K6
    F042C4
    F042C6
    F042F4
    F042F6
    F042G4
    F042G6
    F042K4
    F042K6
    F042T6
    F048C6
    F048G6
    F048T6
    F051C4
    F051C6
    F051C8
    F051K4
    F051K6
    F051K8
    F051R4
    F051R6
    F051R8
    F051T8
    F058C8
    F058R8
    F058T8
    F070C6
    F070CB
    F070F6
    F070RB
    F071C8
    F071CB
    F071RB
    F071V8
    F071VB
    F072C8
    F072CB
    F072R8
    F072RB
    F072V8
    F072VB
    F078CB
    F078RB
    F078VB
    F091CB
    F091CC
    F091RB
    F091RC
    F091VB
    F091VC
    F098CC
    F098RC
    F098VC
    F100C4
    F100C6
    F100C8
    F100CB
    F100R4
    F100R6
    F100R8
    F100RB
    F100RC
    F100RD
    F100RE
    F100V8
    F100VB
    F100VC
    F100VD
    F100VE
    F100ZC
    F100ZD
    F100ZE
    F101C4
    F101C6
    F101C8
    F101CB
    F101R4
    F101R6
    F101R8
    F101RB
    F101RC
    F101RD
    F101RE
    F101RF
    F101RG
    F101T4
    F101T6
    F101T8
    F101TB
    F101V8
    F101VB
    F101VC
    F101VD
    F101VE
    F101VF
    F101VG
    F101ZC
    F101ZD
    F101ZE
    F101ZF
    F101ZG
    F102C4
    F102C6
    F102C8
    F102CB
    F102R4
    F102R6
    F102R8
    F102RB
    F103C4
    F103C6
    F103C8
    F103CB
    F103R4
    F103R6
    F103R8
    F103RB
    F103RC
    F103RD
    F103RE
    F103RF
    F103RG
    F103T4
    F103T6
    F103T8
    F103TB
    F103V8
    F103VB
    F103VC
    F103VD
    F103VE
    F103VF
    F103VG
    F103ZC
    F103ZD
    F103ZE
    F103ZF
    F103ZG
    F105R8
    F105RB
    F105RC
    F105V8
    F105VB
    F105VC
    F107RB
    F107RC
    F107VB
    F107VC
    F205RB
    F205RC
    F205RE
    F205RF
    F205RG
    F205VB
    F205VC
    F205VE
    F205VF
    F205VG
    F205ZC
    F205ZE
    F205ZF
    F205ZG
    F207IC
    F207IE
    F207IF
    F207IG
    F207VC
    F207VE
    F207VF
    F207VG
    F207ZC
    F207ZE
    F207ZF
    F207ZG
    F215RE
    F215RG
    F215VE
    F215VG
    F215ZE
    F215ZG
    F217IE
    F217IG
    F217VE
    F217VG
    F217ZE
    F217ZG
    F301C6
    F301C8
    F301K6
    F301K8
    F301R6
    F301R8
    F302C6
    F302C8
    F302CB
    F302CC
    F302K6
    F302K8
    F302R6
    F302R8
    F302RB
    F302RC
    F302RD
    F302RE
    F302VB
    F302VC
    F302VD
    F302VE
    F302ZD
    F302ZE
    F303C6
    F303C8
    F303CB
    F303CC
    F303K6
    F303K8
    F303R6
    F303R8
    F303RB
    F303RC
    F303RD
    F303RE
    F303VB
    F303VC
    F303VD
    F303VE
    F303ZD
    F303ZE
    F318C8
    F318K8
    F328C8
    F334C4
    F334C6
    F334C8
    F334K4
    F334K6
    F334K8
    F334R6
    F334R8
    F358CC
    F358RC
    F358VC
    F373C8
    F373CB
    F373CC
    F373R8
    F373RB
    F373RC
    F373V8
    F373VB
    F373VC
    F378CC
    F378RC
    F378VC
    F398VE
    F401CB
    F401CC
    F401CD
    F401CE
    F401RB
    F401RC
    F401RD
    F401RE
    F401VB
    F401VC
    F401VD
    F401VE
    F405OE
    F405OG
    F405RG
    F405VG
    F405ZG
    F407IE
    F407IG
    F407VE
    F407VG
    F407ZE
    F407ZG
    F410C8
    F410CB
    F410R8
    F410RB
    F410T8
    F410TB
    F411CC
    F411CE
    F411RC
    F411RE
    F411VC
    F411VE
    F412CE
    F412CG
    F412RE
    F412RG
    F412VE
    F412VG
    F412ZE
    F412ZG
    F413CG
    F413CH
    F413MG
    F413MH
    F413RG
    F413RH
    F413VG
    F413VH
    F413ZG
    F413ZH
    F415OG
    F415RG
    F415VG
    F415ZG
    F417IE
    F417IG
    F417VE
    F417VG
    F417ZE
    F417ZG
    F423CH
    F423MH
    F423RH
    F423VH
    F423ZH
    F427AG
    F427AI
    F427IG
    F427II
    F427VG
    F427VI
    F427ZG
    F427ZI
    F429AG
    F429AI
    F429BE
    F429BG
    F429BI
    F429IE
    F429IG
    F429II
    F429NE
    F429NG
    F429NI
    F429VE
    F429VG
    F429VI
    F429ZE
    F429ZG
    F429ZI
    F437AI
    F437IG
    F437II
    F437VG
    F437VI
    F437ZG
    F437ZI
    F439AI
    F439BG
    F439BI
    F439IG
    F439II
    F439NG
    F439NI
    F439VG
    F439VI
    F439ZG
    F439ZI
    F446MC
    F446ME
    F446RC
    F446RE
    F446VC
    F446VE
    F446ZC
    F446ZE
    F469AE
    F469AG
    F469AI
    F469BE
    F469BG
    F469BI
    F469IE
    F469IG
    F469II
    F469NE
    F469NG
    F469NI
    F469VE
    F469VG
    F469VI
    F469ZE
    F469ZG
    F469ZI
    F479AG
    F479AI
    F479BG
    F479BI
    F479IG
    F479II
    F479NG
    F479NI
    F479VG
    F479VI
    F479ZG
    F479ZI
    F722IC
    F722IE
    F722RC
    F722RE
    F722VC
    F722VE
    F722ZC
    F722ZE
    F723IC
    F723IE
    F723VE
    F723ZC
    F723ZE
    F730I8
    F730R8
    F730V8
    F730Z8
    F732IE
    F732RE
    F732VE
    F732ZE
    F733IE
    F733VE
    F733ZE
    F745IE
    F745IG
    F745VE
    F745VG
    F745ZE
    F745ZG
    F746BE
    F746BG
    F746IE
    F746IG
    F746NE
    F746NG
    F746VE
    F746VG
    F746ZE
    F746ZG
    F750N8
    F750V8
    F750Z8
    F756BG
    F756IG
    F756NG
    F756VG
    F756ZG
    F765BG
    F765BI
    F765IG
    F765II
    F765NG
    F765NI
    F765VG
    F765VI
    F765ZG
    F765ZI
    F767BG
    F767BI
    F767IG
    F767II
    F767NG
    F767NI
    F767VG
    F767VI
    F767ZG
    F767ZI
    F769AI
    F769BG
    F769BI
    F769IG
    F769II
    F769NG
    F769NI
    F777BI
    F777II
    F777NI
    F777VI
    F777ZI
    F778AI
    F779AI
    F779BI
    F779II
    F779NI
    G030C6
    G030C8
    G030F6
    G030J6
    G030K6
    G030K8
    G031C4
    G031C6
    G031C8
    G031F4
    G031F6
    G031F8
    G031G4
    G031G6
    G031G8
    G031J4
    G031J6
    G031K4
    G031K6
    G031K8
    G031Y8
    G041C6
    G041C8
    G041F6
    G041F8
    G041G6
    G041G8
    G041J6
    G041K6
    G041K8
    G041Y8
    G050C6
    G050C8
    G050F6
    G050K6
    G050K8
    G051C6
    G051C8
    G051F6
    G051F8
    G051G6
    G051G8
    G051K6
    G051K8
    G061C6
    G061C8
    G061F6
    G061F8
    G061G6
    G061G8
    G061K6
    G061K8
    G070CB
    G070KB
    G070RB
    G071C6
    G071C8
    G071CB
    G071EB
    G071G6
    G071G8
    G071GB
    G071K6
    G071K8
    G071KB
    G071R6
    G071R8
    G071RB
    G081CB
    G081EB
    G081GB
    G081KB
    G081RB
    G0B0CE
    G0B0KE
    G0B0RE
    G0B0VE
    G0B1CB
    G0B1CC
    G0B1CE
    G0B1KB
    G0B1KC
    G0B1KE
    G0B1MB
    G0B1MC
    G0B1ME
    G0B1NE
    G0B1RB
    G0B1RC
    G0B1RE
    G0B1VB
    G0B1VC
    G0B1VE
    G0C1CC
    G0C1CE
    G0C1KC
    G0C1KE
    G0C1MC
    G0C1ME
    G0C1RC
    G0C1RE
    G0C1VC
    G0C1VE
    G431C6
    G431C8
    G431CB
    G431K6
    G431K8
    G431KB
    G431M6
    G431M8
    G431MB
    G431R6
    G431R8
    G431RB
    G431V6
    G431V8
    G431VB
    G441CB
    G441KB
    G441MB
    G441RB
    G441VB
    G471CC
    G471CE
    G471MC
    G471ME
    G471QC
    G471QE
    G471RC
    G471RE
    G471VC
    G471VE
    G473CB
    G473CC
    G473CE
    G473MB
    G473MC
    G473ME
    G473PB
    G473PC
    G473PE
    G473QB
    G473QC
    G473QE
    G473RB
    G473RC
    G473RE
    G473VB
    G473VC
    G473VE
    G474CB
    G474CC
    G474CE
    G474MB
    G474MC
    G474ME
    G474PB
    G474PC
    G474PE
    G474QB
    G474QC
    G474QE
    G474RB
    G474RC
    G474RE
    G474VB
    G474VC
    G474VE
    G483CE
    G483ME
    G483PE
    G483QE
    G483RE
    G483VE
    G484CE
    G484ME
    G484PE
    G484QE
    G484RE
    G484VE
    G491CC
    G491KC
    G491MC
    G491RC
    G491VC
    G491CE
    G491KE
    G491ME
    G491RE
    G491VE
    G4A1CE
    G4A1KE
    G4A1ME
    G4A1RE
    G4A1VE
    GBK1CB
    H723VE
    H723VG
    H723ZE
    H723ZG
    H725AE
    H725AG
    H725IE
    H725IG
    H725RE
    H725RG
    H725VE
    H725VG
    H725ZE
    H725ZG
    H730AB
    H730IB
    H730VB
    H730ZB
    H733VG
    H733ZG
    H735AG
    H735IG
    H735RG
    H735VG
    H735ZG
    H742AG
    H742AI
    H742BG
    H742BI
    H742IG
    H742II
    H742VG
    H742VI
    H742XG
    H742XI
    H742ZG
    H742ZI
    H743AG
    H743AI
    H743BG
    H743BI
    H743IG
    H743II
    H743VG
    H743VI
    H743XG
    H743XI
    H743ZG
    H743ZI
    H745BG
    H745BI
    H745IG
    H745II
    H745XG
    H745XI
    H745ZG
    H745ZI
    H747AG
    H747AI
    H747BG
    H747BI
    H747IG
    H747II
    H747XG
    H747XI
    H747ZI
    H750IB
    H750VB
    H750XB
    H750ZB
    H753AI
    H753BI
    H753II
    H753VI
    H753XI
    H753ZI
    H755BI
    H755II
    H755XI
    H755ZI
    H757AI
    H757BI
    H757II
    H757XI
    H757ZI
    H7A3AG
    H7A3AI
    H7A3IG
    H7A3II
    H7A3LG
    H7A3LI
    H7A3NG
    H7A3NI
    H7A3QI
    H7A3RG
    H7A3RI
    H7A3VG
    H7A3VI
    H7A3ZG
    H7A3ZI
    H7B0AB
    H7B0IB
    H7B0RB
    H7B0VB
    H7B0ZB
    H7B3AI
    H7B3II
    H7B3LI
    H7B3NI
    H7B3QI
    H7B3RI
    H7B3VI
    H7B3ZI
    L010C6
    L010F4
    L010K4
    L010K8
    L010R8
    L010RB
    L011D3
    L011D4
    L011E3
    L011E4
    L011F3
    L011F4
    L011G3
    L011G4
    L011K3
    L011K4
    L021D4
    L021F4
    L021G4
    L021K4
    L031C4
    L031C6
    L031E4
    L031E6
    L031F4
    L031F6
    L031G4
    L031G6
    L031K4
    L031K6
    L041C6
    L041E6
    L041F6
    L041G6
    L041K6
    L051C6
    L051C8
    L051K6
    L051K8
    L051R6
    L051R8
    L051T6
    L051T8
    L052C6
    L052C8
    L052K6
    L052K8
    L052R6
    L052R8
    L052T6
    L052T8
    L053C6
    L053C8
    L053R6
    L053R8
    L062C8
    L062K8
    L063C8
    L063R8
    L071C8
    L071CB
    L071CZ
    L071K8
    L071KB
    L071KZ
    L071RB
    L071RZ
    L071V8
    L071VB
    L071VZ
    L072CB
    L072CZ
    L072KB
    L072KZ
    L072RB
    L072RZ
    L072V8
    L072VB
    L072VZ
    L073CB
    L073CZ
    L073RB
    L073RZ
    L073V8
    L073VB
    L073VZ
    L081CB
    L081CZ
    L081KZ
    L082CZ
    L082KZ
    L083CB
    L083CZ
    L083RB
    L083RZ
    L083V8
    L083VB
    L083VZ
    L100C6
    L100R8
    L100RB
    L100RC
    L151C6
    L151C8
    L151CB
    L151CC
    L151QC
    L151QD
    L151QE
    L151R6
    L151R8
    L151RB
    L151RC
    L151RD
    L151RE
    L151UC
    L151V8
    L151VB
    L151VC
    L151VD
    L151VE
    L151ZC
    L151ZD
    L151ZE
    L152C6
    L152C8
    L152CB
    L152CC
    L152QC
    L152QD
    L152QE
    L152R6
    L152R8
    L152RB
    L152RC
    L152RD
    L152RE
    L152UC
    L152V8
    L152VB
    L152VC
    L152VD
    L152VE
    L152ZC
    L152ZD
    L152ZE
    L162QC
    L162QD
    L162RC
    L162RD
    L162RE
    L162VC
    L162VD
    L162VE
    L162ZC
    L162ZD
    L162ZE
    L412C8
    L412CB
    L412K8
    L412KB
    L412R8
    L412RB
    L412T8
    L412TB
    L422CB
    L422KB
    L422RB
    L422TB
    L431CB
    L431CC
    L431KB
    L431KC
    L431RB
    L431RC
    L431VC
    L432KB
    L432KC
    L433CB
    L433CC
    L433RB
    L433RC
    L433VC
    L442KC
    L443CC
    L443RC
    L443VC
    L451CC
    L451CE
    L451RC
    L451RE
    L451VC
    L451VE
    L452CC
    L452CE
    L452RC
    L452RE
    L452VC
    L452VE
    L462CE
    L462RE
    L462VE
    L471QE
    L471QG
    L471RE
    L471RG
    L471VE
    L471VG
    L471ZE
    L471ZG
    L475RC
    L475RE
    L475RG
    L475VC
    L475VE
    L475VG
    L476JE
    L476JG
    L476ME
    L476MG
    L476QE
    L476QG
    L476RC
    L476RE
    L476RG
    L476VC
    L476VE
    L476VG
    L476ZE
    L476ZG
    L486JG
    L486QG
    L486RG
    L486VG
    L486ZG
    L496AE
    L496AG
    L496QE
    L496QG
    L496RE
    L496RG
    L496VE
    L496VG
    L496ZE
    L496ZG
    L4A6AG
    L4A6QG
    L4A6RG
    L4A6VG
    L4A6ZG
    L4P5AE
    L4P5AG
    L4P5CE
    L4P5CG
    L4P5QE
    L4P5QG
    L4P5RE
    L4P5RG
    L4P5VE
    L4P5VG
    L4P5ZE
    L4P5ZG
    L4Q5AG
    L4Q5CG
    L4Q5QG
    L4Q5RG
    L4Q5VG
    L4Q5ZG
    L4R5AG
    L4R5AI
    L4R5QG
    L4R5QI
    L4R5VG
    L4R5VI
    L4R5ZG
    L4R5ZI
    L4R7AI
    L4R7VI
    L4R7ZI
    L4R9AG
    L4R9AI
    L4R9VG
    L4R9VI
    L4R9ZG
    L4R9ZI
    L4S5AI
    L4S5QI
    L4S5VI
    L4S5ZI
    L4S7AI
    L4S7VI
    L4S7ZI
    L4S9AI
    L4S9VI
    L4S9ZI
    L552CC
    L552CE
    L552ME
    L552QC
    L552QE
    L552RC
    L552RE
    L552VC
    L552VE
    L552ZC
    L552ZE
    L562CE
    L562ME
    L562QE
    L562RE
    L562VE
    L562ZE
    MP151A
    MP151C
    MP151D
    MP151F
    MP153A
    MP153C
    MP153D
    MP153F
    MP157A
    MP157C
    MP157D
    MP157F
    U575CG
    U575CI
    U585CI
    U575RG
    U575RI
    U585RI
    U5750G
    U5750I
    U5850I
    U575VG
    U575VI
    U585VI
    U575QG
    U575QI
    U585QI
    U575ZG
    U575ZI
    U585ZI
    U575AG
    U575AI
    U585AI
    WB5MMG
    WB50CG
    WB30CE
    WB10CC
    WB55CC
    WB55CE
    WB55CG
    WB55RC
    WB55RE
    WB55RG
    WB55VC
    WB55VE
    WB55VG
    WB55VY
    WB15CC
    WB35CC
    WB35CE
    WL55CC
    WL54CC
    WL55JC
    WL54JC
    WLE5J8
    WLE5JB
    WLE5JC
    WLE5C8
    WLE5CB
    WLE5CC
    WLE4J8
    WLE4JB
    WLE4JC
    WLE4C8
    WLE4CB
    WLE4CC
)

# Store a list of devices into a given STM_DEVICES list.
# You can also specify multiple device families. Examples:
# Get list of all devices for H7 family: stm32_get_devices_by_family(STM_DEVICES FAMILY H7)
# Get list of all devices: stm32_get_devices_by_family(STM_DEVICES)
function(stm32_get_devices_by_family STM_DEVICES)
    # Specify keywords for argument parsing here
    set(ARG_OPTIONS "")
    set(ARG_SINGLE "")
    set(ARG_MULTIPLE FAMILY)

    # Parse arguments. Multiple families can be specified and will be stored in ARG_<KeywordName>
    cmake_parse_arguments(PARSE_ARGV 1 ARG "${ARG_OPTIONS}" "${ARG_SINGLE}" "${ARG_MULTIPLE}")
    stm32_dev_parser_check()

    # Build a list of families by filtering the whole list with the specified families
    if(ARG_FAMILY)
        set(RESULTING_DEV_LIST "")
        foreach(FAMILY ${ARG_FAMILY})
            set(STM_DEVICE_LIST ${STM32_ALL_DEVICES})
            list(FILTER STM_DEVICE_LIST INCLUDE REGEX "^${FAMILY}")
            list(APPEND RESULTING_DEV_LIST ${STM_DEVICE_LIST})
            if(NOT STM_DEVICE_LIST)
                message(WARNING "No devices found for given family ${FAMILY}")
            endif()
        endforeach()
    else()
        # No family argument, so get list of all devices
        set(RESULTING_DEV_LIST ${STM32_ALL_DEVICES})
    endif()

    set(${STM_DEVICES} ${RESULTING_DEV_LIST} PARENT_SCOPE)
endfunction()

# Print the devices for a given family. You can also specify multiple device families.
# Example usage:
# Print devices for H7 family: stm32_print_devices_by_family(FAMILY H7)
# Print all devices: stm32_print_devices_by_family()
function(stm32_print_devices_by_family)
    # Specify keywords for argument parsing here
    set(ARG_OPTIONS "")
    set(ARG_SINGLE "")
    set(ARG_MULTIPLE FAMILY)

    # Parse arguments. Multiple families can be specified and will be stored in ARG_<KeywordName>
    cmake_parse_arguments(PARSE_ARGV 0 ARG "${ARG_OPTIONS}" "${ARG_SINGLE}" "${ARG_MULTIPLE}")
    stm32_dev_parser_check()

    if(ARG_FAMILY)
        # print devices one family per line
        foreach(FAMILY ${ARG_FAMILY})
            stm32_get_devices_by_family(STM_DEVICES FAMILY ${FAMILY})
            stm32_pretty_print_dev_list(${FAMILY} "${STM_DEVICES}")
        endforeach()
    else()
        # print all devices
        stm32_get_devices_by_family(STM_DEVICES)
        stm32_pretty_print_dev_list("all" "${STM_DEVICES}")
    endif()

endfunction()

# The arguments checked in this macro are filled by cmake_parse_argument
macro(stm32_dev_parser_check)
    # contains unexpected arguments (unknown keywords beofre ARG_MULTIPLE)
    if(ARG_UNPARSED_ARGUMENTS)
        message(WARNING "Unknown keyword(s) ${ARG_UNPARSED_ARGUMENTS} will be ignored")
    endif()
    # is populated if ARG_SINGLE or ARG_MULTIPLE is used without values
    if(ARG_KEYWORDS_MISSING_VALUES)
        message(FATAL_ERROR "Keyword ${ARG_KEYWORDS_MISSING_VALUES} expects values")
    endif()
endmacro()

# Pretty printer to limit amount of list entries printed per line
macro(stm32_pretty_print_dev_list FAMILIES STM_DEVICES)
    if(${FAMILIES} STREQUAL "all")
        message(STATUS  "Devices for all families")
    else()
        message(STATUS "Devices for ${FAMILIES} family")
    endif()
    set(TMP_LIST "")
    foreach(STM_DEVICE ${STM_DEVICES})
        list(APPEND TMP_LIST ${STM_DEVICE})
        list(LENGTH TMP_LIST CURR_LEN)
        if(CURR_LEN EQUAL 10)
            message(STATUS "${TMP_LIST}")
            set(TMP_LIST "")
        endif()
    endforeach()
    if(TMP_LIST)
        message(STATUS "${TMP_LIST}")
   endif()
endmacro()
