diff options
64 files changed, 1427 insertions, 1554 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 677ea51cec..4efa93acaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,8 +41,8 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) # Set the version information here set(VERSION_INFO_MAJOR_VERSION 3) set(VERSION_INFO_API_COMPAT 7) -set(VERSION_INFO_MINOR_VERSION 2) -set(VERSION_INFO_MAINT_VERSION 0) +set(VERSION_INFO_MINOR_VERSION 3) +set(VERSION_INFO_MAINT_VERSION git) include(GrVersion) #setup version info # Append -O2 optimization flag for Debug builds diff --git a/cmake/Modules/GnuradioConfig.cmake b/cmake/Modules/GnuradioConfig.cmake index a81211f31d..23115c484c 100644 --- a/cmake/Modules/GnuradioConfig.cmake +++ b/cmake/Modules/GnuradioConfig.cmake @@ -25,6 +25,10 @@ if(NOT GR_REQUIRED_COMPONENTS) set(GR_REQUIRED_COMPONENTS RUNTIME ANALOG BLOCKS DIGITAL FFT FILTER PMT) endif() +# Allows us to use all .cmake files in this directory +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_LIST_DIR}) + +# Easily access all libraries and includes of GNU Radio set(GNURADIO_ALL_LIBRARIES "") set(GNURADIO_ALL_INCLUDE_DIRS "") diff --git a/cmake/Toolchains/oe-sdk_cross.cmake b/cmake/Toolchains/oe-sdk_cross.cmake new file mode 100644 index 0000000000..ea77815c96 --- /dev/null +++ b/cmake/Toolchains/oe-sdk_cross.cmake @@ -0,0 +1,13 @@ +set( CMAKE_SYSTEM_NAME Linux ) +#set( CMAKE_C_COMPILER $ENV{CC} ) +#set( CMAKE_CXX_COMPILER $ENV{CXX} ) +set( CMAKE_CXX_FLAGS $ENV{CXXFLAGS} CACHE STRING "" FORCE ) +set( CMAKE_C_FLAGS $ENV{CFLAGS} CACHE STRING "" FORCE ) #same flags for C sources +set( CMAKE_LDFLAGS_FLAGS ${CMAKE_CXX_FLAGS} CACHE STRING "" FORCE ) #same flags for C sources +set( CMAKE_LIBRARY_PATH ${OECORE_TARGET_SYSROOT}/usr/lib ) +set( CMAKE_FIND_ROOT_PATH $ENV{OECORE_NATIVE_SYSROOT} $ENV{OECORE_TARGET_SYSROOT} ) +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +set ( ORC_INCLUDE_DIRS $ENV{OECORE_TARGET_SYSROOT}/usr/include/orc-0.4 ) +set ( ORC_LIBRARY_DIRS $ENV{OECORE_TARGET_SYSROOT}/usr/lib ) diff --git a/docs/doxygen/images/gnuradio-logo.png b/docs/doxygen/images/gnuradio-logo.png Binary files differdeleted file mode 100644 index ec4db23fc8..0000000000 --- a/docs/doxygen/images/gnuradio-logo.png +++ /dev/null diff --git a/docs/doxygen/images/gnuradio-logo.svg b/docs/doxygen/images/gnuradio-logo.svg new file mode 100644 index 0000000000..7143bc2a38 --- /dev/null +++ b/docs/doxygen/images/gnuradio-logo.svg @@ -0,0 +1,521 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="650" + height="164" + id="svg3716" + version="1.1" + inkscape:version="0.48.3.1 r9886" + sodipodi:docname="gnuradio-logo3.svg"> + <defs + id="defs3718" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.7" + inkscape:cx="333.61853" + inkscape:cy="-208.88012" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="843" + inkscape:window-height="720" + inkscape:window-x="510" + inkscape:window-y="445" + inkscape:window-maximized="0" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata3721"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0.71428519,1.0663847)"> + <image + y="-1.0663847" + x="-0.71428519" + id="image3732" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAooAAACkCAYAAAAQTQ/jAAAABHNCSVQICAgIfAhkiAAAIABJREFU +eJzs3Xd8VFXaB/DfuXUmkw4hAUKRpqAiiq5dsa6uAiomgBXLCsG2FiANvSuQhNVVd1UCuJZXXQsB +ey9rb6soYlmkKB0SSE9m5tbz/oHsYkyZmXumJJzv55PPvq9z5zlPQjLzzLnnPAfgOI7jOI7jOI7j +OI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7jOI7j +OI7jOI7jOI7jOI7jOI7juP0CiXcCHaG3wocmpEJWU+A4KQAAIjTC0ZsQRBN5FME4p8hxHMdxHNej +xb1QpNegNyTpCFAcDpAxIBgDiuEAxC6eagL4DsAqUKwCoV+DWF+TRWiJftYcx3Ecx3E9X8wLRQoQ +zJSOBxXOBeh4AKMYhrcBfAbQlwDxeVKp/8gwNsdxHMdx3H4lZoUinYlkUPlqAAUARsRgSAfAZyDk +fljGcrIUZgzG5DiO4ziO6zGiXijSa7wDIVm3gOJKAMnRHq8DNQB5BKL0d3K/f3uccuA4juM4jutW +olYo0pvgRVApBuitADzRGidMjQDmYre5iFTBjncyHMdxHMdxiYx5obhnDaJ8KSipAGhf1vEZWQtC +ryeLrDfjnQjHcRzHcVyiYloo0quQCVl6GIRMZBk3ShwQ3I9d5ixSBSPeyXAcx3EcxyUaZoUinSmP +AcUKAENchnIArAPBZgD1AOpBSQMoCEAz9nyRDBAMAzDIbd4APoEo5/G1ixzHcRzHcb/GpFCkM+XL +QLEYgDeCp+sAfROUvAnQryFY34TaC5EWIAOCdAQcHAGQcwCcCEAIPwWyE3DySaX1YfjP5TiO4ziO +65lcF4q0QJoDkIpwnwaQVwE8Dcl4kdyHJrd5AACdiRxQeRIILgbFsWE+3QB1JpHF9ssscuE4juM4 +juvuXBWKdKZUAkrmh/GUIAiWQhDvJfcHf3YzdlfodPkwCLgFwFQAUohPs0HJJWSx8XQUU+M4juM4 +jusWIi4U6Qz5OhD8PfQY9EXY4s1kqb4h0jEjQa9RDoJIFwM4OcSn6IAziVTar0QzL47jOI7juEQX +UaFIC5TzAPpsaM+n20GFG8hiY0UkY7FAAYIZ8gwQLASQEsJT/AA5llQaq6OdG8dxHMdxXKIKu1Ck +MzyDQeyvAGSEEP5l2MYlZCkaQ4qtQUKNMhzAaAAHw6GpIEjF3hNdKBpASCOoUwtCv4WtfEuWBjaH +mftzAMaEcPk62OZRoebOcRzHcRzX04RVKO45bUX+DHsKuS4ikz9jkfFnAtBOY05Xh0N0zoWDc0Bw +PMI/xaUOBG/DwctwzNfIUuzudLzrocKSHwRwadehySvINiYQDU6YOXEcx3Ecx3V74RWKM5XJoDSE +jR70FlJp3d3ho3kQkaWcD0pnAfhdODl0wQbBCgB3kUXmFx2Or0HATvkuENzURbxaiPJo3mOR4ziO +47j9Ufi3nmcqd4DSuR1fQIvIYqvDdjl0hjIFhM4HMDTcscP0LgTcSh4wv+owl5ny30BxQ7sPElTD +IuPIUmNN1DLkOI7jOI5LYJFuZvkzQG/77QO4hyw2b273OdOVURDo/QBOiWTMCNkAFgPmXFKJ+t/k +pEHATukZEHJhm4dqAXIq38zCcRzHcdz+LPL2OAXKXwA6a5//9DF2myeTKti/vVaaA5D5CL2fIWN0 +OwjyyCLrk988cit8aJW/wf9mOJvh0N+TJdansc2R4ziO4zgusbhsuK1ooPR2AC0QxdFtm2jTPCjI +kv8OiumusmQjCIICssh8tO0DtEA+BsBHAJog4PTObldzHMdxHMftL9wf4TdTKQd1GkiltfBX//0a +yBCl5QCZ4HYMpgidRRZZd7X9z3SGMh+C8w5ZZL0bj7Q4juM4juMSjetCEdiz1m/fFjK/NLh+GATT +wgzlAPgSwFcAvgGhP4GSWkCsh0AlOE4mHCcTIhkFSg4FcDSAA8Meg2IaWWw+HubzOI7jOI7j9itM +CsW26AzpFhDym1m7TnwPiqWQpWfJfYGt4Y2lHAKCPBA6HRTZIT7NgIPjyRLzy3DG4jiO4ziO258w +LxTpTHkMKD4DoIZw+UrAmYtK+/WuGnN3Oe5N8CIgXwWC2wH0DuEpa+EzjyB3odXNuD1BeXl5RnNz +4/lwnLE2xYHEoQMppb0BR6aESJRCopQSACCE2JRSSggJCERoIQKaKCXVEiFfQ5I+kGX5XU3TmuL9 +PbVn2bJl4qpVq6ZSx5xBLTrEBs0AaKd/AwIRmv1BPfe+++7TY5VnR4oLC180LeNMNzFEQdxc8Zc7 +R4R6/dy5c8dapn4btemRDqUpFI7S2fWCIG1Z+Je/DHeTo1ulpaV/0IP+Z93GUSVlwfyKinlu47x6 +9jA1K635z5mKeb5PtPrLgu2RCBXdxnXDpIIDwNEd0QTgOBR+ShHw21J10BHXBC3p882BlFfzX/rx +565icT3bfy7p/VM/j/+Arq6jAK031C2bDe8dJz+9/aFQYpcUFj6pG/rUUK4lhDiCKK6WZOXGBQsW +fBDKczg22O9CpvRUgHRVJAYBehuyrXuIBovFsOQeBADzfjoTy0GlJSGsjRyMVvlQwPyMxfjdiaZp +mVYweKtFnTMd2zpwd011MqUh1+l73+BUG0j/5f8eZQKnQMfNQQLMvvWWFiIIayVRes/r8/29tLR0 +E/vvIjwlJYUzVv778zst2w7ne4UNW/X5kh4HkB+97ELMxXGybcsO5QNYh4hMeoVy3YIFxdktTeZL +/pamo8L4cUGQhZDiRxOlNMXtzwkAHAmuv5dPp/a7frhv5529ZN11PowJv3ztfQ/w/fK/AwEcBeDS +o+hu1F7lM+pNdUOdqb6wscF3d/5r63fFI1kufjyCraTKZiiXkjTZHDjI1/qPry/Kmv5hfdqJN7y2 +vtMP2JRS1XFCPvhMsG17jGmY7xfNmfNsWUXFhYQQVxNMXGiYF4qk0rqbFkgiQP7SwSW7QXEOWWz9 +m/XYAEAWYSdgTaQz5RtBcTf2vBi2FQShE8kia78pEjVNSzKC/lm2TS9vbmwYvHeGkDVKAcuykgEc +YcI4IhgM3Dxn9qxdoiC+kpqefnthYWHIZ3OzyYeSoqLC14P+4JnhFIj7MnX9wsLCwsMrKiq+Zpxe +QiotLR3Z2OD/0jLtpHjn0p19c0mfRaN8uwskoXu+lwmEIlMxlEzFGDkUzSNHp9YXrrs0c1O17q04 +Ydm2xfHOj0tMBBRj0hqO8on2mmV5ecPyq6p+0zLPHQrD0C8oLip6F8A4trG59rRXRLlGKq07AXp7 +Ow+1ADiLLDajUiT+KodF5t9AMbOdhyxQcglZZL0Z7RwSwfz58/sXz5n9dmtTY3MwqGumaRwQrSKx +PZRSmIaRFQwGpu2q3rlpzqxZm+YWF14dqxzmFhc/bep6xEUisKfYBLWeZJhWwtI0LdkMBj7jRaI7 +n0/JmXNwckO3LRLbowo2hiU3Dzq+V03lzitSGz/J63tNvHPiEtfw5ObBh6j/ejsasSml0IOBk0sK +C/8Wjfjcr0WlUAQAUmndAYKb8b+1hzYovZBUmis7ex69Hql0pjKZFshP0QL5O1og19ACmdICuYUW +yOtogfwvWiDNodOVUV3msNhcAop9f5FMgOSRxcYKF99at1BRUZFWWDj7tYa62s1BXT/Ndpyo/VuH +ilIK0zQGtvoDDxbOmb2jpKRkcjTHu620aHogGMh3UyTuZRrWQcXFxZcwSCuhBQOt/zItKzXeeXRn +7+YNzhmV0lgm9uC7YtmeQOoxvWuXbLgsY/1beUMGxjsfLjGNSGke9/GFAyZGK75u6NctWFDcN1rx +uT2iWjyQReY9AC365f99giy23ujoWvonpNMCpQKWvBOUPg1gCoCDAWT9cokPwDAApwCkAgL9nhbI +n9IZ0qmdJiGbcwD8BMAGyJWk0nje7feV6EpLi2+p3bWrxgjqZzkJUCC2xzSM7EBry9OFs2Ztnju3 +6HjW8SmlRA8af2FRJP4SD7ahL1q2bFlcNyFEU0lJyQmmYR4V7zy6uyy59dFkyUrIvzuWCCiG+FqG +HpFavf6D/NxJ8c6HSzwiKLK8rQuiFd9xHKG52frtccIcU1F/MSOV1kJQ3AhJKu3oGlqgnAdd3gDQ +OQC8YYQ/BoS8QwuUl+hVyGx3/Pugg5IiEFxNKo0nws2/OyktLT2gcM6sDf6W1rts2+p0d2qiMExj +gL8l8GFx4ZxHNE1j9vtYWlR0HuuZMdOyUlZ9tfJhljETiW2ZC1gV1vuzLI9+YrxziKVMxZCPyti9 +/OMp/W6Idy5c4slS9YM0LXq1BnXo76MVm9sjJp96yWLz7+31R6QAoTMVDaDPAu0XeqGh50KWvqEF +8tj2xzeWtXd0X09SWlp0oe5v/dHQjSHxziVclFISDAanBVpbdpSWljJpreJQ5zIWcdoyDPMSTdNy +oxE73hzbOTLeOXR3T044ILu3Etzv1nd6BBtjU+vu/SS/37XxzoVLLKmSKQ79dGSoPY7DRqkTSjs8 +zoX43h4pkGb/cla0+40NhOQCeIsWqOGe1NKtUUpJSVHhE4HWQJXtOHK883HDNM0+wYD/h9Kioj+4 +jUWBQSxyastxbCHob30lGrHjSdM0wXGs/a7AYS1HDBwk9OC1iZ1RRZuMTq//+wcXDDoi3rlwiUMg +FL19etQ+XFNKE631VI8Tt0KRzlQuAEg547AZgPMGvTrkE1q6vZLCwreCweDFPeWWoWPbUlDXXyou +Lp7iJg5xaNQ2ZJimOfq2kpLx0YofJ+k95FcorgRJcnFnpPvziZYwJK3hnXfHjWPfo5frthw7emvl +99PPZTEVl0KRFiADlC5F5zOJdSC4H0SYAIqj4dDjAHIxQF8C0FmHzkGQpCVsM048lFJSVDjn30E9 +eFpPKRL3chxb0AP+J0tLZ18YcQwSneMpgT0bW4KG/jjLNZXxpiiK2NN+j7j46O/xp2f0++HReOfB +cRwbcXqjU2YBnZ568A8Y5nCyyLyeLNJfIovNf5Ml1qek0niSVFoTQHEsKL7t8NmETKQFUo9eUF5S +WPiWoes9docqpZQE/ebTJXPmHBfvXNpjmWaaoev3xjsPjktEw5Obpn40ZUC/eOfBcZx7MS8U6fXI +Amgnu+NoIak0/0geQl1HV5DF5r+RbB4LkNc6jkOitiU/3ooKCx/TDb3HzSS25TiOaFjW22VlZXE/ +Fq49hh6cuXChxt8MOa6NJNEWUkW9Mt55cBznXuzXkdjyBPzvXNFfI3iYLLIWhhKG3IVWer0xBZa8 +Env6K7Z1Ar3em9vebuvurLS4+Hq/33/p//qY92y2bXmbGupXapo2RNO0kA8FjQXHccSGev9yAAk5 +68lx8dTf2/qHJWPHytNXrgzpoGBu/yMIwiMej3e3yyC1jNLhOhD7QpHSCR0sTayDYt4STihyH5po +gXAL4LzQ3sOwrQkAFkWSZiIqKio6KBgM3LO/FIl7GYYxSJDkBwAUxDuXtgzdOLa0tPCs+fMrXo93 +LlzPsSPobdId0d0baFuUEkmgPpHAKxNbzVAMJZqnx2TKhnTIsB1/xMqe8xrMsTW/vPxlAC/HOw+u +c3HYmUban32hWEHuRUPY4Sr1lzBD2vpLe5y2jkMPKRQ1TRMCrS0fOY4T85NBiLDPCgVKEY9b3kYw +cE1paem98+fP/zHmg3eCUgpDtx6nlPYhhO+/49jY4U96YuwzO6Pak3BZ3rCsvtSfl+PVr871to7x +iDbzDWCZin4FeshrMMftr2JaKNJrIKOjTSwCeSeSmASgVCBvguLK3w6IHrN+zAgGK03TjPpaPUEQ +bFGUNhJReF+ShM8kh3yqpqRsKywsbCCEUE3TJFVVU/x+f67jGGdQC8c5oIdapjksmscFOo4jWGbw +ZQBMGnKzZJlm79LS4jsAzI13LhwXqvyq9buwp4hb9E5ebv8+ir78oJSmYyTCboVHpqIfyiwYx3Fx +EdsZRcHbB7A6+NTqbIk4rkM3grQTlqBHHBZeWFg4zDD0q6M5hqwoP0ui9PfDDj/8vvz8fLvt40VF +e47s1jTNAlD/y9e3AO4GgOuvv15NT06+1rCtqy3DGBmNqTXTsIaVFhWdN7+8POHO6zaCwTmFhYV3 +V1RU1Mc7F44L12lVW7cBOPbj/H4VR2bUzlEENsViL9lQl507on/+y2u3MQnIdenuvGO9Hn+Lx3IC +/hteW6/HO5/9yd/PHqZKgjcJACwnYN/w2vqmeOfEQuI0RaUuPsYKcNpdtkcT6PtzgTr2y9GarZMV +pVqU5KvKyspcnTZy33336dhTNN5dVFR0ELWtZw3DGMkmyz0opTAt834ACVco2rYjixJdBuCMeOfC +cZE6ftn2wvcvzA0e13vX7SxmFkVCkeNtnQAgKjugl4wfmzRCqb4gUzFPkkV7pCrauRKcFElAkkwc +WSIOkQSHAIBNCbUcATYlJkBM3SEB3ZGaTUp26Lb0U5MjftNsya+OX7FxTTRyZe35iUMH9EtquSVF +sI5Lkq1BKaKVIRFHUsSvCTL3rGS//GovNalotlpinU6lTc2W+GGNk/TA2U9v3Bjv/AHg66k5z4xM +bcjv7BrbAdUd0Wqx5N21pvLS1mbppvEvbffHKse2Vlww7Ih+kn9yimwc5ZOsYYpAU7yC5VUEW/FK +m4mwTzFyfYEMhxL4HdEJWlJLwBGqA5a4ttmSPt+FpMcT5d+hK7EtpJxADUSZor3dLJREPvvnkH7t +7o8hEax5TDClpaUT/C3NzI8lJIRQ1etZsmBB+UzWa+vKy8vXABhVXFhYouvBeZRSZmufTNPsX1pU +dO4vi6ATimnop8+dW3T8vHnlH8c7F46L1MnLt2qrL8oad2haw8ks4qXK1lgWcfZ6aVLu8P6yMTfL +Ezyrt/J97wjWVooAPABSAPQBMBTACQBAgb/WXeWzGixla5Mlv7el0Xfv+Jd//oZl/m68evYwtVdq +y7y+SYErctStveUuinmPAAJYSi8FOQByABxt0cZbN09La9wZ8P5zTX2f2Ze9ubo1Jsm3QyCOpAq/ +uYHV5iKQJNhyhmL0HYDWawZ6lWmfTOk387intz8UixwpQP41eeCFfeXWWzIVY0yWslkN55hOgVAk +i5aQLFqpAFKxZ/nUOQ5tuKPmyuRAraH+u9b0/v2EZ7Y+G63vwa2Y9lEkS2EC6GArO428QbaAU9sP +iZ8jjpkgLEO/h3VMURStFJ/3vLKyioJobsAoq6hY4POq4wWhq1eC8FiOrbGMxwqlFGbQfCbeeXCc +W2safFNaLInJ/WeJ2EPcxtA0CO9OGnDt+ssyt56VtWvt4Rn1l+Z6A1msN+AQABmKIR2Q1DL4sNT6 +aWfnblu1eVpa/edT+z74z3MGZrAcKxyvnj1M/XpqnyeP7b+j5XeZtbMGePxdFokdkYiDAV5/2lGZ +tTMnDFzf+PVFff65LC8v5pskI5WpGMqRabX/+PfUnLuiOc5jZ472/Xty9pKdV6T4T83csWxkStPR +2WowrCKxMwKhyFJ170EpTScfn1m9YscVqc0rp2bd8+60wR4mAzAUh5NZ6Cft/mdCJ9Ob4A072rXS +SaA4qINHvwg3XiKZW1R0omGYrl9k9yWKoiWrnqO1+eUvsozbkTvKFr7iUdRzBZHRoicAlmkermla +1M5ydsMwzf6lxcVhtXniuEST/+rGnVsCSV+xiKWKTpab5787KfeSaT+n14/rs/P+ob7m/iw323RF +JBQDvP7036XvvnpC/127v7+41+svx7hg/GRq3z8d2Xdnw5j0+qnpssH0LmCabIpj0uovOj75zZpP +pvTrNv1gZcHBYWn1t3w0tR/ztfuaBuHfk7PvPXfghoajMuuuyfEEY1K45XgCyUekN/zpUHFXwxeT ++5bEYsxQxb5QJKSDW4akHwLSreGEonlQ4JCOP1UIwqth5ZZgTMd6gGXPREEQHFVWzikrK2PyBhCq ++RUVr8uKch1pb8NRBBzHEUxTT9hiTDeCCzRNS4p3HhznRqOpMFkLLBAa9gQAADxx9rDUHy7p/fVJ +WTWPD0pqjfsHw2TREkalNv3+hH67az6fkh31k7+WjB0rf3dJ73ePTqu9J0vVo1qs9PP4Mw9Prfvo +i8k5s6I5DksKcXBgUtP9r549TGUV8/38ASddvSmt7qjMuhszGBfloeqlGOqRmbvn/3x5xraXJg3u +YBIstmJfKBrmiwCC7T5GyO10pjo+lDA0DyJ6yUsAdHTe8dfkAeP7yJKMv6Kiol6mYR7CKh4hBIrH +Wzy/ouJNVjHDUV6+sFJV1I9YxbMt80JWsVizLVs1goEn4p0Hx7mxy6886TBYXixShP1G/v6F/Y47 +Padm+8iUxjGsbvWxkiaZ0lEZdcX/ubTXF4+Mi85twlfyBuecfej6bQenNI6L1ffvEW1yeEbdX1Zd +lP1wTAZkoLeiq73SmopYxPryoj53/i5913v9Pf40FvHcGpzU0u/kzOrvP8jrF/fiPeaFIvkHqgFy +XwcPi6DOs3SmfOMvPRfbRa9BX/RWngfBtA4Hot37rGdCaBHLTSCyoqwtKysL6XjEaFG83omiIDI5 +zsu2nBGapsVh6URodF0/b+7cubyHHNdtBT2/2xyw3f+JhXuj+L3JA/MOz6j/INsTaP+o1wRAAByU +3HTkKYPqNy7LG8K0sHhj6uCDjkyp2zDA63d1yz4SIqE4LK3uilUXZT8V67EjlSlbeW6er2kQ1l2W ++dHYtPpbo9F03o0UyRKO67X7L19fnB3Xte9xeqM1ygHUdfCgBIp7Icr/oQXSbXSmdBydqQ6jM5RD +6AxlEi2QKyHKawF6bicD6JCEmN5eZc22rKmsYgmi4Hi8SXFv26JpWp3q8dzSwRGOYbFtWzJNM2HX +1FBKiREMroh3HhwXqfyqKttwRNcb0RxKQt5V+2H+wPFHptY8kyJZ3WJzxaAkf/axybXrl+XlRnR7 +va1X8gbnjPbUreyjBuK6dOWQ1Popn+Tn3BHPHELlk+3+kT5X0yDkr+/99TBf8/Esc2JJJBSHpdbl +f3VRn7gtpYtLoUgqUQ/Q8wB01gx0KED+DEo+BnXWgdBvQehyADMAJHcxhArb+YROV0YxSzqGKiq0 +gZZpMTtVRpGkVzRN28wqnhvzy8ruU1X1ERaxqG139mHBNbdrKk3TGF5SUngxo3Q4LvaI+0XSDkhL +KNf9a9LAg0en7n7OJyXWrE5Xcj3+3qPV4Kdu47w7bbBndHL9tzme+BaJwJ7i5IiMhrkfXZh7drxz +6YpM7Ihv/09al/XhyJTG0SzziQYCYExa/dmrpvZZHo/x43brjlRaH4LixuiNQHMg0NdogYfpruFY +aG3Up7M6T1kQBdsh4uVMgjFSvnDhlV5f0i2iILi6DU1hR3VGUZalHYLgbkbF0M0lS5Ys6XAZBccl +KgoQmTiuF/QbDunydIpleQcrw5IbP0yVzW4xk9jWgSmNh306pd8cNzFyrJa3cz3+3qxycksVbAxJ +aX4GBAn9b0IivEW1ckrOY4ekNiTsXam2CIBD0xomfTY557ZYjx3XNV5ksbkEBFcDMBhE2wFC5+DX +s5QDAfs9eo061H382LEc6w+sYkmi/FEiHiu3YEH53b7UtPQkj/ceSVZ+liTRL0qSJYiiHeoXpUJU +X1QpJUFZVf/mJoZtWb6NGzc8yConjouVqrOH9faI7lvRBGyxy02FQ6Xaxwck+ePWp5CFYUlNdyw7 +NrJb0J9M7nvjiOSmhLv92dfjT+nnCeTEOw/WPs3PufzQtPpL451HuARCMTqtUXs7v/8psRw37kfc +kUXmQ7RAWgsIzwA00tNZPoJt5JOl2EFniD+ACCsAKL88NgCC/R6dqZ5CFunrGaUdVZZtMzn6jhAC +QZL+xCJWNGia5gdw8y9fCUlV1Vm2aU6zLDMz0himYV5aWlo6b/78+RtY5sZx0TQg1T+FRc/CJlPt +tNPCq5MHDB2ZstvVhoRE0FvVlcGDrXn4FGG1eXsxb9ABo1J2/TXRdnfvpbA9LyHu3srrN3BUWsM/ +ZHatfWPKK1pkVHLLc0vGjs2avnIlk82hXUmIXaOk0voQPmM4QEuAsI7dWw+Qi5FtnkyWYgcAkMX2 +yyDChdh3lpKQXDj2u3S6OnzfJ9Nb4aMF6gQ6Q5lPC5SXaIH8JS2QN+zz9R6dIS+lBfLVbZ8bLUVF +RQc5tsOkL5QkSfVlZWWrWMTaX2ma5kiKcpmb5YqO7QiWafCNLVy34hONiW5jmI6AzbXCW51dM1AK +/MMrWt1qXWJH+qn+q8J9zghP63Np3fSWe3c0UA2+mCqZcZ8kc6Ov6k87esSWmO1MT4hCEQDIXWgl +lVYZiDkAhOQBeALAevxvd7QNoAbAd6D4Gxx6JmxzFKk0niTarzswkEX6S4CQh7bFomC/S69VR9Br +5aNpgfQcWuVawHkBhJb8sot6LIAh+3ydDII/AngQgrOWFsjf0QLpZjqzy800ERPgnMdsfaIkvsMk +0H6urKzsFUVWv3QTw9D1w+bOLc5nlRPHRdOyvFzvIJ//JLdxqnVPwxXvbWy/by6AZcfmegcktboe +py2TCqjWPfrWgLdxc8C3baM/+aeNft/mbQHvruqgt7nRlG0WPSLbyvbo6c+dNyDkpU7/mjToD8N8 +TYcxT4Rr1/uT+l8+LLmlR/y8D0xpuuDNi3JjMoGVcFU1WYQWwFgOwNXuHlKpv0gL1DzAqcJ/b0OT +/nCcrwEkRbj+9WCA/BVULqIzMQuLzP8jLI9OAUCdDhuIh4UQAlWUK1nE4gAiSRMEy9ziOE7En/yN +gL5U07TlmqZ1z3se3H5jiGgtSpVM15uwag3PG0Bjh48PGGjfnCpZTCYsArZEtwS8q6t177Kf/b7/ +u/zltds6u/7Z84f2yfW0XpspG1MHJLUOVxjcZpeIg36qeQ2AkDa25PqaK8Uo3nIO2BIaLUl36J77 +rBJxxHTZVHra7eRQHZDcEpVb/BQEu3Ql0GwpPwUsYZ0NoYYQeGViD0wIvxKNAAAgAElEQVQRrVG9 +VKM361lzj2iTAaL/UQBRX9uacIUiS6RSf5Feq+TDocvwvzWLLFoP9AbFIyhQplLbmLb3tjcLDhwm +LX0IIfbt8+a9q82fzyLcfq+srGxHcXHxg0F/64xIY5iWlSbq+r0AbmCYGscx9erEgeNHptS47pRg +U4LdptppL74MxWQyy76uNXXdNttz6in/3LY11Odc8NyGGgC3A7j9zfMGjxme2vjqYF9LpOvk/ytZ +to4M5bp38weePtS3c6Db8dpqMGV7sz/5/UZD/ftOkvpaftX3v9os+si4wZ5h2eb4VNG4NNsTPCNb +jc1ZxvH2QX7upNykml4sYzZbkl0d9HxQZ3puP/rpHR92dN0LEw5MGZTccM/ApJZLMmSD2ZGDB3j9 +x76YN+iACVWbfmYVsz0Jc+s5WsgDxgsA/hmd6PRMiMpKep3C7AQO23aY9E8UJbGGkARdHd1NKYpy +rSRJ4ayh/Q1DD85csGCB6zcjjouGD/Nyzzomq/bZJAa9DLcFvDWnV23+obNrMpXggW7H+U9z2tcj +HqsdEU6R2NaZz29c9eb3Qwb92JK61m0+HsE+IJTrchT/XwSGN6SCtkhXN6SveKsxM+WwJ2tOO2n5 +lhfaFokAcMV7G4MnPrOt6rAnd01YPLDZ92Vtr4UNlmwxSyRB9fUEKhi0BQUAGI5Iv21Kf+2dXdm9 +hz9ef2pnRSIATHzxx+YxT1Zf/bI+tNea5tSvKINDJwBAFW0yRGmNeleNHl8o0pnyjQCuiOIIfWHT +9+l0mcm6B+pQJsdWCUT8jkUc7n80TXMUWfmjm5NlHMcRW5sa49I0leM68sKEA7K/vTjrjaMydr+W +IRtM7jTtCHoLO3v8kfMGp6dLpqvZlRpdDW6sTT/WTYy9pq9caf7YmHpSqy25ugctEqfL1/AXJhyQ +PTCpdYybcfa1W1eNz+p7/+Gwp3ZdmF+1NRDq8zQNzlHLdhZ+W5s18Gd/8k+s8kk07+Tl9h/obRnG +IlaDKZuf1mdOHP3PXX84//mNYU0cXPb46taRT9SO/bIh8xFWa2QHJLWesmT82Kg2ae/Rt57pDCUf +lN4dg6EyIJDX6XWe48j9wYingO+++27vti2b2ex+E/Atkzjcr8wvL19eVDhrtR40Iu7mrxvGccXF +xb8vKyt7g2VuHBcqbdw4aXTG1qP6eVrOz1aCeTmeHYM9DNetbfT7thzzzM5OT2CSdclZ1ZAx0804 +fhNf/uG19Z2d8BWWiS/+XL3+soyfh/paIu69Kwn/XebUoQHJgdIkRmvWdutq8JvmzLFdzd525qRn +N+2gwLD/XNrr45HJTUwK70SSJplzFAbtcHRHpN80pU8at2z7S27i/O6pnVd+c1F28ui0OtdtoVIl +SzjCt+02AJ1+MHOjxxaKtEA9EHAeQsxmTWkOLHs5nYbjyaPocJdfZ3bt2jWI1Y5nVRK/YBKI+w1f +ctoE06j9yXGciH63KKWwLfNxSmk2Xx7AtSfX13LF5mlpk1jHlQg8AnHUVOlzNVotaYK2SDf4lcld +XXfJa+ubACTchjvdEbcDiLhQFEjXtxwyJf38SOPvK2BLdHVz2jluisS9CEC1obUnXLSh14/Dk5uY +zL4lil6ycQGLOKsb0he7LRL3OuzJ6vx1l/VaP8zX5PpAkCxVvwy8UAwP1SCg2nkUXZ8JvQfBl3Dw +fxDFl9AarCaPIkivQW8QaTiIcB6IcwlAul47SHAEvMptgFEcSd6yLByoh3zToHN+3fqGTSSurdLS +0k0lhYWPBYKBaZHGMA0ja25JyZ8BxPw4Ji7x9VF1L4CITvmIJwpgXUvaX06vqnZ99nG8UApX6/Wc +Lj76LcsblpXt3drfzRh7fdOUfu9pVdv+xSIWsOdW9Ki8jON6q8FtGbLRI44efej4A1OyPZtd/7x3 +6En1r47ceR2LnPba0JJ8Yi8luMntzzpHDfR9YcIB2RNf/LmaVW776plrFKvlSwEcE8KVNSBkChaZ +vyOLzfvJA8FNe2cDyVLsJkusT8liYw581giAlAGhvIDQWyJtzu04Vm4kz2uLEIKsrKzNLGJx7ZM9 +nj9KktzsJoauBwo1TUtnlRPHxdsPjWkfjX6yOmozG91Ep6XiIKFlGovb/FsDSTXHPL3jFteB2siv +Wr9rQ3PSA6zjxsuBuc2TvaL7vTqb/Mk3a216Nrt11rObdqxpSnX9s1ZFG/2T/DeyyKk9PW5Gcc9s +IopCuPQ7UHE8qQxu7OpCchdaAaOEFogf7TlqECmdXK6AOMWIYAON4xBGjbwJnTVrViubWKGZPetW +v23bMZ0BEQRi33nX3XH5HdY0zdLmFl/T3GI9FelyAdt2ZD0QeAbA79lmx3Gx5VCC1Y0Zyw5/qrrL +W877uxTZOsdtDIcS/NSaesMANEZl6cor1QfPGpz8ZUFvRWfWyiVe0iXT9W3nat3beOzT2x51n81v +baWZc3bqLQU5atDVzzpFMc8GENHdzK70vBnFaulUAF20XKDbYJtnksVdF4n7IpX2a6D0PHQ1s0hw +ES1A2Afci5Qw2bkkELafekJBHSpQx0FMv1j1GIiQNq/saVmR17iJYRj6mSWzZ4cy+81xCUm3RXzV +2OsxXiTu0dUHx2TRjHgj3F7bAt66k6u2POM2Tke0996ztgR8r0crfiylyMZYtzG2B7xVLHJpT37V +98bOQNKzbuOki4brVlMd6XmFIkhXu4goKCZH2iSbLLb+BdDbu7hMAeTzwo1tU5tJaxwQgW+QiBUi +jnezIYVSChs0ai9CHBctFARrW1I2fVCTc/hRT+1w3aA7URCXzfY6O61rWV6e2Es1XC83qTE8UeoN +/D+bzFTNjGy/XkJJk0xXTbZtSrDFkheyyqc92/3ev7l9085UTe9jl45mU0O00f1/C37rjE4fpXQF +WWx97GoE27oTQOc9pwjOCjsuEbtsqxBanNjPKO6vKioq1ise1dUne8MwcktKim5mlRPHRZMDgo1+ +365PanvPGvF43QFnPr9xVbxzSiS0k/54vc3Px7hti2M6AnY0p0W1cAGA86vWrarWPfXRHiealk0Y +OixVtly1nKvRvc0Tq7auZ5VTe855YePndabiqs2TRBwMCdQxPzcd6GFrFOkM9AHQVVd81wtHyVKY +dAZ9EISUd5wMjg47Lhw2e54p7YkfABKWqnovty1zgmXaES8dMIJ6maZpizVN87PMjeNYCtoiPq/v +VXly1bZrD0BDwt+5eGTcYE+fTJLtdezeikz7eyXT41CaTClRZclSHSqkE0AQCTyUIg0AfJJxkKtB +Scf3nr2KcZqr2AB2657m8V2cY81KgymvzPXi9FiMFQ0DvIGz3Z7G0mjK6xil06kGXV3XSzYOcRND +lcwTALzGKKX/6lGFIiB1tdu4ATnWR2yGEl6BTTsuFIEB9Hqo5D6E/CmBUsqoSGDU8p0LiaZpRnFx +4Y22FXww8o0ttmoEg48BuJBtdhzHjke0cVLvmoJtV6Rf8nHAe8vxT++I+vFhHVkydqx80LCaU5KI +eWqSZB/qIdZgWaAZquCkKoLl8UiO6BFiUk+FzCM6rk9jabalmHW0aLHFz4DuWyiqgu16PajfEb9k +kUtXGmx5NQB3haLoHM4onV/pYTNPQle9kr4nmrseWf91v/Ed0GkRKMD0hHemrwAmhSJ1qEA7u//B +MVdWVvEPSZY3uImh68EL5s6dy+zccI6LBgKgv6c15Zj02qXrLsv87q28IWmxGFcbN076dHK/q1df +nPX+pmlp9ZeO/UE/KXPnG0dm1M4ZldLwhyHJLaMGJLX27eMJ+NIVU2R50kx4Ol6zrIrOALfRg5a4 +2m2MULXYYrc+PUomziC3MQK29BWLXLqiO+7/Xb3Ejkqj9J41o0i6OCeZ0BpmQwGUAtUABnZ4keR0 +1kbnNyglLW7zAgAKkIULF6YCaGQRjwuNrKjjLdP8PtIinVJKTF1fji537XNc/AmEYpiv+eB02dz2 +yaR+Jx63YvvX0Rjng0kDzuulBm7rl/Tv0emyyeaI0ziRieNqYwUAtJgSm7tiIfh414jPjs+op9E6 +xSfaVMnu+qCMLjQG5ZiswdV15zO3MRTJTmWRS1s9a0axq8UIrNupdLUW0ApvcYTsYKObdPailKKp +qamrtZocY/Pnz/+P4lFfcBPDMPQRRUVFV7HKieOirbcS9I1Ib/rsjckDXN022xcFyIeTcm+ovjK1 +7sQ+O58bldZ4eLcpEjt5H5IF6nrH8y5T/NZtjFBp771ntVoMulXHiQL3P++Njb5NLHLpyo+tff5j +u7wRKAJR6XvZswpFSrpoMk16MxsKICAkq/OrhLBmCJWUlO/c5PSrkQUa9mYazj1V9U6VJCmis773 +skzjb0uWLOkRx2dx+4deiq4c5mv87PW83Ey3sd46f9DI9Zdlbjouq+ZvfdRA2P1o44120nNCIo7r +Qwla7eSdbmOEw4JgxnI8lgTiuOokQkGQhNYGVvl0JpDmazYcd5+FJIGy6ZzSRs8qFB1naxdXjKJ5 +YPOpdLo8Gp1X7zZqg9vDCTlixIjtgsBm0tOx6JFMAnFh0TQtKMtKESGR/zvaluXbvHHjEoZpcVzU +ZasB3zCv/303Mb6cml14TFbNd8N8zQOEyNuTxlVnfRhFgbp6/7EpQX2A1rmJES7LJkYsx2NJINTV +8jpKgU3jNsbk+7+p6tOg5fJXXiJOVJYT9qxCUbLWovNzNjORJR3LZCxCz+7iip9IFcL6BcvPz7eJ +IDCZ5ncc52AWcbjwLSgvv1eRZVe3K3Q9eHlpaelQVjlxXCwM8TUf8kl+v2sjee6nU/o9OyatvjxZ +tLr1+1Jnb0AE7iYqTEeA3OBrchMjXA7g6g5JPAmEuCsUAYz6/uCY7OUgAHUocdUDWSIupyQ7ihuN +oPFCHkAtLcD36GyLOcVNAFwtBqa3wodW4YZOXxIIPowkNiGkCYDr2zeU2u56gXGuSKpnkmGaX0S6 +scVxHME2jOUAotLugEtsXzX0WlbXqlawiOVVnQGqaOVQ2NkekQxOEo2TMmTjgAzFEFnvUCAABie3 +VlBgUWcnlLS1ckrOY4dn7D7fbc+7REBpx9+EQNwddUIIoPdpjHUh3S03sgCADXeHT1AQbGoUZSC8 +SZ84isq/VY8qFPcgrwG0k0XV5Dw6XT6SLDEj743UIt0KQjtvfeOQiNoKCIK4CbBcF4qWZWfcdNNN +3nvuuYdNE28uLPPmzVtZPGfO60E92NXMc4cM0xhTWlR04fzy8uUsc4umBGnL1K1npAAADnaf8eIm +VruIfxNH0yCc/P2AvIHelgWDk1qHsrzN21f1J380ue8NeGbH30K5/sup2YVj0uou7QlFYlccx90P +WiIOVElIQeet2ZgSSHQ2SMSEA1frKyXiIDfJyALQxf4H97Rx4yRZ+NzVa5fbGcmOdP8X1LYIfbKL +KwQIWEFnIieS8LRAPBuE3NbFZU3wGi9FEl8g5PtIntcWpRTJXu9kFrFCIcvS56pHWRPOl9BdFyGF +KKN37zxRFCN+QaeUwjTNBzVN6zZ/pyQBPnwS4v6DVk+naXBOqdryzNDH6od9XJs1s8GUmTYd7K8E +bwrlupfGDxk43Nc8vye9FHT2nVAQVz9nkVColhOTvpX/HRPothvrbBDXG3FSxKao9CZsq7e4M012 +WedFq1CM+4s6a2SRuYoWyO8BGNfJZQNB5XfodeK55P7gz6HGpjOU8wH6BLoqsClZTO5BRDN5okDe +B3BJJM9ty7TtGQAeZRGrK2UVC08O53pN0zINvb42WvkkglmzZrUWFxfebvsDEd9CNC0zXQwG7gbw +J4ap/YZhGJQQgkhPltmLkvi/pjgOYVIoCi5vW3UXJ1Vtq3xz0oAvjsqo+yRdNpgUBX29wYFPnD0s +9ZLX1ne6nm5YeuOK1O7S9iZ0Hf4RuS0UASBFQhYAV839wyEITrctFB3qfiOOjwiDGaTSpZRU9JIF +dy85FnX/+9WebjNTER6qoev1MaNg25/RAvlqqnX+5kYLkEEL5HtA6HIAXZ3n2wAYfw0j2V+xIbzi +Zsfsr2JZ1phEnY0yjODlLmuSbqGsrGKhIsmuzhEzDOO64uLibFY5dTQMiyDUiX+hCAdMWqpQ0lW7 +rZ7jzBVbvlzTnDHRsEUmf5Ue0SKDfP5OP/C+cf6AQ4b4Wnpcd4bO1mZa1P3fWXZSa0w3uflEy/Xf +tCC6rIAiZFLR9Q5xVXA6PlSDoVzB7/qgBZOSqCw1i/+LehSQSut9WiD/E13PzPUB8CCq5VI6Ey+A +kH8BdAscsQGOnQlChkCgvwfF+UCIbz4EJaQSEZ8AU1ZWtmPOrbc0mZblusO6bVuqZRjXArjPbSzW +HMvZb840FlX1QmJbn0Y6W+c4jkgdc0WU15QzWqztbrE+CzZ1XDfZBQBC2JyU1F0c+8zW1769pNfb +h6Q0ncEiXpJsnw5gUUeP90sK3qVE504ZbErQaotO0JaDQUdo1B2xwXbQaFGh1qLiLtOmjU4HBZ0q +4rAxaXWnRDp2Z6t0DUdoAtBF/93OeQV6HIB/uokRqucnDh3gk7a4/ptuJU4zi3zCFXTINrjcEOiT +rZjcek6TjaPcxjCpGJUd8T2yUAQAELMAVD4KoR2HNggUN4DSG/b8v/Yvc600jH17AChdTiqtDl8Y +QyWK4irTsk5yGwcALMuchQQrFJcsWSKvX/ej6z+K7mLBggWfFRUWvq8HA2Hdnt+XoZvHy4q7mcmu +hthTiLqbULJtR9A0LUfTtJg2Bd4XoRjBJpK9XxWKALBTT7t6mK91E4tzkn2i1eGmQgqQnWpwnOtB +fmE4Aqp1747dQfWDFlt6vdaUnz//+Y0NiGAF0Cd5/a4DEHGhCNrxgkubCrUAXM0IqqI12s3zw5Ei +Bsex2GTUHPDFpGl1WwYVN7qN4RVi00FEJPQwtzEMW4hKj824f/qPFrIILXAwGbE773g1PNYfWQQS +ROF5FnEAwDTNAVpp6ams4rGwZdPPN9uW3W3XvURC9XguEMTIj8KilMI0zP4sc9qXpmlOZ42Cw+GY +wRNZxIkUpZTJ8ZUEiMssSDydUfXT5u2BpLUsYiXLVp+OHnvrgn7HZau66920zZbkrGrM+OebdYNy +Bz7a0O+Ip6unnFS17dE9RWKcdPJ3ZFBS7Ta8KjgxO541WbF/5zaGQwn8fsTlQ5duCz+6jeEVrcEM +UumSKlrD3cYIUjEqxw322EIRAMgS8xsQUhmDodZClM8m94LJi5Np04cJYbMNkFIKv64/yiIWK6Zl +3RjvHGJN07Q6VVHL3Kw/dbvRpCtEYHNUl23jBBZxIuU4tqtbe3tJkhjNGdyEVWsqT7OIIxHH09Fj +GYo9xe3nku16Uv37db0OOvzJmkvGV63tFv9WuiW5LlwyZT3a65X/K0UyXd/50R0Ru8Z972eRT7g2 ++5Pfdlx27EoWzXRt3Lio333NkE3XayH9lvRvFrm0FfNCkc5EMp0unUELpGJaID9FC+RVtEDe0Obr +KzpTepYWKHfSGcrF9Fo1oltJdKZ8GSidxfp7aOMbEPNkcr8/rOP6OrNw4cJGSVbWsYpnmcaAuSWF +17CK58ZtJYV5lml13oOyh1pQXn67JMuuZxSiRSCR7dRvy4EdtybhJSUl/R2HzS7NoEm3sIjT3VQH +vc+y+EgioOPj03yi5WqmqtUSnfV+32HjV2xl9jq5lyO4O/ats/rX78gfu4oNIEMxpFcuGMBkaVJX +0iT3t7mDjmBpWnw6CEx9ae2PTZbkauw0xSKHZ/50NKuc2vPIeQcNzlR0n9s4LQHxbRb5tBWTQpFe +iRRaIF9BC+R3QeV6CORNgCwAMAXAYQCGtPk6HJScD9BbQegTcJwfaYG8jhYod9JrlZCOpqMF8uWg +eAQuj0zqfBA8Cts8jiwC8/VYokRcr3XcVzBoPjB/fskgljHDpWmaRzfNh6M9M5bIFFWanAgdqdtD +ITBZCG1ZzhEs4kTCcaybWfx+EUIwePDgkFtn9STnPvfz6mZTdv3GLgkd/zt4JSfXTeytQd+XJz+9 +PSqFvEyoyz6FHd8N2knpB7bLGS4CYKAneIOrICF4cfyQo7I9Aa/bOLojxq17AAFosynXu4tBkasY +U1jl1J7hStO1isuN4S2mRD9pGrqKUUq/EtVCkV6LXrRA+TNUeROAh7Gnt2Gkn9aGAfRWOPQ7WiB/ +QK+VTutw3AL5il/Ga/v91YHSIgAbI8xhr9UQ6OlksXkFWYqoTKkrirdSEERmPZFs25Jam4x343ly +hh4MPmwaVnK8xk8E8+aVvy+rqqsjJKNFFEnEu/X3ZVuWb+7cuVH9BN4Rajl5LOIIgmBNnz6dya34 +7oYA1G9Lrl/XBNLxa41HdFx1dag31CfcPL8zEtw1tO7sc0p+1da6WkNx3WEgy6Of5TZGV/ont94s +MlgBFbSis8EiVC2W5LrnZIaqn8sil470UYIXuI1Ra3h2au+9F/E6+M5ErVCkM+XL4Mg/AvQ2hNpa +JnQnwiFv0wLljba3pekM+UoA/0C7RSJOJ4utCuw2DwTBFQB5Awj5iB8bhLwKIkxApTmGPGC9w+D7 +6JCmaYasSEwLCt0wDigqKnyTZcxQ3VZSOFnXg1PjMXai8XiTJoqiEJU/aDcEInzHKpZlGOWsYoXq +jrlzjzItcwCLWERgM7vaXVkOCUYzvojIN7MFbRFbNgv/YJnPvhSBumqH0lWvjEZTcT1Tna0GfF9c +lHOd2zgd0TQIud7WCSxitdjuCzU3Gm35Vbcx+nsCg16/YFBUlky9eVHu8EHJrUPcxmmw5U9Z5NMe +5oXinubU0oug+D8AvVjHbzPamXCc1XSmfBMFCJ0pXwWCB9FhkWh+DQCkCgZZZD5KKo2zYJtZAD0D +oIUAHgKlLwB4+5f//QdAbweEiRDMbLLIOIcs0l8K57B7V98dhKtZbWrZy9T104uL5sSkB9deWsmc +EwJB44lOP2rvRzRNq1Mk5d5459EWJWD2wcQwjXHz58+P6VIHv2E8xmpZg0CE/XJ94l4WotO4dy9J +oBEvCfLbkpH/6dao5aeIjqtCkZDOfwn9tvyJm/h79ZEDf6ZRaq562g/9ZvVR9a4OlwiJ35Zcr8t0 +Y7ed9IhF3ZU6imCTPp7gXYxS+pVcIbCURT/ROt0btfd1poUivU45FJC/BMh4lnG7oILibhTIn4Fi +KX77PdXuWyS2RZaikVRab5NKayGpNK8mi63zSKV5xi//+0dSad1BKvUXyQOI+XFzFRUV6xVF+YJl +TEop9KB+UdGc2Z9rmqawjN2e0tLSCa1B813btntuz84IzK+omC3LckIdYUiI+Bar9x3qOKS5qek1 +JsFCUDpnzo2moTPrd0ZErGYVqztyKIn4jPIQ40dc0dtR/KBOAdJL1V3N7tAu/oaqLeXRrq4JxcAk +f+aXU7IjPgWsI6+ePUwdkdyssYrXaipVrGJFYnzVT5t36R7X6yQP8DXnPzThwBQWOe31QX6f44f4 +Wsa5jVNnqMYHh2xi1lavLWaFIp0unQGbfoI9m1Hi4Xf4zfdDdsAmJ3RUJHYHqjfpj6w/MlJKoev6 +7/ytzdW33XZbh2s93dA0TSguLqwMtLY8z4vE3yKEUFUQL2V0WiMTCxYs2CRJIrNbjpZpjCwumsN0 +U1Z7bisuPi1oGnez3CRFCHF9u6qbi+pvpuWQiJdeeARbidZM2vv5A6b0kt31dyS080L2zGVbPtyl +q0z+zkamNt347vn9mLajys1sfLOPGuywtVE4ag3VOHXF5u9ZxHKj3pRd1wDpkikdk1rLrBhblndw +8nBf8HWVwemGO3XP59HcWc6kUKQzpeMgkOcAJNJGhVoQ+gey1FgT70Tc0DRtteJR349GbMu00lub +m94uLpzz4ezZs12fM7nXbSWFkwOtLTVBf2BGPDfPJLo7Fi58TVY8TGeM3RJFkdk6xV9mrwuKCwsf +ZBWzrcLCwqmtwcAbjsPu6EAiEKoo3mdZxeuOCIluoWg6QsSFUrJkk/fy+h3PMp+9+qt+zW2Mrl7x +CEBrDeVzt+MAgE+0hIMzmt56O2/gKBbxPp+c/eDBKY3MWu/U6J4fWMVyY5vfeyeLj5EHJjed+unk +fte7jaNpEA717PwsxxNwXTM5lKBG95S5jdMZ1zM99Fp1BBznRQCuewCxRc8ni6yobBWPNYeSiaIk +1diWxfxWMaUUwWDwBBCypnDWrDWSLC4dMOiA+8Pd8VleXp7R0tJyq2XqV7f6g3325xY44fB4vRMs +09jqOE702jiFQRDEFQCOZBVvz+x18Oo5s2ad7ABn33nnnUwWtmualhwMBp4w9eBE1r9rkiRv0zSN +0dnX3RSLe6OdCDpiNSLc5EhAkaUYGoDTWeb0xZSciiG+OvfHPzpd3xrfHvTddVBK88ksDkPKUnXP +GFL71XtTB44f99TmtyKJQQGyamqfFaPT688XGN7ZbzaVh5gFc+HMZ7e8uOOKlECOJ+iq3Y9IKMak +1f3twyn9Wk98evvDkcTQxo2T8tZ/9+VBKY0htfrryvagt+6Uqq2vs4jVEVeFIr0SKXCclxH1TSsR +uZVq+JjEqdEnSwsXLmwsKSqaE7Tte6JWgFEKwzQOMkzcvXbNf/46e9attYIg/iAQ8gMlZLUsCFtB +aQsAWEBfAehLbbufQ5xjHYseXLurJtVxuv2POuY0TdtZVFT4gB4IRL0vWihS09MfCOrBMuo4zAoF +SilM0xhOBGFd0exZn8mSXHJHWdm7kcSaPXv2SJGQ+a3NTeNtOzrHQBKBvByNuN1KlGcUg464AUDE +a0qH+FpPfefCfsedtny7640hFCCrLsp56OCU+isEFnsHQ6i0Tl+++eUt09Iac71+lz0b9+ilGOrR +Ys0bqy7OXrbWkK/Irwp9s8/HF/U9aYvsf2ZMUn0Oi1z2ajAVy189YjHA7CwKV2p075s5nuBEt3E8 +ok2OSdv90HcX975orV+dfMFz20Jea/523sBRw5JWvT0oqZXZDmYwSK8AACAASURBVOrtQe+D0T6p +2N2MoiovAuD6fMJfGABaAaSAwUwnQCZgp1QCWPPcx4q/BeXl9xbOmTXd0I2oH1BOKSWWafYGzJMA +nAQAUV3Zvp9TVc9NjmVdapom6zZSYZszZ05zUeGsb/Wg4fpEhrao4xDdMI7VDeNfs2+9JUiIsFEQ +hO8E4FsiC18Si+7Y93pbEPpRSg8TQEfZjn24Y9kH2KbhtaI4W00IoR5P0u1RG6C7cKJbKDZY8qsA +zon0+V7RIqNTm955fWLfM896YceHkcTQxo2Tzuqz5sbtSYGSMd5aZn97of521hjqg7le/62sxvWI +NjkstW7yYFOe9P0lvT+tCyqPfNbUe9msN1f/ZiPHUxOHDhjs9V+TrQYvG+CpHdhZc/RI/ez3vXNK +lPr6RWJr0Hfj0KTmCT7Zcv27LQkUB6c2njbIK1V/e1HW29up70+/f2pjh8vcnjtvwNDhvsDdg327 +zvWJFrNlMrt0NbhqXf+5YH/mx69EXJDRGcr5AL0k4pEJ1oCSZ+HQ52CaP5KH0QwAVIOA3Uk5MPUx +EITJACYCiOxTFyFz6Uz5JbLI7BG3oHv17nPkrurqbZZlMvkUyiUGTdOcoqKiK2Faz8Wo81KnZMV7 +hx40lkdzDMuyPNgzo3QQgAsT5ZOIrKj/0TSNSePxbk2IbqG4w/H8U3fEB1Qh8jMFequ65+Rs6/01 +l/b+utpQl66pzXl6+tsrO5xauf+0g3qNSNOPT1X0E9Nk/awc9YuR6bIRtyUfTUrS3Dqj9cZMxWA6 +M54mm1Ka3HgiUnDikb3qHr7iKp8edKSg7cCRBSp6RTspWdoqSQxasnREt0Xa7Eh/jNoAETjn2Z83 +fXNxnzdGy/XMmpUny5Z4SFrD70fSxv9svyKttd6QfrSotIGC1tuO4FUk+4AU0RyZre7q5WF3fsZ/ +bWxNfmD6ypVRPxggokKRXoMkEHpPhGP+BEKKschY1l4/wj23iv3bAWwH7FfpNUiCIM0CIbMQ/jpI +GcAiAMdFmGtCmTVrVqtWXHxSi2N/lShr2jg2ysvLny+aM3uVrutj4p3LHXfcsWLOrFnVpmlkxzuX +WJMIuSneOSQCtt1bfyu/6qfGny7P2HJAUourBuke0SYHJjcecSCw+Ki0usXnXZWsBy3xv6fKiAKR +CKjkFSwlRf5ZjGZxtFdXu573OuXRjcHPJ+fc87vM2tnRysUj2PAotgoYrnZyh2tDq+/NaB2x6MYG +f8rlg5Oad6RK7Gb1gD1rF/t6/L6+HhwBICZHmG4PJDW9Wn1QYbRnE4FIdz1L0nUAImmm+w/sNkeS +RcYzoTatJkvhJ4utP4NKBwIIf10TxbG0QGXSYT4RaGVlq1WvOpMkUl8VjgnVmzRREMWEWOgpq+qV ++9vvmKIqa+ZXVMTl5KJEQ6O8RhEAduvqoyzjeUULfRRdHZjkz9j71d/TmtLP4/dmKEZMikQAe3bb +hOi1kTuLdgSTmqOZTqzVGqrx/e6ci+KdR3sueG5DzTeNmX+L8l6tqDMdAT+0pF4WrSP72gq7UKR5 +UEBxY7hPA6GlpNL8I6lCRLsJyeLANuw2zwLwWPjPdoojGTNRLVhQsdTj8Vbsb2/kPZ2maZsVVX40 +3nkAwPz581+VFTkhWlvEBCFUVjzT4p3G/mSjfeKfaww2/QQTCQ1xRhEANA3Omqa0q0123Z3iyqEE +G1p9M/Pf+D6u5zt35sRl225Z15L8U7zzcOOH5rQ3z1i+5YVYjRf+b2eWMgkg/cJ6DiVlZJG1IOyx +2iBVMFBpTgPweJhPPZpeKx/tdvxEsqC8vMjj8d7Oi8WeZcyYsdfIkpQQ5wynpMqniqK0X7SJ8XjV +/5s3bx6T3nY9ghP9bhH5VVX2lkDyo9EeJ9bCvWt/6orNy75rSn8pKsnE2OqmjOePfro6IVridIQA +dEtj2nENhtItX9s2+n1bnh9Rc3Ysxwy/UKS4NMxnVGGxMTfscTpAAArbvAoUH4T1RAfTWOWQKBaU +l9/h8aj3dudiUZSkBNnGkBjy8/NtxatOT4R/05KSsmpPkloQ/0yiS1GUrYrivSreeSQSyrKZXide +HrHz2i2BpISdfYpQ2D+7L9bmTtoSSKqPRjKxsq419bPDn6w+P955hOL0F3+uXtnU69wmU2a/wySK +qnVvy4/NaUdH8xSW9oRVKNIrkQLQcI58a4ZkXhvqesRQkaUwIQp/BBD6/XlKz43WsU/xtKB84U2q +N+kKQXCxfTBOVNWzRBDEbn1yTjTMm1f2dKLc9p03r+xhRVVuT4C6NSpESWrwJPkO1TQtIdaGJgqC +2LwRaRqcta1pU4K2GP/t/nE0feVK89umzMNrGB3tF0sUwJrm1PdHPFZ7bLxzCcfpVZv/v71zj4+q +uvb4b+1zZiYTwjtBRER8XCvWJ9bqVajvJ+1ttQJerbSoH4d5JNS2+NY7VyEB8YqdmTNDrK+KWgnW +R4veXh/VimKLL0TxiS8EhCQIhIQkM3POun/MTDIJk2TOzJlkgP39fPL5sM/stffai7PP2Wftvdd+ +4e3m8vN27CGDxcaoo231ziHHn//k19/2ndtazHkUberJAEycDkKLKIgGcyplWbLW/inMTEETjYXH +XvAYhANBdXX1Q05HyWRVte3qO3dx4ChxLq9ZsGDWQOtRrKg2x4+FKI6NLTULFt7ucA5aWAxeTiux +qWrT0GHDj/H7/dsHWpdig7n/PBZnL1v/wpqmoTXGXnPaZ257xqc8+eXXaxpHnrItZi+a2IN90aqr +xuodw+ZOeGTr6QOtSy6c+fj6l95qGn7OtiKfht7c5mx+r3nosecv27BuIOo3N1BUhJnzNVuhRv/H +nDomIWHufEPmkwukyYBzR03NG6VlZQc6HI7VxfxCJwKcTmeoZv78nwy0LsXM3Llzv3Q47H8aaD1S +VFdXX1dS6pxBe6DnOhM2u+1dZ9ng/W+55ZaiC+FRDPS3e++kx7fcvHr7sEXxvWNTR87mO+cvX7/7 +fsPwid+2lxb2qI08YQBftpR983bDiIkTH2uwbGnZQHB23caXP20bduiGXc5+99Rlw+ctZRvf2Fhx +6NlLN346UDqY7JU8IeusRC9TEAVdlE/h9nVgvJ+9AAY8Rl0h8fv939UsuPP4ktJBM2w2pei8i0JR +Yg6n86p5NfPzPlR9X2Dc+INnKqq626kKA8W8eTVLSgeVHW+z2TYW88dIbwgh9JJS58IFd9410e/3 +F10f2Zc54fH636zeMXxB254eIjbPUfZpz2x4/8XYQQd80jz0vWL0sm5pd7a80VDhPeThbeMmP7Xx +vYHWxwpOfnTjhrF/bDrgg6ZhS4tlGUSUBdbsHLbskUO2jbv4+c8H9BAAcwNFxqHZ5+XnzCqTE4Ke +zTov8/jCKVI8zJs3b4lz0JCRTmfpnxRFLYppDLvD/rHdUXJQdfX8nA5S3xdxuVwxm2qrKqZB2R13 +3PH+goV3jbWXOG9UFHWPWU9FRHDY7a/bS5wHVFfPL1iAY0l+nPj45hve3DFyasOeHTYn74HGjCVr +Wo5Y0njcqm2jfr6pSDa5fLOrdOsb35XPGv1AU9mpT2wKD7Q+VkMAH/1ow6Vvt40Yv65l8MqBDFm0 +qc25+b3tI0899pGGaf29cSUTJi1BB2SflfvnS8OAiXoor1MA9iT8fn/bvJqay9qi0TKHs/QeRVGz +PiTeSlRV3eYc5Jw2f8HCCdXV1UXp2i9mqufPf0C12T8baD26U1NTM3/Q4MGDHY6SuapqK4oXWSYU +VY2XlDj/anOUHFpz58JJ1dXVWwZaJ0nv/OjxjU/8LXpI+fs7hj23K64WhXfHDGzhzP2/L93w5B++ +On7Ue00jApvbnDv62xituoJ1zUPWrWwc5TnwjzsqTln6bW0/q9DvTHp40/p/e/i7U1+vHzn5k51D +3mmJ9c89yAA2tDq3/3Nb+W/GPNg05oePb1rZH/Vmg8kj/Lgs+7zKZjObknOGjG9NbGY2of/eQTAY +bAdwbV1d3e9Wv/POL3XDcBt6/Dhd13M+57svSBDbVNtaVVEDqsNxv9xRmh82u/2n8XhsLRtG8bgW +Afj9/jiAWwHcesstt5wej0avNwzjR7oeL2UemPc7EUERol1R1PdsqvqwsNvv9/v9e7J3ap9kxpI1 +LQCmvDD1kHGj7U33H+BsPX24LVqwZxYARA2Bze0lW5vjti1HDt5xZCHrMoP/lVfifmA2gNkrph/w +41G21ptH2qMTRzraTWwszZ6oIbCprXRzfbvj6S9aB1X/5zOf75PreM94atNrAE54dMq44YcNilaP +Lm2dNtrRNsIurHudMYDvovb2xnbHqg0tZXee/dT65Sjsir2cMNvxnFnnbG/vn9hYQjTCyPKlxJy9 +/nsZ06ZN0wE8AOCBuro6ZfXqt6cbOi5hwzhR1+P753N2NBFBUZUWAfEhqWK5w+G82+/3N1un/b7N +3LlzP7rphhv+2tbWWrRHUc6dO/cVAK8AgP+mm45qZ/1ysHGGHje+ZxjGEGYWVg8eiQhEZCiq0iRI +fA7QSqGqD8+bN+8tSyuSDBjnLPtiPYBz6qZOVcaK164ebm+fMcIWPW6EPVaaz5F8Bgg7orbYTl3d +uktXvmiO2VZs2mUP/PQv32xaOXWMD4MRzLlwKtxJ2ZOXblwOYDkAvHzZuLMrROs1ZUrsB0PU2Nhh +9pjNxOmBHeyMq0ZTzL6jOa580KTbnmuIOx+asuyrwh8gvIdw+bPrtwFwA3A/edGho8bYW2aNcMR+ +NlSJHT7YFh3kVLLf3xdlgW1RR3NTTP28Wbev2NrseOCcv3z9LtACoHjDiZodKLYDKM0qZ0nJYKCt +8C2PG0MgsnS0EEnPAjoGjY8l/8DMdNtttx1jGMZJrOvHMnA4sz6GGTYwO0FkAwAy2GAhWojQLoAN +IPGhIsQ7jtLSf+S6e1QI8YHNbh+diywR9bjRQxHK88Juz2uXO6m0Kh95K7GXlEw3DONlApfkUw4p +ouA75/zV1R8AuLHLNb9/jBFrm6wbNNFg3h8wKsA80mAMA6AApIK582OFiAGOElGMGC0g7ABoK4g2 +qURfq0TvtTGvrqmp2Vro9pghDvHJRzuH/CPfclqhvmSFPrmyvd3+xEfGkLzi4sVY7ASs2S80bdky +HUBt8g91FxxWceCQ1kvs0I9ShH6QIrjCToZdJBdTRQ2KEdDSZijtAFoMpo26Qd+0wv5Va1z55IOd +gz+f8/yajM+Ptrjx/gdNQ3Pu+ztjdnOHQeTIGY+tfxHAi6n0C1MPGTcIbZOcavxYmzCOEMRDFcIg +QawCQMyguM4iFjdosw58GTPUj75FyasXL/3iU2BAViahxVCf+2jnkJH5lBEz1Hqgf/wSFz/1eT2A +25N/8J9+ujp52LqJQ5yxc0qEcTSDnIKMMubU7CVtixrKRt3A11ESn2zShz87bdnaPc6JYmoqi922 +egAVWWU2cCLVxgr+Zc9u+88AfirL7O9SJDaxoApJJBKJRCKR7CWY3dbTmHVO6q+NI2Z2MlNBgn9L +JBKJRCKR7I2YjaOY/e5L4nNN6pIbhAuzz2xCf4lEIpFIJJJ9HHMDRSIzA62CDxTZgzIwJmctQJAD +RYlEIpFIJJIsMTtQXGEi9yHsVi4wp45JWK0EYGZxf96LzCUSiUQikUj2FUxOPUdfA8xECRe3mSs/ +e/hKDAboNyZEtqEhlv1xfxKJRCKRSCT7OKYGiqRhK8x55U7mWbYrzKmUJQ7bnQDKTUg8TcuQfcAj +iUQikUgkkn0c84cZMh4xlZ9Qy27bCabr6U2FWTYXgFkmpR6zUgeJRCKRSCSSvR3zA0URqwNgJsit +E8xP8zX2I0zXlQF226eCTEfN/wj7xf9uRf0SiUQikUgk+wqmB4oURjOIF5kTorFQ+E32OH5itr50 +2GP3A7wUgM2cIM0jv5m1lRKJRCKRSCQSUyezpOBfYxiito/B2M+kaAzAfVBscym0a1PW9XnsEwDc +BWYTMRNTwngfo2MTyY+4aVmJRCKRSCSSfZicBooAwG77ZQA/mqN4Kwh/gkHPwYi+SPdix27l/xrD +0GY/F8Q/BTAN5s+lBgAG82RaHH89Rz0lEolEIpFI9llyHigCAHvUJ8F0UZ46xAGuB9NmEL4DMATg +AwDaD7kNDtO5myKx3+ZZhkQikUgkEsk+SZ4DsfgMwLYKwIT8dKAxIIzpvJTX+DXF39EYu86KgvoT +TQttJmQ/pV/f0Gjz+/3xhKz2KwI/mPyp3eP1dQlGHggExqqK+CaVZtBkr9f7Wje5jDDwqNfr+0X2 +7TBfZi8yrQA2gvAKMy3wer3rClhXjzJmYGZarGm/YGIPQN8DUAJGAwTWMNPdXq/35VzKra2tLTVi +satZ4CIwjgIwFIydIHwMwvL29ljk2muv3d5drpf2xgjYwqDXSeh3u91Vq7KU62xrH7Yl4CG31zcz +XSashRoBjEzIJ+7DbNofDoeHE/MNDP4JgPGJ4rEVwAYQ3hEGnprl873Qk3wB7JfRDrn243A4eBmY +kjM19JnH6z28o3xmimhaIwgjkhXWeHy+m1K/RyLBM9mgl5LJrW6Pt4KIOL2ecDg8BWwsT1M6CiFG +ezyebZn0yrVP9iGbVr1lz5U+9Ulh1gY91GsAiDKwgxhfM+GfQih/cLvdH/Qhu9tzOdd7si/ysb/f +7xcVFRUXA3yZAE5koCLZ5q8A+gcDD3i93jczlZlPe8z279raWpsRj73NwNHJS2/WNzSe7Pf7O/Yk +BAKBITZFrGVgbLLVz3q8lT/Op14L39MZyeJ9FdcNPqiysrLLEr5wOOQFI9S1LBrs9Xqbs9U1E+Z3 +PadBYTRD0FSY2wXdH3wFxXaFjJu41+AEcBgYVxP4zWAwePBAK9QXi8PhO5jwMEAnAxgOwAnCODB+ +LICTcipzceBIXY+tYcLvwTgdiTiituTA4RQwqh129cNwOHyyiWJtiQcoT2dDvBEJhS7NRbfeYOAK +TdPy+ZgEACxatGgY2FjF4OuQ+Dh1InEy0wEATgLDrRN+2ZN8gexnKcwi7fQr/rdIJDIqldI07ciO +QSIAEE3qImyIzuNMGa93HyQmK+hqH4KdDCOX//Ni65PZ62ONDQSAEgL2A+GHBFSxoa8Jh0Lz/X5/ +1u/VYrwna2tr9x81qvxVAi8j4KLkAMuBhI0nADwL4L9a3Z5c+rfL5YqRwVcCHe/6EysqRlam57Ep +VNM5SMQOEqor33qLAFWIriECmZmY4StIZfkWQFp0Lbts50PgJQBDLNApXxqh0wUUyX6zTDFBhDBz +px0FcG7H1xJjPROWdROxeje3zsA9GTR7u5/LjIMxB4ANRCcAPD15fZgQuAbAjRbWZXmbGexJS1zL +RMuZeYxCdK4BmL4377vv7hHRNvG/IIxLlhkF8CgTf0xE48GYAWAQQPuDjeW1tb+f6HLNXt9DcSnb +AsCBIFwFYCgAwYRwIBB4qqqqqj2DXK52UgCeB+DiPhvaCyV2eyWDD0smtzGwBOCNBFEB4DCAz+pJ +1mL79WmHXPux1+v9JhwKre/QMx6fDODPAKAQTWKkj/34xLo6v33aNH80mU4/9343D+2iRYuGIeEx +6QITzwAQ6aGt6eTaJ4HCPFdM62OBDYBkW4hhB2E8gLMAlAIgEK4fVV5uA9DnkieL78msdN79clf7 +33333U49HvsbgGPSLq8E40UmbiGIg8F8IQgOq9uTa/+eVVn5VjgUuguE6wGAQHNra3//lMs1e72m +aacw2N2RmfE7t9u9MV0+l3otfE/n0S/omro6/9xU/6/VtLOJYEkYwu7kPVAEAKqNvcVe+ynQjb+B +aGzfEgVjHaCcR/e2fTGAOuSFx+O7PT0d1rT7AD4aAIjwmcfr+12BVYh7ra8jlzJ1j8/X0YHC4dBY +ME5NpOhAi+uyvM0MRDsWUAjjA6+nah2AdQBezaW8aNT+244HMMDEfJ67svKV1O/BYDCiEL0Fgh3A +SD2u3gbg6h6K62JbTQuuItDjyeRwuxATAbyRQS5nOxFwUSQS+GH3qW0zMDCxs0D+rddT2WX6JhAI +OFRVHZ9J1mL79WmHfPoxE1YQcDkAsEKTkBwoMpDyIK5B4kVe0tBQ8QMAK/1+v8pAp5dGpHsmE5TY +7dMZnJz25GcBOglAOUAnh0Khw30+36e9tQm590mgMM8V0/pYYAOgW1sikcgoNownOgbqhGuDweBD +lZWVvR4Za/E9aUrnnigpsVeBOweJxJjt9vkC6Xn8fr8oLy/fbbCdb3vy6d/OQYP8rbtafgbgewDK +9LgI19X5L26s5z+AEmvZCHjJ7fPd1102l3otfE/n0i+aAAwhYL/GxpHTgMQhKIZAVfI7sgkWO+3y +mnpOh7ToWgjlDBA+tqpMk7wHUs+kyJ47SJT0goE0Dxd/03PGYoHv7finIe4PBoNjesmcRXGY1vFv +wrPpD2AASL6UHkoTuDjbKTAh+Mv0tCGMQbkr2h36DKmlKYaozrOwjiUuzHTJ4sWBI9N/rKqqavd4 +PJ9klCyg/axGgDoHeYw0LyFPSlziJQCSXhFjEgBUVFQcDyD1/9aqKMpuHgkGz+j8t3iIwHWptEI0 +o3v+Pim2PpmFPpbbAIDb7a4nIS5BYp0kAJAqRN/rLovxnjTQaQPG37sPEgHA7/cbPp/vmd1k829P +zv175syZbQy6Eh2eO5rS2DDyeRBSZbRAKD0NsnN/rgwMnwFYCQBg8gFAOBw+BIwLAYBAva5/zAVL +PIopKNy+jn+F41FqWwBGlZVl914xAlBi11Ewlmm6bF/FEdZCu69RylWO+CKPp/JpS3XpvUyhadol +AGwAnwDgjOT1JiLlDxbXZWmbNU07g8Cd60cI4xSiFyORyOlut7seACKadiuDfwoABuM8n8/X4zrf +Bx98sKR1V0tqagTMvJu3CAAgeAWYrkmmhpeXlx8I4OvedA0EAmPZELekX2NWenoo5mAnbmLwvQRa +yMBZ4XDgbI+n6sXedOoRMv4MpqsAgIALDV1cGNZC2wG8y+BXFcV4dNas2Z91FyuA/QrRRzrQmV8T +nfv5jtM0rUwIMZQNfTwAECmvAcYJYFxKoEkA7kSntxEAr3K5XLH0MjVNOwzgU5LJptLS0uVtzc3f +QsADAMx8BTPfmnFdYye59kmgMDYzpY9FNsiI2+2uD2va6wCfDQAG+Pje8heyT/dAn/YPBAKOtIEV +mGj5bvl7wJL25Ni/U3i93pXhcCgAxq+TjTstrZ03ut3urzIK5llvnuTULxgUosS9fJKmaSfCMC4F +QQBoIV1/kBUx20olLf86oYfQRuHYbDBNB+hbq8vvxhcg8R8Ujs2mIOQgce/CllhMzY9RYr0PEfCq +bvAkj8dTtF7jxYHAsQRejsQuwa3cOYU7gQ39hfvuu3sEADD4fAAnADjc6/V+11uZ8R07hqaniWhL +5py8OT0lhBiaOV/i4RTWQpzcBd8xjUTAE16v11LvUGlpWQgpDxjn7lX0eCr/F4zrAOxKuzwMwBkE ++i9DVz6OaNoN3eUKYL+C4vV6PwQjdU8oCvO/G0Y8NRBsVRTlbeYOr+MpzExd1icSZXhJGx2eIgKe +nDlzZtssn28lgK+SF8eFw+HT+1Ct2PqkSX0ssUHPMNenlT+st6zFeE86DaOLzkRGQ7ayVrQn1/6d +jqLYbgbh8y4XCa/X12/VepKxot7+RlXVJwD+FgAIxg0gXJn4hZawzbZbXOp8KZgbmxZH66BHJwA0 +F0CPYQdypAHEc9Aa+z6F2zPuvpJAB2NB+h+Bw7nIgbFACM5m7U5By2TgByrRYX1ky6Uuy9qsK+K/ +kFjYDoNxFUDnAvzP5M/HtLfb/0/TtElIrScjPN+XB0MdOrRLx2fmHsIy0Oj0lGEYZh4YBgOPNu9q +/VUveXKy08yZM9tASK3pOTESDP7chF5d8Ph8C9ujsQMI9AuAFiOxXi9lP8HgeZqmHZcuUwD7FaKP +dGpBxCB0HBJgJLyFiYEi4V8ulysmhEitdR1ZWxucQEitzQNI5y4bWZiZCHRFx++Mx9Lqeazzerfd +wFmQZZ8ECmyzvvQppA06IOrYoc5Ar+Fs+qlPp9On/VuF6KIzs6jItnCr2pNL/07H5XLtYqYuYfEM +A1Xp4XIykW+9eZBTv3C5XDGCqE2k6GIkP0wM5lAvYjlj6dRzdxInrkRv5StxJxy2ywFMBXAaACWH +4nQAK8Cog4gtoTDyigu0DxD3+HxdvoIScRTJ05NAT3KF0CUL2j1eX4mmaaMJCAA8FUApEx4JhUJH ++ny+nqZfcqnLsjYnY44BABRFecvtdjeHw+ELwcYrAI4h4AcAv4zkRxozZdjx1pWZM2e2hbXQOgCH +AQAxnZoxI4tTO59t2N7Y2NiTZ7Bz17NAjJm2CCHe8HTbDZhJLlc71dc3PjCqonwOgMMMQXMpt2cA +ACAZg+3R5B9qg8EjdEErkAjFIYiMyQBWp/IXwn4F6CPddMEKUNLTS5hMoOHJX14DgFmzZq2NaNp3 +IIww4uIqEFKDFD3G3GUjUiQS+RESseEAAAbh+bAWStXTCeHnCxcu9M6ZM6elB61y7ZNAYWyWtT4W +2iAjiQ0tesd9JUDv9pa/APdkX/Rp/6qqqvZwKPRhavpZgKcAWJRN4Va2x2z/zkB9esIwjPqeMlpc +by7k3C8MoJaAmwHYAACMv/t8vrWRSGS8hfoBKKBHMR16ADspEltMkdhZiMZGgekSABqAlwF8g65d +NQlvAuNVAIvBNB16bDRFYmfQ4lhEDhL3Hbxe7+aWXbtmojOkTKkgvr03mYGEgWjHv1mfAgAej2cb +CeUcAKmvRDWZWcs20DQ4LdwC4SeRYLDLgzgRp5BndmbHk718Resen+8ej893j8fj07xe7xPdQ0ZY +jd/vjxPjVgAg4Aj0MTWXiUgw+PNwOHxM9+uuysqPQejQn1jYdxO21n6Fp+uu5ZORDL2R8hZ28ToS +runMSmuqqqqaupRlGNl6ycrKnM4+QxgVW5/MSh+LbZBO1NsHNwAABE5JREFUKBQayawvRSL+HgBw +3DAe6VOwGO9JgQ69GThL07TdHAvMTOFweMpusnm2J6/+nQcDVW++eL3ezV1sLjhYqLoK6lHMBN2P +74Don5EM+ZCCf4dBaIEdKnQKoqkHcUnhUcOh0PwM1zenh6LoT+bMmdMSDoUWglJft3RZMBj0V1ZW +fpkhey76W9ZmAj/DoGsBAIxAOBw6SBh43WD9YKS+/JIwZT9YMoD/UYArkoFjiQW9qGmhPwL0CcDj +KfEATsU228aMQry487LTLK93aSSsXQ8gpykcFuICsPFEWAutJfA/mOkrCAgwnwnGsal8BvCv7rJF +Yr+sURTlbT1utCIx+EgNQHR7aenKjkydXseyzmtdp51ra2tL9XjskjSZ2yG469pxFqcjGYOQEzt/ +l/Sln8k+CRT4udKbPgWwQaotNhCPB3AuOP3/AIv6Co0D9Ps9mZX9FcX2ez0evQygowCAwFpYC05j +4AUiamXmgyNhbQonltd0nUbOsz359O98GKh6k+TVL5hoLmB8Rkzx8or9CrYMr98Hij1Bd6EFgCl3 +v6QgKKnApd1Yi4yBQfsHxWa7V4/HbkZiGkBVBW4E0j0pnVlz0N+yNgvV/t96PPYjJDaqOMC4ySB0 +95kbAAQBl4dDoY89Pt/cvsr1+XxbI5HIBTD0vwA4GIlTIVzdC2ZgC0AX+3zeXHZG9kVediIiXhwK +3WwQns1Tj+8z6PvosGvakZ+EP3s9u3tpi8R+WeNyuWLhcOhfSJxukYTWXHXVVTs7kkKsAHd1MFG3 +QNtGPH4RgMHJ5Ob6xsb/7u6VCoVCKwQhGayazwwEAmOrqqo29KWjiT4J9MNzpSd9CmCDtLZ0OW6W +CbRwS2NDb4HHO+jnezIr+7tcrl2RSOR8NuJPIHGqFAA6jYDTwEiFJASA3TarWNge0/3bIgai3rz6 +hdfr/QiA32qlujMgccIkErO4XK5d4M71Msz0y0AgMJDB3TPicrl2xHXjVAbPAfA2EjvpYgC+AWgp +gy4AcedxYYTbw+Hg1GzKdrvdH7Tsaj0ajGspEbh7K4A4gO0A/xOMm4nEBK/Xu7KPogaMWT7fc8hw +akg2KKp6K4OvBmgZEg/SrUisXd4G0AoQu8vLR03vSX5Ps99uIUa6eQuTsRLTd2oi3i0Pp+30ZeCZ +TFOXPp9vLTqXRQibomR19nKx9cme9CmQDRhAOwNbwFgFwj1CMY5ye73Xm5keLsZ70u12byyv2G8S +gy8F6GkAG5E4ZWU7Ae+DEVR04zyr25Nv/86VgapXIpFIJBKJRCKRSCQSiUQikUgkEolEIpFIJBKJ +RCKRSCQSiUQikUgkEolEIpFIJBKJRCKRSCQSiUQikUgkEolEIpFIJBKJRCKRSCQSiUQikUgkEolE +IpFIJBKJRCKRSCQSiUQikUgkEolEIpFIJBKJRCKRSCQSiUQikUgkEolEIpFIJBKJRCKRSCQSiUSy +7/L/7tLt1enPwIwAAAAASUVORK5CYII= +" + height="164" + width="650" /> + </g> +</svg> diff --git a/docs/doxygen/other/extra_pages.dox b/docs/doxygen/other/extra_pages.dox index 617e00d553..88aee72ffe 100644 --- a/docs/doxygen/other/extra_pages.dox +++ b/docs/doxygen/other/extra_pages.dox @@ -119,7 +119,7 @@ built or installed. The -DENABLE_DEFAULT=False can be used to disable all components. Individual components can then be selectively turned back -on. For example, just buidling the Volk library can be +on. For example, just buidling the VOLK library can be done with this: \code @@ -160,27 +160,27 @@ cmake -DCMAKE_CXX_FLAGS:STRING="-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -g -/*! \page volk_guide Instructions for using Volk in GNU Radio +/*! \page volk_guide Instructions for using VOLK in GNU Radio \section volk_intro Introduction -Volk is the Vector-Optimized Library of Kernels. It is a library that +VOLK is the Vector-Optimized Library of Kernels. It is a library that contains kernels of hand-written SIMD code for different mathematical operations. Since each SIMD architecture can be greatly different and no compiler has yet come along to handle vectorization properly or -highly efficiently, Volk approaches the problem differently. For each +highly efficiently, VOLK approaches the problem differently. For each architecture or platform that a developer wishes to vectorize for, a -new proto-kernel is added to Volk. At runtime, Volk will select the -correct proto-kernel. In this way, the users of Volk call a kernel for +new proto-kernel is added to VOLK. At runtime, VOLK will select the +correct proto-kernel. In this way, the users of VOLK call a kernel for performing the operation that is platform/architecture agnostic. This allows us to write portable SIMD code. -Volk kernels are always defined with a 'generic' proto-kernel, which +VOLK kernels are always defined with a 'generic' proto-kernel, which is written in plain C. With the generic kernel, the kernel becomes portable to any platform. Kernels are then extended by adding proto-kernels for new platforms in which they are desired. -A good example of a Volk kernel with multiple proto-kernels defined is +A good example of a VOLK kernel with multiple proto-kernels defined is the volk_32f_s32f_multiply_32f_a. This kernel implements a scalar multiplication of a vector of floating point numbers (each item in the vector is multiplied by the same value). This kernel has the following @@ -193,10 +193,10 @@ proto-kernels that are defined for 'generic,' 'avx,' 'sse,' and 'orc.' void volk_32f_s32f_multiply_32f_a_orc \endcode -These proto-kernels means that on platforms with AVX support, Volk can +These proto-kernels means that on platforms with AVX support, VOLK can select this option or the SSE option, depending on which is faster. On other platforms, the ORC SIMD compiler might provide a solution. If -all else fails, Volk can fall back on the generic proto-kernel, which +all else fails, VOLK can fall back on the generic proto-kernel, which will always work. Just a note on ORC. ORC is a SIMD compiler library that uses a generic @@ -210,13 +210,13 @@ step to performance improvements until a specific hand-tuned proto-kernel can be made for a given platform. See <a -href="http://gnuradio.org/redmine/projects/gnuradio/wiki/Volk">Volk on -gnuradio.org</a> for details on the Volk naming scheme. +href="http://gnuradio.org/redmine/projects/gnuradio/wiki/Volk">VOLK on +gnuradio.org</a> for details on the VOLK naming scheme. \section volk_alignment Setting and Using Memory Alignment Information -For Volk to work as best as possible, we want to use memory-aligned +For VOLK to work as best as possible, we want to use memory-aligned SIMD calls, which means we have to have some way of knowing and controlling the alignment of the buffers passed to gr_block's work function. We set the alignment requirement for SIMD aligned memory @@ -228,7 +228,7 @@ calls with: set_alignment(std::max(1,alignment_multiple)); \endcode -The Volk function 'volk_get_alignment' provides the alignment of the +The VOLK function 'volk_get_alignment' provides the alignment of the the machine architecture. We then base the alignment on the number of output items required to maintain the alignment, so we divide the number of alignment bytes by the number of bytes in an output items @@ -249,13 +249,16 @@ do. The next section discusses the use of the aligned/unaligned information in a gr_block's work function. -\section volk_work Using Alignment Properties in Work() +\section volk_work Calling VOLK kernels in Work() The buffers passed to work/general_work in a gr_block are not guaranteed to be aligned, but they will mostly be aligned whenever -possible. When not aligned, the 'is_unaligned()' flag will be set. So -a block can know if its buffers are aligned and make the right -decisions. This looks like: +possible. When not aligned, the 'is_unaligned()' flag will be set so +the scheduler knows to try to realign the buffers. We actually make +calls to the VOLK dispatcher, which is mainly designed to check the +buffer alignments and call the correct version of the kernel for +us. From the user-level view of VOLK, calling the dispatcher allows us +to ignore the concept of aligned versus unaligned. This looks like: \code int @@ -266,15 +269,9 @@ gr_some_block::work (int noutput_items, const float *in = (const float *) input_items[0]; float *out = (float *) output_items[0]; - if(is_unaligned()) { - // do something with unaligned data. This can either be a manual - // handling of the items or a call to an unaligned Volk function. - volk_32f_something_32f_u(out, in, noutput_items); - } - else { - // Buffers are aligned; can call the aligned Volk function. - volk_32f_something_32f_a(out, in, noutput_items); - } + // Call the dispatcher to check alignment and call the _a or _u + // version of the kernel. + volk_32f_something_32f(out, in, noutput_items); return noutput_items; } @@ -282,7 +279,7 @@ gr_some_block::work (int noutput_items, -\section volk_tuning Tuning Volk Performance +\section volk_tuning Tuning VOLK Performance VOLK comes with a profiler that will build a config file for the best SIMD architecture for your processor. Run volk_profile that is diff --git a/docs/doxygen/other/main_page.dox b/docs/doxygen/other/main_page.dox index fdbf1c76b4..e2956384f6 100644 --- a/docs/doxygen/other/main_page.dox +++ b/docs/doxygen/other/main_page.dox @@ -1,6 +1,6 @@ /*! \mainpage -\image html gnuradio-logo.png +\image html gnuradio-logo.svg Welcome to GNU Radio! diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml index 18e6a05213..e63128337d 100644 --- a/gr-blocks/grc/blocks_block_tree.xml +++ b/gr-blocks/grc/blocks_block_tree.xml @@ -120,6 +120,7 @@ <block>blocks_message_strobe</block> <block>blocks_message_debug</block> <block>blocks_pdu_to_tagged_stream</block> + <block>blocks_tagged_stream_multiply_length</block> <block>blocks_tagged_stream_to_pdu</block> <block>blocks_random_pdu</block> </cat> diff --git a/gr-blocks/grc/blocks_tagged_stream_multiply_length.xml b/gr-blocks/grc/blocks_tagged_stream_multiply_length.xml new file mode 100644 index 0000000000..f4abb92903 --- /dev/null +++ b/gr-blocks/grc/blocks_tagged_stream_multiply_length.xml @@ -0,0 +1,70 @@ +<block> + <name>Tagged Stream Multiply Length Tag</name> + <key>blocks_tagged_stream_multiply_length</key> + <import>from gnuradio import blocks</import> + <make>blocks.tagged_stream_multiply_length($type.size*$vlen, $lengthtagname, $c)</make> + <callback>set_scalar($c)</callback> + <param> + <name>IO Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>size:gr.sizeof_gr_complex</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>size:gr.sizeof_float</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>size:gr.sizeof_int</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>size:gr.sizeof_short</opt> + </option> + <option> + <name>Byte</name> + <key>byte</key> + <opt>size:gr.sizeof_char</opt> + </option> + </param> + <param> + <name>Length tag names</name> + <key>lengthtagname</key> + <type>string</type> + </param> + <param> + <name>Vector Length</name> + <key>vlen</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Length Scalar</name> + <key>c</key> + <value>1.0</value> + <type>real</type> + </param> + <sink> + <name>in</name> + <type>$type</type> + <vlen>$vlen</vlen> + </sink> + <sink> + <name>set_scalar</name> + <type>message</type> + <optional>1</optional> + </sink> + <source> + <name>out</name> + <type>$type</type> + <vlen>$vlen</vlen> + </source> +</block> + diff --git a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt index 83338b771d..90a32f386b 100644 --- a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt +++ b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt @@ -192,6 +192,7 @@ install(FILES tag_gate.h tagged_file_sink.h tagged_stream_mux.h + tagged_stream_multiply_length.h tagged_stream_to_pdu.h tags_strobe.h threshold_ff.h diff --git a/gr-blocks/include/gnuradio/blocks/tagged_stream_multiply_length.h b/gr-blocks/include/gnuradio/blocks/tagged_stream_multiply_length.h new file mode 100644 index 0000000000..de46516f24 --- /dev/null +++ b/gr-blocks/include/gnuradio/blocks/tagged_stream_multiply_length.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_H +#define INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_H + +#include <gnuradio/blocks/api.h> +#include <gnuradio/tagged_stream_block.h> + +namespace gr { + namespace blocks { + + /*! + * \brief Allows scaling of a tagged stream length tag + * \ingroup stream_operators_blk + * + * \details + * Searches for a specific tagged stream length tag and multiplies + * that length by a constant - for constant rate change blocks + * in a tagged stream + */ + class BLOCKS_API tagged_stream_multiply_length : virtual public block + { + public: + typedef boost::shared_ptr<tagged_stream_multiply_length> sptr; + virtual void set_scalar(double scalar) = 0; + + /*! + * Make a tagged stream multiply_length block. + * + * \param itemsize Items size (number of bytes per item) + * \param lengthtagname Length tag key + * \param scalar value to scale length tag values by + */ + static sptr make(size_t itemsize, const std::string &lengthtagname, double scalar); + }; + + } // namespace blocks +} // namespace gr + +#endif /* INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_H */ + diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt index 6eded4a273..ab6c7e95be 100644 --- a/gr-blocks/lib/CMakeLists.txt +++ b/gr-blocks/lib/CMakeLists.txt @@ -232,6 +232,7 @@ list(APPEND gr_blocks_sources stretch_ff_impl.cc tagged_file_sink_impl.cc tagged_stream_to_pdu_impl.cc + tagged_stream_multiply_length_impl.cc tags_strobe_impl.cc threshold_ff_impl.cc throttle_impl.cc diff --git a/gr-blocks/lib/add_ff_impl.cc b/gr-blocks/lib/add_ff_impl.cc index e12e86c061..ca2fbe659c 100644 --- a/gr-blocks/lib/add_ff_impl.cc +++ b/gr-blocks/lib/add_ff_impl.cc @@ -56,14 +56,8 @@ namespace gr { int noi = d_vlen*noutput_items; memcpy(out, input_items[0], noi*sizeof(float)); - if(is_unaligned()) { - for(size_t i = 1; i < input_items.size(); i++) - volk_32f_x2_add_32f_u(out, out, (const float*)input_items[i], noi); - } - else { - for(size_t i = 1; i < input_items.size(); i++) - volk_32f_x2_add_32f_a(out, out, (const float*)input_items[i], noi); - } + for(size_t i = 1; i < input_items.size(); i++) + volk_32f_x2_add_32f(out, out, (const float*)input_items[i], noi); return noutput_items; } diff --git a/gr-blocks/lib/conjugate_cc_impl.cc b/gr-blocks/lib/conjugate_cc_impl.cc index 14fbbf172c..55ff30aa5d 100644 --- a/gr-blocks/lib/conjugate_cc_impl.cc +++ b/gr-blocks/lib/conjugate_cc_impl.cc @@ -54,12 +54,7 @@ namespace gr { gr_complex *iptr = (gr_complex *) input_items[0]; gr_complex *optr = (gr_complex *) output_items[0]; - if(is_unaligned()) { - volk_32fc_conjugate_32fc_u(optr, iptr, noutput_items); - } - else { - volk_32fc_conjugate_32fc_a(optr, iptr, noutput_items); - } + volk_32fc_conjugate_32fc(optr, iptr, noutput_items); return noutput_items; } diff --git a/gr-blocks/lib/endian_swap_impl.cc b/gr-blocks/lib/endian_swap_impl.cc index 3c263e40a3..604e8b9ad8 100644 --- a/gr-blocks/lib/endian_swap_impl.cc +++ b/gr-blocks/lib/endian_swap_impl.cc @@ -60,47 +60,24 @@ namespace gr { char *out = (char*)output_items[0]; int nbytes(output_signature()->sizeof_stream_item(0)); - if(is_unaligned()) { - switch(nbytes){ - case 1: - memcpy(out,in,noutput_items); - break; - case 2: - memcpy(out,in,2*noutput_items); - volk_16u_byteswap_u((uint16_t*)out,noutput_items); - break; - case 4: - memcpy(out,in,4*noutput_items); - volk_32u_byteswap_u((uint32_t*)out,noutput_items); - break; - case 8: - memcpy(out,in,8*noutput_items); - volk_64u_byteswap_u((uint64_t*)out,noutput_items); - break; - default: - throw std::runtime_error("itemsize is not valid for endian_swap!"); - } - } - else { - switch(nbytes) { - case 1: - memcpy(out,in,noutput_items); - break; - case 2: - memcpy(out,in,2*noutput_items); - volk_16u_byteswap_a((uint16_t*)out,noutput_items); - break; - case 4: - memcpy(out,in,4*noutput_items); - volk_32u_byteswap_a((uint32_t*)out,noutput_items); - break; - case 8: - memcpy(out,in,8*noutput_items); - volk_64u_byteswap_a((uint64_t*)out,noutput_items); - break; - default: - throw std::runtime_error("itemsize is not valid for endian_swap!"); - } + switch(nbytes){ + case 1: + memcpy(out,in,noutput_items); + break; + case 2: + memcpy(out,in,2*noutput_items); + volk_16u_byteswap((uint16_t*)out,noutput_items); + break; + case 4: + memcpy(out,in,4*noutput_items); + volk_32u_byteswap((uint32_t*)out,noutput_items); + break; + case 8: + memcpy(out,in,8*noutput_items); + volk_64u_byteswap((uint64_t*)out,noutput_items); + break; + default: + throw std::runtime_error("itemsize is not valid for endian_swap!"); } return noutput_items; diff --git a/gr-blocks/lib/multiply_cc_impl.cc b/gr-blocks/lib/multiply_cc_impl.cc index b54296c112..2e1ce93b37 100644 --- a/gr-blocks/lib/multiply_cc_impl.cc +++ b/gr-blocks/lib/multiply_cc_impl.cc @@ -56,14 +56,9 @@ namespace gr { int noi = d_vlen*noutput_items; memcpy(out, input_items[0], noi*sizeof(gr_complex)); - if(is_unaligned()) { - for(size_t i = 1; i < input_items.size(); i++) - volk_32fc_x2_multiply_32fc_u(out, out, (gr_complex*)input_items[i], noi); - } - else { - for(size_t i = 1; i < input_items.size(); i++) - volk_32fc_x2_multiply_32fc_a(out, out, (gr_complex*)input_items[i], noi); - } + for(size_t i = 1; i < input_items.size(); i++) + volk_32fc_x2_multiply_32fc(out, out, (gr_complex*)input_items[i], noi); + return noutput_items; } diff --git a/gr-blocks/lib/multiply_conjugate_cc_impl.cc b/gr-blocks/lib/multiply_conjugate_cc_impl.cc index 671e1160f6..7f9652152b 100644 --- a/gr-blocks/lib/multiply_conjugate_cc_impl.cc +++ b/gr-blocks/lib/multiply_conjugate_cc_impl.cc @@ -57,12 +57,7 @@ namespace gr { gr_complex *out = (gr_complex *) output_items[0]; int noi = d_vlen*noutput_items; - if(is_unaligned()) { - volk_32fc_x2_multiply_conjugate_32fc_u(out, in0, in1, noi); - } - else { - volk_32fc_x2_multiply_conjugate_32fc_a(out, in0, in1, noi); - } + volk_32fc_x2_multiply_conjugate_32fc(out, in0, in1, noi); return noutput_items; } diff --git a/gr-blocks/lib/multiply_const_cc_impl.cc b/gr-blocks/lib/multiply_const_cc_impl.cc index d0393907b0..f6b8dc3d63 100644 --- a/gr-blocks/lib/multiply_const_cc_impl.cc +++ b/gr-blocks/lib/multiply_const_cc_impl.cc @@ -58,12 +58,7 @@ namespace gr { gr_complex *out = (gr_complex *) output_items[0]; int noi = d_vlen*noutput_items; - if(is_unaligned()) { - volk_32fc_s32fc_multiply_32fc_u(out, in, d_k, noi); - } - else { - volk_32fc_s32fc_multiply_32fc_a(out, in, d_k, noi); - } + volk_32fc_s32fc_multiply_32fc(out, in, d_k, noi); return noutput_items; } diff --git a/gr-blocks/lib/multiply_const_ff_impl.cc b/gr-blocks/lib/multiply_const_ff_impl.cc index 67205c06c0..366c06181f 100644 --- a/gr-blocks/lib/multiply_const_ff_impl.cc +++ b/gr-blocks/lib/multiply_const_ff_impl.cc @@ -58,12 +58,7 @@ namespace gr { float *out = (float *) output_items[0]; int noi = d_vlen*noutput_items; - if(is_unaligned()) { - volk_32f_s32f_multiply_32f_u(out, in, d_k, noi); - } - else { - volk_32f_s32f_multiply_32f_a(out, in, d_k, noi); - } + volk_32f_s32f_multiply_32f(out, in, d_k, noi); return noutput_items; } diff --git a/gr-blocks/lib/multiply_ff_impl.cc b/gr-blocks/lib/multiply_ff_impl.cc index 912c1bb926..22100497c5 100644 --- a/gr-blocks/lib/multiply_ff_impl.cc +++ b/gr-blocks/lib/multiply_ff_impl.cc @@ -56,14 +56,9 @@ namespace gr { int noi = d_vlen*noutput_items; memcpy(out, input_items[0], noi*sizeof(float)); - if(is_unaligned()) { - for(size_t i = 1; i < input_items.size(); i++) - volk_32f_x2_multiply_32f_u(out, out, (float*)input_items[i], noi); - } - else { - for(size_t i = 1; i < input_items.size(); i++) - volk_32f_x2_multiply_32f_a(out, out, (float*)input_items[i], noi); - } + for(size_t i = 1; i < input_items.size(); i++) + volk_32f_x2_multiply_32f(out, out, (float*)input_items[i], noi); + return noutput_items; } diff --git a/gr-blocks/lib/tagged_stream_multiply_length_impl.cc b/gr-blocks/lib/tagged_stream_multiply_length_impl.cc new file mode 100644 index 0000000000..18a8eef1e9 --- /dev/null +++ b/gr-blocks/lib/tagged_stream_multiply_length_impl.cc @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/io_signature.h> +#include "tagged_stream_multiply_length_impl.h" + +namespace gr { + namespace blocks { + + tagged_stream_multiply_length::sptr + tagged_stream_multiply_length::make(size_t itemsize, const std::string &lengthtagname, double scalar) + { + return gnuradio::get_initial_sptr (new tagged_stream_multiply_length_impl(itemsize, lengthtagname, scalar)); + } + + tagged_stream_multiply_length_impl::tagged_stream_multiply_length_impl(size_t itemsize, const std::string &lengthtagname, double scalar) + : block("tagged_stream_multiply_length", + io_signature::make(1, 1, itemsize), + io_signature::make(1, 1, itemsize)), + d_lengthtag(pmt::mp(lengthtagname)), + d_scalar(scalar), + d_itemsize(itemsize) + { + set_tag_propagation_policy(TPP_DONT); + set_relative_rate(1); + message_port_register_in(pmt::intern("set_scalar")); + set_msg_handler(pmt::intern("set_scalar"), + boost::bind(&tagged_stream_multiply_length_impl::set_scalar_pmt, this, _1)); + } + + tagged_stream_multiply_length_impl::~tagged_stream_multiply_length_impl() + { + } + + int + tagged_stream_multiply_length_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const void* in = input_items[0]; + void* out = output_items[0]; + + // move data across ( wasteful memcopy :< ) + memcpy(out, in, noutput_items*d_itemsize); + + // move and update tags + std::vector<tag_t> tags; + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+ninput_items[0]); + for(size_t i=0; i<tags.size(); i++){ + if(pmt::eqv( tags[i].key , d_lengthtag)){ + // propagate with value update (scaled) + add_item_tag(0, tags[i].offset, tags[i].key, pmt::from_long(pmt::to_long(tags[i].value) * d_scalar), tags[i].srcid ); + } else { + // propagate unmodified + add_item_tag(0, tags[i].offset, tags[i].key, tags[i].value, tags[i].srcid ); + } + } + + consume_each(noutput_items); + return noutput_items; + } + + } /* namespace blocks */ +} /* namespace gr */ + diff --git a/gr-blocks/lib/tagged_stream_multiply_length_impl.h b/gr-blocks/lib/tagged_stream_multiply_length_impl.h new file mode 100644 index 0000000000..5d61650369 --- /dev/null +++ b/gr-blocks/lib/tagged_stream_multiply_length_impl.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_IMPL_H +#define INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_IMPL_H + +#include <vector> +#include <gnuradio/blocks/tagged_stream_multiply_length.h> + +namespace gr { + namespace blocks { + + class tagged_stream_multiply_length_impl : public tagged_stream_multiply_length + { + private: + pmt::pmt_t d_lengthtag; + double d_scalar; + size_t d_itemsize; + + public: + tagged_stream_multiply_length_impl(size_t itemsize, const std::string &lengthtagname, double scalar); + ~tagged_stream_multiply_length_impl(); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void set_scalar(double scalar){ + d_scalar = scalar; + } + + void set_scalar_pmt(pmt::pmt_t msg){ + set_scalar(pmt::to_double(msg)); + } + + }; + + } // namespace blocks +} // namespace gr + +#endif + diff --git a/gr-blocks/swig/blocks_swig5.i b/gr-blocks/swig/blocks_swig5.i index 09679531d9..deb3b5a045 100644 --- a/gr-blocks/swig/blocks_swig5.i +++ b/gr-blocks/swig/blocks_swig5.i @@ -51,6 +51,7 @@ #include "gnuradio/blocks/sub_cc.h" #include "gnuradio/blocks/tag_gate.h" #include "gnuradio/blocks/tagged_stream_mux.h" +#include "gnuradio/blocks/tagged_stream_multiply_length.h" #include "gnuradio/blocks/tagged_stream_to_pdu.h" #include "gnuradio/blocks/tags_strobe.h" #include "gnuradio/blocks/threshold_ff.h" @@ -90,6 +91,7 @@ %include "gnuradio/blocks/sub_cc.h" %include "gnuradio/blocks/tag_gate.h" %include "gnuradio/blocks/tagged_stream_mux.h" +%include "gnuradio/blocks/tagged_stream_multiply_length.h" %include "gnuradio/blocks/tagged_stream_to_pdu.h" %include "gnuradio/blocks/tags_strobe.h" %include "gnuradio/blocks/threshold_ff.h" @@ -128,6 +130,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, sub_ii); GR_SWIG_BLOCK_MAGIC2(blocks, sub_cc); GR_SWIG_BLOCK_MAGIC2(blocks, tag_gate); GR_SWIG_BLOCK_MAGIC2(blocks, tagged_stream_mux); +GR_SWIG_BLOCK_MAGIC2(blocks, tagged_stream_multiply_length); GR_SWIG_BLOCK_MAGIC2(blocks, tagged_stream_to_pdu); GR_SWIG_BLOCK_MAGIC2(blocks, tags_strobe); GR_SWIG_BLOCK_MAGIC2(blocks, threshold_ff); diff --git a/gr-fft/include/gnuradio/fft/window.h b/gr-fft/include/gnuradio/fft/window.h index 4a7fb44ff9..92f62c64cb 100644 --- a/gr-fft/include/gnuradio/fft/window.h +++ b/gr-fft/include/gnuradio/fft/window.h @@ -35,19 +35,41 @@ namespace gr { public: enum win_type { - WIN_NONE = -1, //!< don't use a window - WIN_HAMMING = 0, //!< Hamming window; max attenuation 53 dB - WIN_HANN = 1, //!< Hann window; max attenuation 44 dB - WIN_BLACKMAN = 2, //!< Blackman window; max attenuation 74 dB - WIN_RECTANGULAR = 3, //!< Basic rectangular window - WIN_KAISER = 4, //!< Kaiser window; max attenuation a function of beta, google it - WIN_BLACKMAN_hARRIS = 5, //!< Blackman-harris window - WIN_BLACKMAN_HARRIS = 5, //!< alias to WIN_BLACKMAN_hARRIS for capitalization consistency - WIN_BARTLETT = 6, //!< Barlett (triangular) window - WIN_FLATTOP = 7, //!< flat top window; useful in FFTs + WIN_HAMMING = 0, //!< Hamming window; max attenuation 53 dB + WIN_HANN = 1, //!< Hann window; max attenuation 44 dB + WIN_BLACKMAN = 2, //!< Blackman window; max attenuation 74 dB + WIN_RECTANGULAR = 3, //!< Basic rectangular window; max attenuation 21 dB + WIN_KAISER = 4, //!< Kaiser window; max attenuation see window::max_attenuation + WIN_BLACKMAN_hARRIS = 5, //!< Blackman-harris window; max attenuation 92 dB + WIN_BLACKMAN_HARRIS = 5, //!< alias to WIN_BLACKMAN_hARRIS for capitalization consistency + WIN_BARTLETT = 6, //!< Barlett (triangular) window; max attenuation 26 dB + WIN_FLATTOP = 7, //!< flat top window; useful in FFTs; max attenuation 93 dB }; /*! + * \brief Given a window::win_type, this tells you the maximum + * attenuation you can expect. + * + * \details + * For most windows, this is a set value. For the Kaiser window, + * the attenuation is based on the value of beta. The actual + * relationship is a piece-wise exponential relationship to + * calculate beta from the desired attenuation and can be found + * on page 542 of Oppenheim and Schafer (Discrete-Time Signal + * Processing, 3rd edition). To simplify this function to solve + * for A given beta, we use a linear form that is exact for + * attenuation >= 50 dB. + * + * For an attenuation of 50 dB, beta = 4.55. + * + * For an attenuation of 70 dB, beta = 6.76. + * + * \param type The window::win_type enumeration of the window type. + * \param beta Beta value only used for the Kaiser window. + */ + static double max_attenuation(win_type type, double beta=6.76); + + /*! * \brief Helper function to build cosine-based windows. 3-coefficient version. */ static std::vector<float> coswindow(int ntaps, float c0, float c1, float c2); diff --git a/gr-fft/lib/window.cc b/gr-fft/lib/window.cc index 1610b46f5d..015e2d9943 100644 --- a/gr-fft/lib/window.cc +++ b/gr-fft/lib/window.cc @@ -74,7 +74,24 @@ namespace gr { return 1.0/(ntaps >> 1); } - std::vector<float> + double + window::max_attenuation(win_type type, double beta) + { + switch(type) { + case(WIN_HAMMING): return 53; break; + case(WIN_HANN): return 44; break; + case(WIN_BLACKMAN): return 74; break; + case(WIN_RECTANGULAR): return 21; break; + case(WIN_KAISER): return (beta/0.1102 + 8.7); break; + case(WIN_BLACKMAN_hARRIS): return 92; break; + case(WIN_BARTLETT): return 27; break; + case(WIN_FLATTOP): return 93; break; + default: + throw std::out_of_range("window::max_attenuation: unknown window type provided."); + } + } + + std::vector<float> window::coswindow(int ntaps, float c0, float c1, float c2) { std::vector<float> taps(ntaps); diff --git a/gr-filter/doc/filter.dox b/gr-filter/doc/filter.dox index ad0cfcb6c5..a9b329836c 100644 --- a/gr-filter/doc/filter.dox +++ b/gr-filter/doc/filter.dox @@ -54,11 +54,6 @@ impulse response (IIR) filtering. an IIR filter with a single pole (also known as a moving average filter). -\li Adaptive FIR filters (see adaptive_fir.h): FIR filters that define -an \b error and \b update_tap virtual interface to create filters that -update the taps based on some criteria. \sa -gr::digital::lms_dd_equalizer_cc, gr::digital::cma_equalizer_cc - \li PFB arbitrary resampler (see pfb_arb_resampler.h): performs arbitrary resampling (i.e., using any real number) using the polyphase filterbank method. \sa \ref pfb_arb_resampl @@ -94,11 +89,6 @@ blocks. <li>gr::filter::single_pole_iir_filter_cc</li> <li>gr::filter::single_pole_iir_filter_ff</li> </ul> -<li>Adaptive FIR Filters</li> - <ul> - <li>gr::filter::adaptive_fir_ccc</li> - <li>gr::filter::adaptive_fir_ccf</li> - </ul> <li>Polyphase Filterbanks</li> <ul> <li>gr::filter::pfb_arb_resampler_ccf</li> diff --git a/gr-filter/grc/filter_pfb_decimator.xml b/gr-filter/grc/filter_pfb_decimator.xml index 8ecf9b2d95..d57119636c 100644 --- a/gr-filter/grc/filter_pfb_decimator.xml +++ b/gr-filter/grc/filter_pfb_decimator.xml @@ -15,7 +15,8 @@ $channel, $atten) </make> - <callback>set_taps($taps)</callback> + <callback>set_taps($taps)</callback> + <callback>set_channel(int($channel))</callback> <param> <name>Decimation</name> <key>decim</key> diff --git a/gr-filter/include/gnuradio/filter/CMakeLists.txt b/gr-filter/include/gnuradio/filter/CMakeLists.txt index 7871c8c003..3135688eb4 100644 --- a/gr-filter/include/gnuradio/filter/CMakeLists.txt +++ b/gr-filter/include/gnuradio/filter/CMakeLists.txt @@ -79,7 +79,6 @@ add_custom_target(filter_generated_includes DEPENDS install(FILES ${generated_includes} api.h - adaptive_fir.h firdes.h fir_filter.h fir_filter_with_buffer.h @@ -91,8 +90,6 @@ install(FILES pm_remez.h polyphase_filterbank.h single_pole_iir.h - adaptive_fir_ccc.h - adaptive_fir_ccf.h dc_blocker_cc.h dc_blocker_ff.h filter_delay_fc.h diff --git a/gr-filter/include/gnuradio/filter/adaptive_fir.h b/gr-filter/include/gnuradio/filter/adaptive_fir.h deleted file mode 100644 index be2060537f..0000000000 --- a/gr-filter/include/gnuradio/filter/adaptive_fir.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_H -#define INCLUDED_FILTER_ADAPTIVE_FIR_H - -#include <gnuradio/filter/api.h> -#include <gnuradio/filter/fir_filter.h> - -namespace gr { - namespace filter { - namespace kernel { - - /*! - * \brief Adaptive FIR filter kernel with gr_complex input, - * gr_complex output and gr_complex taps - * - * This class implements an adaptive FIR filter. Any class - * actually wanting to use adaptive FIRs will contain an object of - * this class. - */ - class FILTER_API adaptive_fir_ccc : public fir_filter_ccc - { - public: - adaptive_fir_ccc(int decimation, - const std::vector<gr_complex> &taps); - ~adaptive_fir_ccc(); - - protected: - // Override to calculate error signal per output - virtual gr_complex error(const gr_complex &out) = 0; - - // Override to calculate new weight from old, corresponding input - virtual void update_tap(gr_complex &tap, const gr_complex &in) = 0; - - gr_complex d_error; - }; - - - /*! - * \brief Adaptive FIR filter kernel with gr_complex input, - * gr_complex output and float taps - * - * This class implements an adaptive FIR filter. Any class - * actually wanting to use adaptive FIRs will contain an object of - * this class. - */ - class FILTER_API adaptive_fir_ccf : public fir_filter_ccf - { - public: - adaptive_fir_ccf(int decimation, - const std::vector<float> &taps); - ~adaptive_fir_ccf(); - - protected: - // Override to calculate error signal per output - virtual float error(const gr_complex &out) = 0; - - // Override to calculate new weight from old, corresponding input - virtual void update_tap(float &tap, const gr_complex &in) = 0; - - float d_error; - }; - - } /* namespace kernel */ - } /* namespace filter */ -} /* namespace gr */ - -#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_H */ diff --git a/gr-filter/include/gnuradio/filter/adaptive_fir_ccc.h b/gr-filter/include/gnuradio/filter/adaptive_fir_ccc.h deleted file mode 100644 index 13e05a477b..0000000000 --- a/gr-filter/include/gnuradio/filter/adaptive_fir_ccc.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H -#define INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H - -#include <gnuradio/filter/api.h> -#include <gnuradio/sync_decimator.h> - -namespace gr { - namespace filter { - - /*! - * \brief Adaptive FIR filter with gr_complex input, gr_complex output and gr_complex taps - * \ingroup filter_blk - * - * \details - * This is a base class to implement an adaptive FIR - * filter. Generally, another block will inherit from this one to - * build a new type of adaptive filter such as an equalizer. - * - * This class implements two functions that are designed to be - * overloaded by the child class: error(gr_complex out) and - * update_tap(gr_complex tap, gr_complex in). - * - * The error() function calculates the error value that will be - * used to adjust the taps. The update_tap function then uses the - * error and the input signal value to update a particular - * tap. Typically, the error is calculated for a given output and - * then this is used in a loop to update all of the filter taps in - * a loop: - * - * \code - * d_error = error(sum); - * for(k = 0; k < l; k++) { - * update_tap(d_taps[ntaps-k-1], in[i+k]); - * } - * \endcode - * - * See digital::cma_equalizer_cc and digital::lms_dd_equalizer_cc - * for example usage. - */ - class FILTER_API adaptive_fir_ccc : virtual public sync_decimator - { - protected: - - public: - // gr::filter::adaptive_fir_ccc::sptr - typedef boost::shared_ptr<adaptive_fir_ccc> sptr; - - /*! - * \brief Adaptive FIR filter with gr_complex input, gr_complex output and gr_complex taps - * - * \param name Provides a name to identify this type of algorithm - * \param decimation (interger) decimation rate of the filter - * \param taps (complex) filter taps - */ - static sptr make(const char *name, int decimation, - const std::vector<gr_complex> &taps); - - virtual void set_taps(const std::vector<gr_complex> &taps) = 0; - virtual std::vector<gr_complex> taps() const = 0; - }; - - } /* namespace filter */ -} /* namespace gr */ - -#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H */ diff --git a/gr-filter/include/gnuradio/filter/adaptive_fir_ccf.h b/gr-filter/include/gnuradio/filter/adaptive_fir_ccf.h deleted file mode 100644 index 81d11d6fd6..0000000000 --- a/gr-filter/include/gnuradio/filter/adaptive_fir_ccf.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H -#define INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H - -#include <gnuradio/filter/api.h> -#include <gnuradio/sync_decimator.h> - -namespace gr { - namespace filter { - - /*! - * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps - * \ingroup filter_blk - * - * \details - * This is a base class to implement an adaptive FIR - * filter. Generally, another block will inherit from this one to - * build a new type of adaptive filter such as an equalizer. - * - * This class implements two functions that are designed to be - * overloaded by the child class: error(gr_complex out) and - * update_tap(float tap, gr_complex in). - * - * The error() function calculates the error value that will be - * used to adjust the taps. The update_tap function then uses the - * error and the input signal value to update a particular - * tap. Typically, the error is calculated for a given output and - * then this is used in a loop to update all of the filter taps in - * a loop: - * - * \code - * d_error = error(sum); - * for(k = 0; k < l; k++) { - * update_tap(d_taps[ntaps-k-1], in[i+k]); - * } - * \endcode - */ - class FILTER_API adaptive_fir_ccf : virtual public sync_decimator - { - public: - // gr::filter::adaptive_fir_ccf::sptr - typedef boost::shared_ptr<adaptive_fir_ccf> sptr; - - /*! - * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps - * - * \param name Provides a name to identify this type of algorithm - * \param decimation (interger) decimation rate of the filter - * \param taps (real) filter taps - */ - static sptr make(const char *name, int decimation, - const std::vector<float> &taps); - - virtual void set_taps(const std::vector<float> &taps) = 0; - virtual std::vector<float> taps() = 0; - }; - - } /* namespace filter */ -} /* namespace gr */ - -#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H */ diff --git a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h index 822206889f..da4eb2bd34 100644 --- a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h +++ b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h @@ -120,7 +120,7 @@ namespace gr { */ virtual void print_taps() = 0; - //virtual void set_channel(unsigned int channel) = 0; + virtual void set_channel(const unsigned int channel) = 0; }; } /* namespace filter */ diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt index db9b0cfcb9..58000bbfcd 100644 --- a/gr-filter/lib/CMakeLists.txt +++ b/gr-filter/lib/CMakeLists.txt @@ -115,7 +115,6 @@ endif(ENABLE_GR_CTRLPORT) # Setup library ######################################################################## list(APPEND filter_sources - adaptive_fir.cc fir_filter.cc fir_filter_with_buffer.cc fft_filter.cc @@ -125,8 +124,6 @@ list(APPEND filter_sources pm_remez.cc polyphase_filterbank.cc ${generated_sources} - adaptive_fir_ccc_impl.cc - adaptive_fir_ccf_impl.cc dc_blocker_cc_impl.cc dc_blocker_ff_impl.cc filter_delay_fc_impl.cc diff --git a/gr-filter/lib/adaptive_fir.cc b/gr-filter/lib/adaptive_fir.cc deleted file mode 100644 index a7ee8228a0..0000000000 --- a/gr-filter/lib/adaptive_fir.cc +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gnuradio/filter/adaptive_fir.h> -#include <gnuradio/io_signature.h> - -namespace gr { - namespace filter { - namespace kernel { - - adaptive_fir_ccc::adaptive_fir_ccc(int decimation, - const std::vector<gr_complex> &taps) - : fir_filter_ccc(decimation, taps) - { - } - - adaptive_fir_ccc::~adaptive_fir_ccc() - { - } - - - /**************************************************************/ - - - adaptive_fir_ccf::adaptive_fir_ccf(int decimation, - const std::vector<float> &taps) - : fir_filter_ccf(decimation, taps) - { - } - - adaptive_fir_ccf::~adaptive_fir_ccf() - { - } - - } /* namespace kernel */ - } /* namespace filter */ -} /* namespace gr */ diff --git a/gr-filter/lib/adaptive_fir_ccc_impl.cc b/gr-filter/lib/adaptive_fir_ccc_impl.cc deleted file mode 100644 index 93c7dea443..0000000000 --- a/gr-filter/lib/adaptive_fir_ccc_impl.cc +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "adaptive_fir_ccc_impl.h" -#include <gnuradio/io_signature.h> - -namespace gr { - namespace filter { - - adaptive_fir_ccc::sptr adaptive_fir_ccc::make(const char *name, int decimation, - const std::vector<gr_complex> &taps) - { - return gnuradio::get_initial_sptr(new adaptive_fir_ccc_impl - (name, decimation, taps)); - } - - adaptive_fir_ccc_impl::adaptive_fir_ccc_impl(const char *name, int decimation, - const std::vector<gr_complex> &taps) - : sync_decimator(name, - io_signature::make(1, 1, sizeof(gr_complex)), - io_signature::make(1, 1, sizeof(gr_complex)), - decimation), - kernel::adaptive_fir_ccc(decimation, taps), - d_updated(false) - { - set_history(d_ntaps); - } - - void - adaptive_fir_ccc_impl::set_taps(const std::vector<gr_complex> &taps) - { - d_new_taps = taps; - d_updated = true; - } - - std::vector<gr_complex> - adaptive_fir_ccc_impl::taps() const - { - return kernel::fir_filter_ccc::taps(); - } - - gr_complex - adaptive_fir_ccc_impl::error(const gr_complex &out) - { - return 0; - } - - void - adaptive_fir_ccc_impl::update_tap(gr_complex &tap, const gr_complex &in) - { - tap = tap; - } - - int - adaptive_fir_ccc_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr_complex *in = (gr_complex *)input_items[0]; - gr_complex *out = (gr_complex *)output_items[0]; - - if (d_updated) { - kernel::fir_filter_ccc::set_taps(d_new_taps); - set_history(d_ntaps); - d_updated = false; - return 0; // history requirements may have changed. - } - - // Call base class filtering function that uses - // overloaded error and update_tap functions. - if (decimation() == 1) { - filterN(out, in, noutput_items); - } - else { - filterNdec(out, in, noutput_items, - decimation()); - } - - return noutput_items; - } - - } /* namespace filter */ -} /* namespace gr */ diff --git a/gr-filter/lib/adaptive_fir_ccc_impl.h b/gr-filter/lib/adaptive_fir_ccc_impl.h deleted file mode 100644 index 66b8fe5a49..0000000000 --- a/gr-filter/lib/adaptive_fir_ccc_impl.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H -#define INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H - -#include <gnuradio/filter/adaptive_fir_ccc.h> -#include <gnuradio/filter/adaptive_fir.h> -#include <gnuradio/types.h> - -namespace gr { - namespace filter { - - class FILTER_API adaptive_fir_ccc_impl : - public adaptive_fir_ccc, public kernel::adaptive_fir_ccc - { - private: - std::vector<gr_complex> d_new_taps; - bool d_updated; - - protected: - // Override to calculate error signal per output - gr_complex error(const gr_complex &out); - - // Override to calculate new weight from old, corresponding input - void update_tap(gr_complex &tap, const gr_complex &in); - - public: - void set_taps(const std::vector<gr_complex> &taps); - std::vector<gr_complex> taps() const; - - adaptive_fir_ccc_impl(const char *name, int decimation, - const std::vector<gr_complex> &taps); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } /* namespace filter */ -} /* namespace gr */ - -#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H */ diff --git a/gr-filter/lib/adaptive_fir_ccf_impl.cc b/gr-filter/lib/adaptive_fir_ccf_impl.cc deleted file mode 100644 index 16d59f36f3..0000000000 --- a/gr-filter/lib/adaptive_fir_ccf_impl.cc +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "adaptive_fir_ccf_impl.h" -#include <gnuradio/io_signature.h> - -namespace gr { - namespace filter { - - adaptive_fir_ccf::sptr adaptive_fir_ccf::make(const char *name, int decimation, - const std::vector<float> &taps) - { - return gnuradio::get_initial_sptr(new adaptive_fir_ccf_impl - (name, decimation, taps)); - } - - adaptive_fir_ccf_impl::adaptive_fir_ccf_impl(const char *name, int decimation, - const std::vector<float> &taps) - : sync_decimator(name, - io_signature::make(1, 1, sizeof(gr_complex)), - io_signature::make(1, 1, sizeof(gr_complex)), - decimation), - kernel::adaptive_fir_ccf(decimation, taps), - d_updated(false) - { - set_history(d_ntaps); - } - - void - adaptive_fir_ccf_impl::set_taps(const std::vector<float> &taps) - { - d_new_taps = taps; - d_updated = true; - } - - std::vector<float> - adaptive_fir_ccf_impl::taps() - { - return kernel::fir_filter_ccf::taps(); - } - - float - adaptive_fir_ccf_impl::error(const gr_complex &out) - { - return 0; - } - - void - adaptive_fir_ccf_impl::update_tap(float &tap, const gr_complex &in) - { - tap = tap; - } - - int - adaptive_fir_ccf_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr_complex *in = (gr_complex *)input_items[0]; - gr_complex *out = (gr_complex *)output_items[0]; - - if (d_updated) { - kernel::fir_filter_ccf::set_taps(d_new_taps); - set_history(d_ntaps); - d_updated = false; - return 0; // history requirements may have changed. - } - - // Call base class filtering function that uses - // overloaded error and update_tap functions. - if (decimation() == 1) { - filterN(out, in, noutput_items); - } - else { - filterNdec(out, in, noutput_items, - decimation()); - } - - return noutput_items; - } - - } /* namespace filter */ -} /* namespace gr */ diff --git a/gr-filter/lib/adaptive_fir_ccf_impl.h b/gr-filter/lib/adaptive_fir_ccf_impl.h deleted file mode 100644 index 188587ee56..0000000000 --- a/gr-filter/lib/adaptive_fir_ccf_impl.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2011,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H -#define INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H - -#include <gnuradio/filter/adaptive_fir_ccf.h> -#include <gnuradio/filter/adaptive_fir.h> -#include <gnuradio/types.h> - -namespace gr { - namespace filter { - - class FILTER_API adaptive_fir_ccf_impl : - public adaptive_fir_ccf, public kernel::adaptive_fir_ccf - { - private: - std::vector<float> d_new_taps; - bool d_updated; - - protected: - // Override to calculate error signal per output - float error(const gr_complex &out); - - // Override to calculate new weight from old, corresponding input - void update_tap(float &tap, const gr_complex &in); - - public: - void set_taps(const std::vector<float> &taps); - std::vector<float> taps(); - - adaptive_fir_ccf_impl(const char *name, int decimation, - const std::vector<float> &taps); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } /* namespace filter */ -} /* namespace gr */ - -#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H */ diff --git a/gr-filter/lib/firdes.cc b/gr-filter/lib/firdes.cc index a52a2ddf63..cb6bffd18a 100644 --- a/gr-filter/lib/firdes.cc +++ b/gr-filter/lib/firdes.cc @@ -658,21 +658,6 @@ namespace gr { // === Utilities === // - // delta_f / width_factor gives number of taps required. - const int MAX_WIDTH_FACTOR = 8; - static const float width_factor[8] = { // indexed by win_type - 3.3, // WIN_HAMMING - 3.1, // WIN_HANN - 5.5, // WIN_BLACKMAN - 2.0, // WIN_RECTANGULAR - //5.0 // WIN_KAISER (guesstimate compromise) - //2.0 // WIN_KAISER (guesstimate compromise) - 10.0, // WIN_KAISER - 6.0, // WIN_BLACKMAN_HARRIS (est.) - 3.0, // WIN_BARTLETT (est.) - 5.5, // WIN_FLATTOP (est.) - }; - int firdes::compute_ntaps_windes(double sampling_freq, double transition_width, // this is frequency, not relative frequency @@ -692,14 +677,8 @@ namespace gr { win_type window_type, double beta) { - // normalized transition width - double delta_f = transition_width / sampling_freq; - - // compute number of taps required for given transition width - if(window_type >= MAX_WIDTH_FACTOR) - throw std::runtime_error("firdes::compute_ntaps: window_type out of range."); - - int ntaps = (int)(width_factor[window_type] / delta_f + 0.5); + double a = fft::window::max_attenuation(static_cast<fft::window::win_type>(window_type), beta); + int ntaps = (int)(a*sampling_freq/(22.0*transition_width)); if((ntaps & 1) == 0) // if even... ntaps++; // ...make odd diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc b/gr-filter/lib/pfb_decimator_ccf_impl.cc index a9e5138d18..feb36a5999 100644 --- a/gr-filter/lib/pfb_decimator_ccf_impl.cc +++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc @@ -82,6 +82,13 @@ namespace gr { return polyphase_filterbank::taps(); } + void + pfb_decimator_ccf_impl::set_channel(const unsigned int chan) + { + gr::thread::scoped_lock guard(d_mutex); + d_chan = chan; + } + #define ROTATEFFT int diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.h b/gr-filter/lib/pfb_decimator_ccf_impl.h index eeebc2c3a7..2df8a506f0 100644 --- a/gr-filter/lib/pfb_decimator_ccf_impl.h +++ b/gr-filter/lib/pfb_decimator_ccf_impl.h @@ -52,7 +52,7 @@ namespace gr { void set_taps(const std::vector<float> &taps); void print_taps(); std::vector<std::vector<float> > taps() const; - //void set_channel(unsigned int channel); + void set_channel(const unsigned int channel); int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gr-filter/lib/qa_firdes.cc b/gr-filter/lib/qa_firdes.cc index dfc5e00f35..b17337001e 100644 --- a/gr-filter/lib/qa_firdes.cc +++ b/gr-filter/lib/qa_firdes.cc @@ -31,456 +31,120 @@ namespace gr { namespace filter { - + #define NELEM(x) (sizeof(x) / sizeof(x[0])) using std::vector; - -#if 0 - static void + + void print_taps(std::ostream &s, vector<float> &v) { - + std::streamsize tmp = s.precision(9); for(unsigned int i = 0; i < v.size(); i++) { - printf("tap[%2d] = %16.7e\n", i, v[i]); + s << v[i] << ", "; } + s << std::endl; + s.precision(tmp); } -#endif - + static void check_symmetry(vector<float> &v) { int n = v.size(); int m = n / 2; - + for(int i = 0; i < m; i++) CPPUNIT_ASSERT_DOUBLES_EQUAL(v[i], v[n - i - 1], 1e-9); } - const static float t1_exp[53] = { - -9.0525491e-04, - 2.0713841e-04, - 1.2388536e-03, - 2.9683491e-04, - -1.7744775e-03, - -1.3599906e-03, - 2.2031884e-03, - 3.2744040e-03, - -1.8868084e-03, - -5.9935520e-03, - 6.4301129e-18, - 8.9516686e-03, - 4.2178580e-03, - -1.0998557e-02, - -1.1173409e-02, - 1.0455756e-02, - 2.0686293e-02, - -5.2032238e-03, - -3.1896964e-02, - -7.4998410e-03, - 4.3362070e-02, - 3.2502845e-02, - -5.3328082e-02, - -8.5621715e-02, - 6.0117975e-02, - 3.1128189e-01, - 4.3769023e-01, - 3.1128189e-01, - 6.0117975e-02, - -8.5621715e-02, - -5.3328082e-02, - 3.2502845e-02, - 4.3362070e-02, - -7.4998410e-03, - -3.1896964e-02, - -5.2032238e-03, - 2.0686293e-02, - 1.0455756e-02, - -1.1173409e-02, - -1.0998557e-02, - 4.2178580e-03, - 8.9516686e-03, - 6.4301129e-18, - -5.9935520e-03, - -1.8868084e-03, - 3.2744040e-03, - 2.2031884e-03, - -1.3599906e-03, - -1.7744775e-03, - 2.9683491e-04, - 1.2388536e-03, - 2.0713841e-04, - -9.0525491e-04 + const static float t1_exp[39] = { + 0.00111410965, -0.000583702058, -0.00192639488, 2.30933896e-18, 0.00368289859, + 0.00198723329, -0.0058701504, -0.00666110823, 0.0068643163, 0.0147596458, + -0.00398709066, -0.0259727165, -0.0064281947, 0.0387893915, 0.0301109217, + -0.0507995859, -0.0833103433, 0.0593735874, 0.310160041, 0.437394291, + 0.310160041, 0.0593735874, -0.0833103433, -0.0507995859, 0.0301109217, + 0.0387893915, -0.0064281947, -0.0259727165, -0.00398709066, 0.0147596458, + 0.0068643163, -0.00666110823, -0.0058701504, 0.00198723329, 0.00368289859, + 2.30933896e-18, -0.00192639488, -0.000583702058, 0.00111410965 }; - const static float t2_exp[53] = { - 9.0380036e-04, - -2.0680559e-04, - -1.2368630e-03, - -2.9635796e-04, - 1.7716263e-03, - 1.3578053e-03, - -2.1996482e-03, - -3.2691427e-03, - 1.8837767e-03, - 5.9839217e-03, - -6.4197810e-18, - -8.9372853e-03, - -4.2110807e-03, - 1.0980885e-02, - 1.1155456e-02, - -1.0438956e-02, - -2.0653054e-02, - 5.1948633e-03, - 3.1845711e-02, - 7.4877902e-03, - -4.3292396e-02, - -3.2450620e-02, - 5.3242393e-02, - 8.5484132e-02, - -6.0021374e-02, - -3.1078172e-01, - 5.6184036e-01, - -3.1078172e-01, - -6.0021374e-02, - 8.5484132e-02, - 5.3242393e-02, - -3.2450620e-02, - -4.3292396e-02, - 7.4877902e-03, - 3.1845711e-02, - 5.1948633e-03, - -2.0653054e-02, - -1.0438956e-02, - 1.1155456e-02, - 1.0980885e-02, - -4.2110807e-03, - -8.9372853e-03, - -6.4197810e-18, - 5.9839217e-03, - 1.8837767e-03, - -3.2691427e-03, - -2.1996482e-03, - 1.3578053e-03, - 1.7716263e-03, - -2.9635796e-04, - -1.2368630e-03, - -2.0680559e-04, - 9.0380036e-04 + const static float t2_exp[39] = { + -0.00111255341, 0.000582886743, 0.00192370394, -2.30611317e-18, -0.0036777542, + -0.00198445749, 0.00586195057, 0.00665180339, -0.00685472786, -0.0147390282, + 0.00398152089, 0.0259364359, 0.00641921535, -0.0387352072, -0.0300688613, + 0.0507286265, 0.0831939653, -0.0592906512, -0.309726775, 0.561578512, + -0.309726775, -0.0592906512, 0.0831939653, 0.0507286265, -0.0300688613, + -0.0387352072, 0.00641921535, 0.0259364359, 0.00398152089, -0.0147390282, + -0.00685472786, 0.00665180339, 0.00586195057, -0.00198445749, -0.0036777542, + -2.30611317e-18, 0.00192370394, 0.000582886743, -0.00111255341 }; - - const static float t3_exp[107] = { - -1.8970841e-06, - -7.1057165e-04, - 5.4005696e-04, - 4.6233178e-04, - 2.0572044e-04, - 3.5209916e-04, - -1.4098573e-03, - 1.1279077e-04, - -6.2994129e-04, - 1.1450432e-03, - 1.3637283e-03, - -6.4360141e-04, - 3.6509900e-04, - -3.2864159e-03, - 7.0192874e-04, - 3.7524730e-04, - 2.0256115e-03, - 3.0641893e-03, - -3.6618244e-03, - 7.5592739e-05, - -5.5586505e-03, - 2.3849572e-03, - 4.0114378e-03, - 1.6636450e-03, - 4.7835698e-03, - -1.0191196e-02, - -3.8158931e-04, - -5.5551580e-03, - 5.3901658e-03, - 1.1366769e-02, - -3.0000482e-03, - 4.9341680e-03, - -2.0093076e-02, - 5.5752542e-17, - 1.2093617e-03, - 8.6089745e-03, - 2.2382140e-02, - -1.6854567e-02, - 1.6913920e-03, - -3.1222520e-02, - 3.2711059e-03, - 2.2604836e-02, - 8.1451107e-03, - 3.7583180e-02, - -5.2293688e-02, - -8.0551542e-03, - -4.0092729e-02, - 1.5582236e-02, - 9.7452506e-02, - -1.6183170e-02, - 8.3281815e-02, - -2.8196752e-01, - -1.0965768e-01, - 5.2867508e-01, - -1.0965768e-01, - -2.8196752e-01, - 8.3281815e-02, - -1.6183170e-02, - 9.7452506e-02, - 1.5582236e-02, - -4.0092729e-02, - -8.0551542e-03, - -5.2293688e-02, - 3.7583180e-02, - 8.1451107e-03, - 2.2604836e-02, - 3.2711059e-03, - -3.1222520e-02, - 1.6913920e-03, - -1.6854567e-02, - 2.2382140e-02, - 8.6089745e-03, - 1.2093617e-03, - 5.5752542e-17, - -2.0093076e-02, - 4.9341680e-03, - -3.0000482e-03, - 1.1366769e-02, - 5.3901658e-03, - -5.5551580e-03, - -3.8158931e-04, - -1.0191196e-02, - 4.7835698e-03, - 1.6636450e-03, - 4.0114378e-03, - 2.3849572e-03, - -5.5586505e-03, - 7.5592739e-05, - -3.6618244e-03, - 3.0641893e-03, - 2.0256115e-03, - 3.7524730e-04, - 7.0192874e-04, - -3.2864159e-03, - 3.6509900e-04, - -6.4360141e-04, - 1.3637283e-03, - 1.1450432e-03, - -6.2994129e-04, - 1.1279077e-04, - -1.4098573e-03, - 3.5209916e-04, - 2.0572044e-04, - 4.6233178e-04, - 5.4005696e-04, - -7.1057165e-04, - -1.8970841e-06 + + const static float t3_exp[77] = { + 0.000119983582, 0.000607753696, 0.000897691818, -0.0010834164, 2.31763315e-05, + -0.00179765455, 0.000822491478, 0.0014836716, 0.000661226455, 0.00204213755, + -0.00466352375, -0.000186616904, -0.00289339852, 0.00297895772, 0.00664081471, + -0.00184599939, 0.00318629085, -0.0135707017, 3.90737225e-17, 0.000884963025, + 0.00652826019, 0.0175401419, -0.013614703, 0.00140484457, -0.0266032815, + 0.00285289111, 0.0201372877, 0.00739659835, 0.0347237773, -0.0490655154, + -0.00766157778, -0.0385900773, 0.0151521852, 0.0955788717, -0.0159830209, + 0.0826964602, -0.281061709, -0.109556615, 0.528591633, -0.109556615, + -0.281061709, 0.0826964602, -0.0159830209, 0.0955788717, 0.0151521852, + -0.0385900773, -0.00766157778, -0.0490655154, 0.0347237773, 0.00739659835, + 0.0201372877, 0.00285289111, -0.0266032815, 0.00140484457, -0.013614703, + 0.0175401419, 0.00652826019, 0.000884963025, 3.90737225e-17, -0.0135707017, + 0.00318629085, -0.00184599939, 0.00664081471, 0.00297895772, -0.00289339852, + -0.000186616904, -0.00466352375, 0.00204213755, 0.000661226455, 0.0014836716, + 0.000822491478, -0.00179765455, 2.31763315e-05, -0.0010834164, 0.000897691818, + 0.000607753696, 0.000119983582 }; - - const static float t4_exp[] = { // low pass - 0.001059958362, - 0.0002263929928, - -0.001277606934, - -0.0009675776237, - 0.001592264394, - 0.00243603508, - -0.001451682881, - -0.004769335967, - 5.281541594e-18, - 0.007567512803, - 0.003658855334, - -0.009761494584, - -0.01011830103, - 0.009636915289, - 0.0193619132, - -0.004935568199, - -0.03060629964, - -0.007267376408, - 0.04236677289, - 0.03197422624, - -0.05274848267, - -0.0850463286, - 0.05989059806, - 0.31065014, - 0.4370569289, - 0.31065014, - 0.05989059806, - -0.0850463286, - -0.05274848267, - 0.03197422624, - 0.04236677289, - -0.007267376408, - -0.03060629964, - -0.004935568199, - 0.0193619132, - 0.009636915289, - -0.01011830103, - -0.009761494584, - 0.003658855334, - 0.007567512803, - 5.281541594e-18, - -0.004769335967, - -0.001451682881, - 0.00243603508, - 0.001592264394, - -0.0009675776237, - -0.001277606934, - 0.0002263929928, - 0.001059958362, + + const static float t4_exp[49] = { // low pass + 0.00105995836, 0.000226392993, -0.00127760693, -0.000967577624, 0.00159226439, + 0.00243603508, -0.00145168288, -0.00476933597, 5.28154159e-18, 0.0075675128, + 0.00365885533, -0.00976149458, -0.010118301, 0.00963691529, 0.0193619132, + -0.0049355682, -0.0306062996, -0.00726737641, 0.0423667729, 0.0319742262, + -0.0527484827, -0.0850463286, 0.0598905981, 0.31065014, 0.437056929, + 0.31065014, 0.0598905981, -0.0850463286, -0.0527484827, 0.0319742262, + 0.0423667729, -0.00726737641, -0.0306062996, -0.0049355682, 0.0193619132, + 0.00963691529, -0.010118301, -0.00976149458, 0.00365885533, 0.0075675128, + 5.28154159e-18, -0.00476933597, -0.00145168288, 0.00243603508, 0.00159226439, + -0.000967577624, -0.00127760693, 0.000226392993, 0.00105995836 }; - const static float t5_exp[] = { //high pass - -0.001062123571, - -0.0002268554381, - 0.001280216733, - 0.000969554123, - -0.001595516922, - -0.002441011136, - 0.001454648213, - 0.004779078532, - -5.292330097e-18, - -0.007582970895, - -0.00366632943, - 0.009781434201, - 0.01013896987, - -0.009656600654, - -0.01940146461, - 0.004945650231, - 0.03066881932, - 0.00728222169, - -0.04245331511, - -0.03203954175, - 0.05285623297, - 0.08522006124, - -0.06001294032, - -0.3112847209, - 0.5630782247, - -0.3112847209, - -0.06001294032, - 0.08522006124, - 0.05285623297, - -0.03203954175, - -0.04245331511, - 0.00728222169, - 0.03066881932, - 0.004945650231, - -0.01940146461, - -0.009656600654, - 0.01013896987, - 0.009781434201, - -0.00366632943, - -0.007582970895, - -5.292330097e-18, - 0.004779078532, - 0.001454648213, - -0.002441011136, - -0.001595516922, - 0.000969554123, - 0.001280216733, - -0.0002268554381, - -0.001062123571, + const static float t5_exp[49] = { //high pass + -0.00106212357, -0.000226855438, 0.00128021673, 0.000969554123, -0.00159551692, + -0.00244101114, 0.00145464821, 0.00477907853, -5.2923301e-18, -0.00758297089, + -0.00366632943, 0.0097814342, 0.0101389699, -0.00965660065, -0.0194014646, + 0.00494565023, 0.0306688193, 0.00728222169, -0.0424533151, -0.0320395418, + 0.052856233, 0.0852200612, -0.0600129403, -0.311284721, 0.563078225, + -0.311284721, -0.0600129403, 0.0852200612, 0.052856233, -0.0320395418, + -0.0424533151, 0.00728222169, 0.0306688193, 0.00494565023, -0.0194014646, + -0.00965660065, 0.0101389699, 0.0097814342, -0.00366632943, -0.00758297089, + -5.2923301e-18, 0.00477907853, 0.00145464821, -0.00244101114, -0.00159551692, + 0.000969554123, 0.00128021673, -0.000226855438, -0.00106212357 }; - + const static float t6_exp[] = { // bandpass - 0.0002809273137, - -0.001047327649, - 7.936541806e-05, - -0.0004270860809, - 0.0007595835486, - 0.0008966081077, - -0.0004236323002, - 0.0002423936094, - -0.002212299034, - 0.0004807534278, - 0.0002620361629, - 0.001443728455, - 0.002229931997, - -0.002720607212, - 5.731141573e-05, - -0.004297634587, - 0.001878833398, - 0.003217151389, - 0.001357055153, - 0.003965090029, - -0.008576190099, - -0.0003257228818, - -0.004805727862, - 0.004721920472, - 0.01007549558, - -0.002688719891, - 0.004467967432, - -0.01837076992, - 5.119658377e-17, - 0.001125075156, - 0.008071650751, - 0.02113764361, - -0.01602453552, - 0.001618095324, - -0.03004053794, - 0.003163811285, - 0.0219683405, - 0.007950295694, - 0.03682873398, - -0.05142467469, - -0.00794606097, - -0.03965795785, - 0.01544955093, - 0.09681399167, - -0.01610304788, - 0.08297294378, - -0.2811714709, - -0.1094062924, - 0.5275565982, - -0.1094062924, - -0.2811714709, - 0.08297294378, - -0.01610304788, - 0.09681399167, - 0.01544955093, - -0.03965795785, - -0.00794606097, - -0.05142467469, - 0.03682873398, - 0.007950295694, - 0.0219683405, - 0.003163811285, - -0.03004053794, - 0.001618095324, - -0.01602453552, - 0.02113764361, - 0.008071650751, - 0.001125075156, - 5.119658377e-17, - -0.01837076992, - 0.004467967432, - -0.002688719891, - 0.01007549558, - 0.004721920472, - -0.004805727862, - -0.0003257228818, - -0.008576190099, - 0.003965090029, - 0.001357055153, - 0.003217151389, - 0.001878833398, - -0.004297634587, - 5.731141573e-05, - -0.002720607212, - 0.002229931997, - 0.001443728455, - 0.0002620361629, - 0.0004807534278, - -0.002212299034, - 0.0002423936094, - -0.0004236323002, - 0.0008966081077, - 0.0007595835486, - -0.0004270860809, - 7.936541806e-05, - -0.001047327649, - 0.0002809273137, + 0.000280927314, -0.00104732765, 7.93654181e-05, -0.000427086081, 0.000759583549, + 0.000896608108, -0.0004236323, 0.000242393609, -0.00221229903, 0.000480753428, + 0.000262036163, 0.00144372846, 0.002229932, -0.00272060721, 5.73114157e-05, + -0.00429763459, 0.0018788334, 0.00321715139, 0.00135705515, 0.00396509003, + -0.0085761901, -0.000325722882, -0.00480572786, 0.00472192047, 0.0100754956, + -0.00268871989, 0.00446796743, -0.0183707699, 5.11965838e-17, 0.00112507516, + 0.00807165075, 0.0211376436, -0.0160245355, 0.00161809532, -0.0300405379, + 0.00316381129, 0.0219683405, 0.00795029569, 0.036828734, -0.0514246747, + -0.00794606097, -0.0396579579, 0.0154495509, 0.0968139917, -0.0161030479, + 0.0829729438, -0.281171471, -0.109406292, 0.527556598, -0.109406292, + -0.281171471, 0.0829729438, -0.0161030479, 0.0968139917, 0.0154495509, + -0.0396579579, -0.00794606097, -0.0514246747, 0.036828734, 0.00795029569, + 0.0219683405, 0.00316381129, -0.0300405379, 0.00161809532, -0.0160245355, + 0.0211376436, 0.00807165075, 0.00112507516, 5.11965838e-17, -0.0183707699, + 0.00446796743, -0.00268871989, 0.0100754956, 0.00472192047, -0.00480572786, + -0.000325722882, -0.0085761901, 0.00396509003, 0.00135705515, 0.00321715139, + 0.0018788334, -0.00429763459, 5.73114157e-05, -0.00272060721, 0.002229932, + 0.00144372846, 0.000262036163, 0.000480753428, -0.00221229903, 0.000242393609, + -0.0004236323, 0.000896608108, 0.000759583549, -0.000427086081, 7.93654181e-05, + -0.00104732765, 0.000280927314 }; void @@ -492,17 +156,17 @@ namespace gr { 1750, 500, firdes::WIN_HAMMING); - - // cout << "ntaps: " << taps.size() << endl; - // print_taps(cout, taps); + + // std::cout << "ntaps: " << taps.size() << std::endl; + // print_taps(std::cout, taps); CPPUNIT_ASSERT_EQUAL(NELEM(t1_exp), taps.size()); for(unsigned int i = 0; i < taps.size(); i++) CPPUNIT_ASSERT_DOUBLES_EQUAL(t1_exp[i], taps[i], 1e-9); check_symmetry(taps); -} - + } + void qa_firdes::t2() { @@ -513,14 +177,14 @@ namespace gr { 500, firdes::WIN_HAMMING); - // cout << "ntaps: " << taps.size() << endl; - // print_taps(cout, taps); - + // std::cout << "ntaps: " << taps.size() << std::endl; + // print_taps(std::cout, taps); + CPPUNIT_ASSERT_EQUAL(NELEM(t2_exp), taps.size()); for(unsigned int i = 0; i < taps.size(); i++) CPPUNIT_ASSERT_DOUBLES_EQUAL(t2_exp[i], taps[i], 1e-9); - + check_symmetry(taps); } @@ -535,8 +199,8 @@ namespace gr { 0.62e6, firdes::WIN_HAMMING); - // cout << "ntaps: " << taps.size() << endl; - // print_taps(cout, taps); + // std::cout << "ntaps: " << taps.size() << std::endl; + // print_taps(std::cout, taps); CPPUNIT_ASSERT_EQUAL(NELEM(t3_exp), taps.size()); @@ -557,8 +221,8 @@ namespace gr { 66, firdes::WIN_HAMMING); - // std::cout << "ntaps: " << taps.size() << std::endl; - // print_taps(std::cout, taps); + // std::cout << "ntaps: " << taps.size() << std::endl; + // print_taps(std::cout, taps); CPPUNIT_ASSERT_EQUAL(NELEM(t4_exp), taps.size()); for(unsigned int i = 0; i < taps.size(); i++) @@ -578,14 +242,14 @@ namespace gr { 66, firdes::WIN_HAMMING); - // std::cout << "ntaps: " << taps.size() << std::endl; - // print_taps(std::cout, taps); + // std::cout << "ntaps: " << taps.size() << std::endl; + // print_taps(std::cout, taps); CPPUNIT_ASSERT_EQUAL(NELEM(t5_exp), taps.size()); for(unsigned int i = 0; i < taps.size(); i++) CPPUNIT_ASSERT_DOUBLES_EQUAL(t5_exp[i], taps[i], 1e-9); - + check_symmetry(taps); } @@ -601,8 +265,8 @@ namespace gr { 66, firdes::WIN_HAMMING); - // std::cout << "ntaps: " << taps.size() << std::endl; - // print_taps(std::cout, taps); + // std::cout << "ntaps: " << taps.size() << std::endl; + // print_taps(std::cout, taps); CPPUNIT_ASSERT_EQUAL(NELEM(t6_exp), taps.size()); diff --git a/gr-filter/python/filter/pfb.py b/gr-filter/python/filter/pfb.py index 52f598cc40..2ddf65962c 100644 --- a/gr-filter/python/filter/pfb.py +++ b/gr-filter/python/filter/pfb.py @@ -169,6 +169,12 @@ class decimator_ccf(gr.hier_block2): self.connect(self.pfb, self) + def set_taps(self, taps): + self.pfb.set_taps(taps) + + def set_channel(self, chan): + self.pfb.set_channel(chan) + class arb_resampler_ccf(gr.hier_block2): ''' diff --git a/gr-filter/python/filter/qa_adaptive_fir_filter.py b/gr-filter/python/filter/qa_adaptive_fir_filter.py deleted file mode 100755 index cb82c7e969..0000000000 --- a/gr-filter/python/filter/qa_adaptive_fir_filter.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008,2010,2012,2013 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# - -from gnuradio import gr, gr_unittest, filter, blocks - -def fir_filter(x, taps, decim=1): - y = [] - x2 = (len(taps)-1)*[0,] + x - for i in range(0, len(x), decim): - yi = 0 - for j in range(len(taps)): - yi += taps[len(taps)-1-j] * x2[i+j] - y.append(yi) - return y - -class test_adaptive_filter(gr_unittest.TestCase): - - def setUp(self): - self.tb = gr.top_block () - - def tearDown(self): - self.tb = None - - def test_adaptive_fir_filter_ccf_001(self): - decim = 1 - taps = 20*[0.5, 0.5] - src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] - expected_data = fir_filter(src_data, taps, decim) - - src = blocks.vector_source_c(src_data) - op = filter.adaptive_fir_ccf("test", decim, taps) - dst = blocks.vector_sink_c() - self.tb.connect(src, op, dst) - self.tb.run() - result_data = dst.data() - self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) - - def test_adaptive_fir_filter_ccf_002(self): - decim = 4 - taps = 20*[0.5, 0.5] - src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] - expected_data = fir_filter(src_data, taps, decim) - - src = blocks.vector_source_c(src_data) - op = filter.adaptive_fir_ccf("test", decim, taps) - dst = blocks.vector_sink_c() - self.tb.connect(src, op, dst) - self.tb.run() - result_data = dst.data() - self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) - - def test_adaptive_fir_filter_ccc_001(self): - decim = 1 - taps = 20*[0.5+1j, 0.5+1j] - src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] - expected_data = fir_filter(src_data, taps, decim) - - src = blocks.vector_source_c(src_data) - op = filter.adaptive_fir_ccc("test", decim, taps) - dst = blocks.vector_sink_c() - self.tb.connect(src, op, dst) - self.tb.run() - result_data = dst.data() - self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) - - - def test_adaptive_fir_filter_ccc_002(self): - decim = 4 - taps = 20*[0.5+1j, 0.5+1j] - src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] - expected_data = fir_filter(src_data, taps, decim) - - src = blocks.vector_source_c(src_data) - op = filter.adaptive_fir_ccc("test", decim, taps) - dst = blocks.vector_sink_c() - self.tb.connect(src, op, dst) - self.tb.run() - result_data = dst.data() - self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) - -if __name__ == '__main__': - gr_unittest.run(test_adaptive_filter, "test_adaptive_filter.xml") - diff --git a/gr-filter/python/filter/qa_firdes.py b/gr-filter/python/filter/qa_firdes.py index d38af31822..b32e5b2f91 100755 --- a/gr-filter/python/filter/qa_firdes.py +++ b/gr-filter/python/filter/qa_firdes.py @@ -32,15 +32,14 @@ class test_firdes(gr_unittest.TestCase): pass def test_low_pass(self): - known_taps = (0.0030193300917744637, -0.004960992839187384, - 0.006678304169327021, -1.132049690556083e-17, - -0.0251916591078043, 0.07206480950117111, - -0.13062666356563568, 0.18007083237171173, - 0.7978920936584473, 0.18007083237171173, - -0.13062666356563568, 0.07206480950117111, - -0.0251916591078043, -1.132049690556083e-17, - 0.006678304169327021, -0.004960992839187384, - 0.0030193300917744637) + known_taps = (0.0024871660862118006, -4.403502608370943e-18, + -0.014456653036177158, 0.0543283149600029, + -0.116202212870121, 0.17504146695137024, + 0.7976038455963135, 0.17504146695137024, + -0.116202212870121, 0.0543283149600029, + -0.014456653036177158, -4.403502608370943e-18, + 0.0024871660862118006) + new_taps = filter.firdes.low_pass(1, 1, 0.4, 0.2) self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) @@ -56,15 +55,13 @@ class test_firdes(gr_unittest.TestCase): self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) def test_high_pass(self): - known_taps = (-0.003062003292143345, 0.005031108390539885, - -0.0067726909182965755, 1.1480492661182674e-17, - 0.025547700002789497, -0.0730833187699318, - 0.13247284293174744, -0.18261581659317017, - 0.20229223370552063, -0.18261581659317017, - 0.13247284293174744, -0.0730833187699318, - 0.025547700002789497, 1.1480492661182674e-17, - -0.0067726909182965755, 0.005031108390539885, - -0.003062003292143345) + known_taps = (-0.0027197482995688915, 4.815287179370254e-18, + 0.01580853760242462, -0.05940871313214302, + 0.1270686239004135, -0.1914101094007492, + 0.21804752945899963, -0.1914101094007492, + 0.1270686239004135, -0.05940871313214302, + 0.01580853760242462, 4.815287179370254e-18, + -0.0027197482995688915) new_taps = filter.firdes.high_pass(1, 1, 0.4, 0.2) self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) @@ -80,15 +77,13 @@ class test_firdes(gr_unittest.TestCase): self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) def test_band_pass(self): - known_taps = (0.004961997736245394, -0.008152946829795837, - -0.004192151129245758, -5.749020235348687e-18, - 0.01581347920000553, 0.11843203753232956, - -0.21467317640781403, -0.11303528398275375, - 0.40520283579826355, -0.11303528398275375, - -0.21467317640781403, 0.11843203753232956, - 0.01581347920000553, -5.749020235348687e-18, - -0.004192151129245758, -0.008152946829795837, - 0.004961997736245394) + known_taps = (-0.001676854444667697, -2.4018533253972557e-18, + 0.009746716357767582, 0.09589414298534393, + -0.20510689914226532, -0.11801345646381378, + 0.4350462853908539, -0.11801345646381378, + -0.20510689914226532, 0.09589414298534393, + 0.009746716357767582, -2.4018533253972557e-18, + -0.001676854444667697) new_taps = filter.firdes.band_pass(1, 1, 0.2, 0.4, 0.2) self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) @@ -104,23 +99,19 @@ class test_firdes(gr_unittest.TestCase): self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) def test_complex_band_pass(self): - known_taps = ((0.0024772135075181723+0.0017997993854805827j), - (-0.004070250317454338+0.002957213670015335j), - (-0.0020928815938532352-0.006441210396587849j), - (-2.8701231652956686e-18+2.805614574993832e-24j), - (0.007894645445048809-0.024297315627336502j), - (0.05912570655345917+0.04295721650123596j), - (-0.10717268288135529+0.07786571979522705j), - (-0.0564316064119339-0.17367789149284363j), - (0.20229223370552063-2.4115112751132983e-07j), - (-0.05643119290471077+0.17367802560329437j), - (-0.10717286914587021-0.07786546647548676j), - (0.05912560224533081-0.0429573580622673j), - (0.007894691079854965+0.024297300726175308j), - (-2.8701231652956686e-18+2.6687109203363464e-24j), - (-0.0020928694866597652+0.006441214121878147j), - (-0.004070255905389786-0.0029572059866040945j), - (0.0024772100150585175-0.0017998040420934558j)) + known_taps = ((-0.0008404505206272006-0.0025866336654871702j), + (-1.2038217948425635e-18+1.1767648157397848e-24j), + (0.0048850891180336475-0.015034818090498447j), + (0.048062704503536224+0.03491950035095215j), + (-0.10280057787895203+0.07468919456005096j), + (-0.05914920195937157-0.18204176425933838j), + (0.21804752945899963-2.5993290364567656e-07j), + (-0.059148769825696945+0.18204189836978912j), + (-0.10280075669288635-0.07468894869089127j), + (0.04806262254714966-0.0349196158349514j), + (0.004885117989033461+0.015034808777272701j), + (-1.2038217948425635e-18+1.1193430388030685e-24j), + (-0.000840445572976023+0.002586635295301676j)) new_taps = filter.firdes.complex_band_pass(1, 1, 0.2, 0.4, 0.2) self.assertComplexTuplesAlmostEqual(known_taps, new_taps, 5) @@ -142,15 +133,13 @@ class test_firdes(gr_unittest.TestCase): self.assertComplexTuplesAlmostEqual(known_taps, new_taps, 5) def test_band_reject(self): - known_taps = (-0.004915320314466953, 0.008076251484453678, - 0.00415271520614624, 5.694938753309664e-18, - -0.01566472090780735, -0.11731793731451035, - 0.2126537412405014, 0.11197195947170258, - 0.6020866632461548, 0.11197195947170258, - 0.2126537412405014, -0.11731793731451035, - -0.01566472090780735, 5.694938753309664e-18, - 0.00415271520614624, 0.008076251484453678, - -0.004915320314466953) + known_taps = (0.0015371545450761914, 2.201753372137003e-18, + -0.00893471110612154, -0.08790513873100281, + 0.1880193054676056, 0.1081816703081131, + 0.5982034206390381, 0.1081816703081131, + 0.1880193054676056, -0.08790513873100281, + -0.00893471110612154, 2.201753372137003e-18, + 0.0015371545450761914) new_taps = filter.firdes.band_reject(1, 1, 0.2, 0.4, 0.2) self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) diff --git a/gr-filter/python/filter/qa_freq_xlating_fir_filter.py b/gr-filter/python/filter/qa_freq_xlating_fir_filter.py index 39a803715e..ca5245db64 100755 --- a/gr-filter/python/filter/qa_freq_xlating_fir_filter.py +++ b/gr-filter/python/filter/qa_freq_xlating_fir_filter.py @@ -91,7 +91,7 @@ class test_freq_xlating_filter(gr_unittest.TestCase): def generate_scf_source(self): self.fs = fs = 1 self.fc = fc = 0.3 - self.bw = bw = 0.1 + self.bw = bw = 0.12 self.taps = filter.firdes.low_pass(1, fs, bw, bw/4) times = xrange(100) self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times) @@ -99,7 +99,7 @@ class test_freq_xlating_filter(gr_unittest.TestCase): def generate_scc_source(self): self.fs = fs = 1 self.fc = fc = 0.3 - self.bw = bw = 0.1 + self.bw = bw = 0.12 self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4) times = xrange(100) self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times) diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i index b7d3656bcf..aad96e5c86 100644 --- a/gr-filter/swig/filter_swig.i +++ b/gr-filter/swig/filter_swig.i @@ -30,8 +30,6 @@ %{ #include "gnuradio/filter/firdes.h" #include "gnuradio/filter/pm_remez.h" -#include "gnuradio/filter/adaptive_fir_ccc.h" -#include "gnuradio/filter/adaptive_fir_ccf.h" #include "gnuradio/filter/dc_blocker_cc.h" #include "gnuradio/filter/dc_blocker_ff.h" #include "gnuradio/filter/filter_delay_fc.h" @@ -79,8 +77,6 @@ %include "gnuradio/filter/firdes.h" %include "gnuradio/filter/pm_remez.h" -%include "gnuradio/filter/adaptive_fir_ccc.h" -%include "gnuradio/filter/adaptive_fir_ccf.h" %include "gnuradio/filter/dc_blocker_cc.h" %include "gnuradio/filter/dc_blocker_ff.h" %include "gnuradio/filter/filter_delay_fc.h" @@ -125,8 +121,6 @@ %include "gnuradio/filter/single_pole_iir_filter_cc.h" %include "gnuradio/filter/single_pole_iir_filter_ff.h" -GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccc); -GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccf); GR_SWIG_BLOCK_MAGIC2(filter, dc_blocker_cc); GR_SWIG_BLOCK_MAGIC2(filter, dc_blocker_ff); GR_SWIG_BLOCK_MAGIC2(filter, filter_delay_fc); diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml b/gr-qtgui/grc/qtgui_freq_sink_x.xml index 35edf61ed8..6a61a05e0f 100644 --- a/gr-qtgui/grc/qtgui_freq_sink_x.xml +++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml @@ -78,6 +78,10 @@ $(gui_hint()($win))</make> <name>Kaiser</name> <key>firdes.WIN_KAISER</key> </option> + <option> + <name>Flat-top</name> + <key>firdes.WIN_FLATTOP</key> + </option> </param> <param> <name>Center Frequency (Hz)</name> diff --git a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml index 176a907e9e..ac08450730 100644 --- a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml +++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml @@ -77,6 +77,10 @@ $(gui_hint()($win))</make> <name>Kaiser</name> <key>firdes.WIN_KAISER</key> </option> + <option> + <name>Flat-top</name> + <key>firdes.WIN_FLATTOP</key> + </option> </param> <param> <name>Center Frequency (Hz)</name> diff --git a/gr-qtgui/include/gnuradio/qtgui/form_menus.h b/gr-qtgui/include/gnuradio/qtgui/form_menus.h index d6499572c3..e7ebc3a797 100644 --- a/gr-qtgui/include/gnuradio/qtgui/form_menus.h +++ b/gr-qtgui/include/gnuradio/qtgui/form_menus.h @@ -26,6 +26,8 @@ #include <stdexcept> #include <vector> #include <QtGui/QtGui> +#include <QtGui/QIntValidator> +#include <QtGui/QDoubleValidator> #include <qwt_symbol.h> #include <gnuradio/filter/firdes.h> #include <gnuradio/qtgui/qtgui_types.h> @@ -498,6 +500,16 @@ public: ~OtherAction() {} + void setValidator(QValidator *v) + { + d_text->setValidator(v); + } + + void setDiagText(QString text) + { + d_text->setText(text); + } + signals: void whichTrigger(const QString &text); @@ -603,11 +615,20 @@ public: d_act.push_back(new QAction("1024", this)); d_act.push_back(new QAction("2048", this)); d_act.push_back(new QAction("4096", this)); - d_act.push_back(new QAction("8192", this)); - d_act.push_back(new QAction("16384", this)); - d_act.push_back(new QAction("32768", this)); + //d_act.push_back(new QAction("8192", this)); + //d_act.push_back(new QAction("16384", this)); + //d_act.push_back(new QAction("32768", this)); d_act.push_back(new OtherAction(this)); + d_grp = new QActionGroup(this); + for(int t = 0; t < d_act.size(); t++) { + d_act[t]->setCheckable(true); + d_act[t]->setActionGroup(d_grp); + } + + QIntValidator *valid = new QIntValidator(32, 4096, this); + ((OtherAction*)d_act[d_act.size()-1])->setValidator(valid); + connect(d_act[0], SIGNAL(triggered()), this, SLOT(get05())); connect(d_act[1], SIGNAL(triggered()), this, SLOT(get06())); connect(d_act[2], SIGNAL(triggered()), this, SLOT(get07())); @@ -616,59 +637,78 @@ public: connect(d_act[5], SIGNAL(triggered()), this, SLOT(get10())); connect(d_act[6], SIGNAL(triggered()), this, SLOT(get11())); connect(d_act[7], SIGNAL(triggered()), this, SLOT(get12())); - connect(d_act[8], SIGNAL(triggered()), this, SLOT(get13())); - connect(d_act[9], SIGNAL(triggered()), this, SLOT(get14())); - connect(d_act[10], SIGNAL(triggered()), this, SLOT(get15())); - connect(d_act[11], SIGNAL(whichTrigger(const QString&)), - this, SLOT(getOther(const QString&))); + //connect(d_act[8], SIGNAL(triggered()), this, SLOT(get13())); + //connect(d_act[9], SIGNAL(triggered()), this, SLOT(get14())); + //connect(d_act[10], SIGNAL(triggered()), this, SLOT(get15())); + connect(d_act[8], SIGNAL(whichTrigger(const QString&)), + this, SLOT(getOther(const QString&))); - QListIterator<QAction*> i(d_act); - while(i.hasNext()) { - QAction *a = i.next(); - addAction(a); - } - } + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + } - ~FFTSizeMenu() - {} + ~FFTSizeMenu() + {} - int getNumActions() const - { - return d_act.size(); - } + int getNumActions() const + { + return d_act.size(); + } - QAction * getAction(int which) - { - if(which < d_act.size()) - return d_act[which]; - else - throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n"); - } + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n"); + } - signals: - void whichTrigger(int size); + QAction * getActionFromSize(int size) + { + float ipt; + float which = logf(static_cast<float>(size))/logf(2.0) - 5; + // If we're a predefined value + if(modff(which,&ipt) == 0) { + if(which < d_act.size()-1) + return d_act[static_cast<int>(which)]; + else + throw std::runtime_error("FFTSizeMenu::getActionFromString: which out of range.\n"); + } + // Or a non-predefined value, return Other + else { + ((OtherAction*)d_act[d_act.size()-1])->setDiagText(QString().setNum(size)); + return d_act[d_act.size()-1]; + } + } - public slots: - void get05() { emit whichTrigger(32); } - void get06() { emit whichTrigger(64); } - void get07() { emit whichTrigger(128); } - void get08() { emit whichTrigger(256); } - void get09() { emit whichTrigger(512); } - void get10() { emit whichTrigger(1024); } - void get11() { emit whichTrigger(2048); } - void get12() { emit whichTrigger(4096); } - void get13() { emit whichTrigger(8192); } - void get14() { emit whichTrigger(16384); } - void get15() { emit whichTrigger(32768); } - void getOther(const QString &str) - { - int value = str.toInt(); - emit whichTrigger(value); - } +signals: + void whichTrigger(int size); + +public slots: + void get05() { emit whichTrigger(32); } + void get06() { emit whichTrigger(64); } + void get07() { emit whichTrigger(128); } + void get08() { emit whichTrigger(256); } + void get09() { emit whichTrigger(512); } + void get10() { emit whichTrigger(1024); } + void get11() { emit whichTrigger(2048); } + void get12() { emit whichTrigger(4096); } + //void get13() { emit whichTrigger(8192); } + //void get14() { emit whichTrigger(16384); } + //void get15() { emit whichTrigger(32768); } + void getOther(const QString &str) + { + int value = str.toInt(); + emit whichTrigger(value); + } private: QList<QAction *> d_act; OtherAction *d_other; + QActionGroup *d_grp; }; @@ -683,50 +723,83 @@ public: FFTAverageMenu(QWidget *parent) : QMenu("FFT Average", parent) { + d_off = 1.0; + d_high = 0.05; + d_medium = 0.1; + d_low = 0.2; + d_act.push_back(new QAction("Off", this)); d_act.push_back(new QAction("High", this)); d_act.push_back(new QAction("Medium", this)); d_act.push_back(new QAction("Low", this)); d_act.push_back(new OtherAction(this)); + d_grp = new QActionGroup(this); + for(int t = 0; t < d_act.size(); t++) { + d_act[t]->setCheckable(true); + d_act[t]->setActionGroup(d_grp); + } + d_act[0]->setChecked(true); + + QDoubleValidator *valid = new QDoubleValidator(0.0, 1.0, 2, this); + ((OtherAction*)d_act[d_act.size()-1])->setValidator(valid); + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getOff())); connect(d_act[1], SIGNAL(triggered()), this, SLOT(getHigh())); connect(d_act[2], SIGNAL(triggered()), this, SLOT(getMedium())); connect(d_act[3], SIGNAL(triggered()), this, SLOT(getLow())); connect(d_act[4], SIGNAL(whichTrigger(const QString&)), - this, SLOT(getOther(const QString&))); + this, SLOT(getOther(const QString&))); - QListIterator<QAction*> i(d_act); - while(i.hasNext()) { - QAction *a = i.next(); - addAction(a); - } - } + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + addAction(a); + } + } - ~FFTAverageMenu() - {} + ~FFTAverageMenu() + {} - int getNumActions() const - { - return d_act.size(); - } + int getNumActions() const + { + return d_act.size(); + } - QAction * getAction(int which) - { - if(which < d_act.size()) - return d_act[which]; - else - throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n"); - } + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n"); + } + + QAction * getActionFromAvg(float avg) + { + int which = 0; + if(avg == d_off) + which = 0; + else if(avg == d_high) + which = 1; + else if(avg == d_medium) + which = 2; + else if(avg == d_low) + which = 3; + else { + ((OtherAction*)d_act[d_act.size()-1])->setDiagText(QString().setNum(avg)); + which = 4; + } + return d_act[static_cast<int>(which)]; + } signals: void whichTrigger(float alpha); public slots: - void getOff() { emit whichTrigger(1.0); } - void getHigh() { emit whichTrigger(0.05); } - void getMedium() { emit whichTrigger(0.1); } - void getLow() { emit whichTrigger(0.2); } + void getOff() { emit whichTrigger(d_off); } + void getHigh() { emit whichTrigger(d_high); } + void getMedium() { emit whichTrigger(d_medium); } + void getLow() { emit whichTrigger(d_low); } void getOther(const QString &str) { float value = str.toFloat(); @@ -736,6 +809,8 @@ public: private: QList<QAction *> d_act; OtherAction *d_other; + QActionGroup *d_grp; + float d_off, d_high, d_medium, d_low; }; @@ -757,6 +832,13 @@ public: d_act.push_back(new QAction("Blackman-harris", this)); d_act.push_back(new QAction("Rectangular", this)); d_act.push_back(new QAction("Kaiser", this)); + d_act.push_back(new QAction("Flat-top", this)); + + d_grp = new QActionGroup(this); + for(int t = 0; t < d_act.size(); t++) { + d_act[t]->setCheckable(true); + d_act[t]->setActionGroup(d_grp); + } connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone())); connect(d_act[1], SIGNAL(triggered()), this, SLOT(getHamming())); @@ -765,6 +847,7 @@ public: connect(d_act[4], SIGNAL(triggered()), this, SLOT(getBlackmanharris())); connect(d_act[5], SIGNAL(triggered()), this, SLOT(getRectangular())); connect(d_act[6], SIGNAL(triggered()), this, SLOT(getKaiser())); + connect(d_act[7], SIGNAL(triggered()), this, SLOT(getFlattop())); QListIterator<QAction*> i(d_act); while(i.hasNext()) { @@ -789,6 +872,22 @@ public: throw std::runtime_error("FFTWindowMenu::getAction: which out of range.\n"); } + QAction * getActionFromWindow(gr::filter::firdes::win_type type) + { + int which = 0; + switch(static_cast<int>(type)) { + case((gr::filter::firdes::WIN_NONE)): which = 0; break; + case((gr::filter::firdes::WIN_HAMMING)): which = 1; break; + case((gr::filter::firdes::WIN_HANN)): which = 2; break; + case((gr::filter::firdes::WIN_BLACKMAN)): which = 3; break; + case((gr::filter::firdes::WIN_BLACKMAN_hARRIS)): which = 4; break; + case((gr::filter::firdes::WIN_RECTANGULAR)): which = 5; break; + case((gr::filter::firdes::WIN_KAISER)): which = 6; break; + case((gr::filter::firdes::WIN_FLATTOP)): which = 7; break; + } + return d_act[which]; + } + signals: void whichTrigger(const gr::filter::firdes::win_type type); @@ -800,9 +899,11 @@ public slots: void getBlackmanharris() { emit whichTrigger(gr::filter::firdes::WIN_BLACKMAN_hARRIS); } void getRectangular() { emit whichTrigger(gr::filter::firdes::WIN_RECTANGULAR); } void getKaiser() { emit whichTrigger(gr::filter::firdes::WIN_KAISER); } + void getFlattop() { emit whichTrigger(gr::filter::firdes::WIN_FLATTOP); } private: QList<QAction *> d_act; + QActionGroup *d_grp; int d_which; }; diff --git a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h index 9a69810276..95e6337f04 100644 --- a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h +++ b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h @@ -73,6 +73,11 @@ private: int d_fftsize; float d_fftavg; gr::filter::firdes::win_type d_fftwintype; + + FFTSizeMenu *d_sizemenu; + FFTAverageMenu *d_avgmenu; + FFTWindowMenu *d_winmenu; + }; #endif /* FREQ_DISPLAY_FORM_H */ diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h b/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h index 926d1cec12..1ac1cf428f 100644 --- a/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h +++ b/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h @@ -92,6 +92,10 @@ private: double d_min_val; double d_max_val; + + FFTSizeMenu *d_sizemenu; + FFTAverageMenu *d_avgmenu; + FFTWindowMenu *d_winmenu; }; #endif /* WATERFALL_DISPLAY_FORM_H */ diff --git a/gr-qtgui/lib/freqdisplayform.cc b/gr-qtgui/lib/freqdisplayform.cc index 46050d8149..32d82b9a8d 100644 --- a/gr-qtgui/lib/freqdisplayform.cc +++ b/gr-qtgui/lib/freqdisplayform.cc @@ -40,17 +40,17 @@ FreqDisplayForm::FreqDisplayForm(int nplots, QWidget* parent) d_fftsize = 1024; d_fftavg = 1.0; - FFTSizeMenu *sizemenu = new FFTSizeMenu(this); - FFTAverageMenu *avgmenu = new FFTAverageMenu(this); - FFTWindowMenu *winmenu = new FFTWindowMenu(this); - d_menu->addMenu(sizemenu); - d_menu->addMenu(avgmenu); - d_menu->addMenu(winmenu); - connect(sizemenu, SIGNAL(whichTrigger(int)), + d_sizemenu = new FFTSizeMenu(this); + d_avgmenu = new FFTAverageMenu(this); + d_winmenu = new FFTWindowMenu(this); + d_menu->addMenu(d_sizemenu); + d_menu->addMenu(d_avgmenu); + d_menu->addMenu(d_winmenu); + connect(d_sizemenu, SIGNAL(whichTrigger(int)), this, SLOT(setFFTSize(const int))); - connect(avgmenu, SIGNAL(whichTrigger(float)), + connect(d_avgmenu, SIGNAL(whichTrigger(float)), this, SLOT(setFFTAverage(const float))); - connect(winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)), + connect(d_winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)), this, SLOT(setFFTWindowType(const gr::filter::firdes::win_type))); Reset(); @@ -120,6 +120,7 @@ void FreqDisplayForm::setFFTSize(const int newsize) { d_fftsize = newsize; + d_sizemenu->getActionFromSize(newsize)->setChecked(true); getPlot()->replot(); } @@ -127,6 +128,7 @@ void FreqDisplayForm::setFFTAverage(const float newavg) { d_fftavg = newavg; + d_avgmenu->getActionFromAvg(newavg)->setChecked(true); getPlot()->replot(); } @@ -134,6 +136,7 @@ void FreqDisplayForm::setFFTWindowType(const gr::filter::firdes::win_type newwin) { d_fftwintype = newwin; + d_winmenu->getActionFromWindow(newwin)->setChecked(true); getPlot()->replot(); } diff --git a/gr-qtgui/lib/waterfalldisplayform.cc b/gr-qtgui/lib/waterfalldisplayform.cc index 4b8e042658..f4dd2fd338 100644 --- a/gr-qtgui/lib/waterfalldisplayform.cc +++ b/gr-qtgui/lib/waterfalldisplayform.cc @@ -75,17 +75,17 @@ WaterfallDisplayForm::WaterfallDisplayForm(int nplots, QWidget* parent) d_autoscale_act->setText(tr("Auto Scale")); d_autoscale_act->setCheckable(false); - FFTSizeMenu *sizemenu = new FFTSizeMenu(this); - FFTAverageMenu *avgmenu = new FFTAverageMenu(this); - FFTWindowMenu *winmenu = new FFTWindowMenu(this); - d_menu->addMenu(sizemenu); - d_menu->addMenu(avgmenu); - d_menu->addMenu(winmenu); - connect(sizemenu, SIGNAL(whichTrigger(int)), + d_sizemenu = new FFTSizeMenu(this); + d_avgmenu = new FFTAverageMenu(this); + d_winmenu = new FFTWindowMenu(this); + d_menu->addMenu(d_sizemenu); + d_menu->addMenu(d_avgmenu); + d_menu->addMenu(d_winmenu); + connect(d_sizemenu, SIGNAL(whichTrigger(int)), this, SLOT(setFFTSize(const int))); - connect(avgmenu, SIGNAL(whichTrigger(float)), + connect(d_avgmenu, SIGNAL(whichTrigger(float)), this, SLOT(setFFTAverage(const float))); - connect(winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)), + connect(d_winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)), this, SLOT(setFFTWindowType(const gr::filter::firdes::win_type))); Reset(); @@ -190,18 +190,24 @@ void WaterfallDisplayForm::setFFTSize(const int newsize) { d_fftsize = newsize; + d_sizemenu->getActionFromSize(newsize)->setChecked(true); + getPlot()->replot(); } void WaterfallDisplayForm::setFFTAverage(const float newavg) { d_fftavg = newavg; + d_avgmenu->getActionFromAvg(newavg)->setChecked(true); + getPlot()->replot(); } void WaterfallDisplayForm::setFFTWindowType(const gr::filter::firdes::win_type newwin) { d_fftwintype = newwin; + d_winmenu->getActionFromWindow(newwin)->setChecked(true); + getPlot()->replot(); } void diff --git a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt index 2dac3461a8..1d2e37b6a6 100644 --- a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt +++ b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt @@ -83,20 +83,15 @@ set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks) ######################################################################## # Find gnuradio build dependencies ######################################################################## -find_package(GnuradioRuntime) find_package(CppUnit) -# To run a more advanced search for GNU Radio and it's components and -# versions, use the following. Add any components required to the list -# of GR_REQUIRED_COMPONENTS (in all caps) and change "version" to the -# minimum API compatible version required. -# -# set(GR_REQUIRED_COMPONENTS RUNTIME BLOCKS FILTER ...) -# find_package(Gnuradio "version") +# Search for GNU Radio and its components and versions. Add any +# components required to the list of GR_REQUIRED_COMPONENTS (in all +# caps such as FILTER or FFT) and change the version to the minimum +# API compatible version required. +set(GR_REQUIRED_COMPONENTS RUNTIME) +find_package(Gnuradio "3.7.2" REQUIRED) -if(NOT GNURADIO_RUNTIME_FOUND) - message(FATAL_ERROR "GnuRadio Runtime required to compile howto") -endif() if(NOT CPPUNIT_FOUND) message(FATAL_ERROR "CppUnit required to compile howto") endif() @@ -111,7 +106,7 @@ include_directories( ${CMAKE_BINARY_DIR}/include ${Boost_INCLUDE_DIRS} ${CPPUNIT_INCLUDE_DIRS} - ${GNURADIO_RUNTIME_INCLUDE_DIRS} + ${GNURADIO_ALL_INCLUDE_DIRS} ) link_directories( diff --git a/gr-utils/python/modtool/gr-newmod/lib/CMakeLists.txt b/gr-utils/python/modtool/gr-newmod/lib/CMakeLists.txt index 312594149c..de53723de2 100644 --- a/gr-utils/python/modtool/gr-newmod/lib/CMakeLists.txt +++ b/gr-utils/python/modtool/gr-newmod/lib/CMakeLists.txt @@ -29,7 +29,7 @@ list(APPEND howto_sources ) add_library(gnuradio-howto SHARED ${howto_sources}) -target_link_libraries(gnuradio-howto ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES}) +target_link_libraries(gnuradio-howto ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES}) set_target_properties(gnuradio-howto PROPERTIES DEFINE_SYMBOL "gnuradio_howto_EXPORTS") ######################################################################## diff --git a/gr-utils/python/modtool/modtool_base.py b/gr-utils/python/modtool/modtool_base.py index f8fc8639c4..86cbd8f420 100644 --- a/gr-utils/python/modtool/modtool_base.py +++ b/gr-utils/python/modtool/modtool_base.py @@ -141,8 +141,7 @@ class ModTool(object): self._info['is_component'] = False for f in files: if os.path.isfile(f) and f == 'CMakeLists.txt': - if re.search('find_package\(GnuradioRuntime\)', open(f).read()) is not None or \ - re.search('find_package\(Gnuradio(\s+[0-9".]+)?\)', open(f).read()) is not None: + if re.search('find_package\(Gnuradio', open(f).read()) is not None: self._info['version'] = '36' # Might be 37, check that later has_makefile = True elif re.search('GR_REGISTER_COMPONENT', open(f).read()) is not None: diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 87576ccae1..a891298fa4 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -113,7 +113,8 @@ class ActionHandler: Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS, Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY, Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY, - Actions.TYPES_WINDOW_DISPLAY, + Actions.TYPES_WINDOW_DISPLAY, Actions.TOGGLE_BLOCKS_WINDOW, + Actions.TOGGLE_REPORTS_WINDOW, ): action.set_sensitive(True) if not self.init_file_paths: self.init_file_paths = Preferences.files_open() @@ -125,6 +126,8 @@ class ActionHandler: if not self.get_page(): self.main_window.new_page() #ensure that at least a blank page exists self.main_window.btwin.search_entry.hide() + Actions.TOGGLE_REPORTS_WINDOW.set_active(Preferences.reports_window_visibility()) + Actions.TOGGLE_BLOCKS_WINDOW.set_active(Preferences.blocks_window_visibility()) elif action == Actions.APPLICATION_QUIT: if self.main_window.close_pages(): gtk.main_quit() @@ -349,6 +352,14 @@ class ActionHandler: Dialogs.TypesDialog(self.get_flow_graph().get_parent()) elif action == Actions.ERRORS_WINDOW_DISPLAY: Dialogs.ErrorsDialog(self.get_flow_graph()) + elif action == Actions.TOGGLE_REPORTS_WINDOW: + visible = action.get_active() + self.main_window.reports_scrolled_window.set_visible(visible) + Preferences.reports_window_visibility(visible) + elif action == Actions.TOGGLE_BLOCKS_WINDOW: + visible = action.get_active() + self.main_window.btwin.set_visible(visible) + Preferences.blocks_window_visibility(visible) ################################################## # Param Modifications ################################################## @@ -447,6 +458,7 @@ class ActionHandler: self.main_window.btwin.clear(); self.platform.load_block_tree(self.main_window.btwin); elif action == Actions.FIND_BLOCKS: + self.main_window.btwin.show() self.main_window.btwin.search_entry.show() self.main_window.set_focus(self.main_window.btwin.search_entry) elif action == Actions.OPEN_HIER: diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py index 17b7df6e6a..e96fb4d276 100644 --- a/grc/gui/Actions.py +++ b/grc/gui/Actions.py @@ -57,27 +57,13 @@ def get_all_actions(): return _all_actions_list _accel_group = gtk.AccelGroup() def get_accel_group(): return _accel_group -class Action(gtk.Action): + +class _ActionBase(object): """ - A custom Action class based on gtk.Action. - Pass additional arguments such as keypresses. + Base class for Action and ToggleAction Register actions and keypresses with this module. """ - - def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None): - """ - Create a new Action instance. - - Args: - key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...) - the: regular gtk.Action parameters (defaults to None) - """ - if name is None: name = label - gtk.Action.__init__(self, - name=name, label=label, - tooltip=tooltip, stock_id=stock_id, - ) - #register this action + def __init__(self, label, keypresses): _all_actions_list.append(self) for i in range(len(keypresses)/2): keyval, mod_mask = keypresses[i*2:(i+1)*2] @@ -111,6 +97,52 @@ class Action(gtk.Action): """ self.emit('activate') + +class Action(gtk.Action, _ActionBase): + """ + A custom Action class based on gtk.Action. + Pass additional arguments such as keypresses. + """ + + def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None): + """ + Create a new Action instance. + + Args: + key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...) + the: regular gtk.Action parameters (defaults to None) + """ + if name is None: name = label + gtk.Action.__init__(self, + name=name, label=label, + tooltip=tooltip, stock_id=stock_id, + ) + #register this action + _ActionBase.__init__(self, label, keypresses) + + +class ToggleAction(gtk.ToggleAction, _ActionBase): + """ + A custom Action class based on gtk.ToggleAction. + Pass additional arguments such as keypresses. + """ + + def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None): + """ + Create a new ToggleAction instance. + + Args: + key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...) + the: regular gtk.Action parameters (defaults to None) + """ + if name is None: name = label + gtk.ToggleAction.__init__(self, + name=name, label=label, + tooltip=tooltip, stock_id=stock_id, + ) + #register this action + _ActionBase.__init__(self, label, keypresses) + ######################################################################## # Actions ######################################################################## @@ -233,6 +265,16 @@ ERRORS_WINDOW_DISPLAY = Action( tooltip='View flow graph errors', stock_id=gtk.STOCK_DIALOG_ERROR, ) +TOGGLE_REPORTS_WINDOW = ToggleAction( + label='Show _Reports', + tooltip='Toggle visibility of the Report widget', + keypresses=(gtk.keysyms.r, gtk.gdk.CONTROL_MASK), +) +TOGGLE_BLOCKS_WINDOW = ToggleAction( + label='Show _Block Tree', + tooltip='Toggle visibility of the block tree widget', + keypresses=(gtk.keysyms.b, gtk.gdk.CONTROL_MASK), +) ABOUT_WINDOW_DISPLAY = Action( label='_About', tooltip='About this program', diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py index 92d87c8809..0e2b29c4e3 100644 --- a/grc/gui/Bars.py +++ b/grc/gui/Bars.py @@ -57,6 +57,7 @@ TOOLBAR_LIST = ( ) ##The list of actions and categories for the menu bar. + MENU_BAR_LIST = ( (gtk.Action('File', '_File', None, None), [ Actions.FLOW_GRAPH_NEW, @@ -88,6 +89,9 @@ MENU_BAR_LIST = ( Actions.BLOCK_PARAM_MODIFY, ]), (gtk.Action('View', '_View', None, None), [ + Actions.TOGGLE_BLOCKS_WINDOW, + Actions.TOGGLE_REPORTS_WINDOW, + None, Actions.ERRORS_WINDOW_DISPLAY, Actions.FIND_BLOCKS, ]), @@ -103,7 +107,6 @@ MENU_BAR_LIST = ( Actions.ABOUT_WINDOW_DISPLAY, ]), ) - class Toolbar(gtk.Toolbar): """The gtk toolbar with actions added from the toolbar list.""" diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py index 9ea37c55e0..b04a4dda7c 100644 --- a/grc/gui/BlockTreeWindow.py +++ b/grc/gui/BlockTreeWindow.py @@ -226,6 +226,10 @@ class BlockTreeWindow(gtk.VBox): # manually trigger action... Actions.FIND_BLOCKS.activate() + elif event.state & gtk.gdk.CONTROL_MASK and event.keyval == gtk.keysyms.b: + # ugly... + Actions.TOGGLE_BLOCKS_WINDOW.activate() + else: return False # propagate event diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py index 0f631791db..3410e3a93b 100644 --- a/grc/gui/Connection.py +++ b/grc/gui/Connection.py @@ -21,6 +21,7 @@ import Utils from Element import Element import Colors from Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT +import gtk class Connection(Element): """ @@ -150,7 +151,11 @@ class Connection(Element): if self.is_highlighted(): border_color = Colors.HIGHLIGHT_COLOR elif self.get_enabled(): border_color = Colors.CONNECTION_ENABLED_COLOR else: border_color = Colors.CONNECTION_DISABLED_COLOR + # make message connections dashed (no areas here) + normal_line_style = gc.line_style + if source.get_type() == "message": gc.line_style = gtk.gdk.LINE_ON_OFF_DASH Element.draw(self, gc, window, bg_color=None, border_color=border_color) + gc.line_style = normal_line_style # restore line style #draw arrow on sink port try: gc.set_foreground(self._arrow_color) diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py index 14139691d2..5f2044aa64 100644 --- a/grc/gui/MainWindow.py +++ b/grc/gui/MainWindow.py @@ -109,6 +109,8 @@ class MainWindow(gtk.Window): self.flow_graph_vpaned.set_position(Preferences.reports_window_position()) self.hpaned.set_position(Preferences.blocks_window_position()) self.show_all() + self.reports_scrolled_window.hide() + self.btwin.hide() ############################################################ # Event Handlers diff --git a/grc/gui/Preferences.py b/grc/gui/Preferences.py index ce545cab6a..c315436cae 100644 --- a/grc/gui/Preferences.py +++ b/grc/gui/Preferences.py @@ -84,3 +84,15 @@ def blocks_window_position(pos=None): else: try: return _config_parser.getint('main', 'blocks_window_position') or 1 #greater than 0 except: return -1 + +def reports_window_visibility(visible=None): + if visible is not None: _config_parser.set('main', 'reports_window_visible', visible) + else: + try: return _config_parser.getboolean('main', 'reports_window_visible') + except: return True + +def blocks_window_visibility(visible=None): + if visible is not None: _config_parser.set('main', 'blocks_window_visible', visible) + else: + try: return _config_parser.getboolean('main', 'blocks_window_visible') + except: return True |