diff --git a/CMakeCPack.cmake b/CMakeCPack.cmake index 3332c695..1c64762f 100644 --- a/CMakeCPack.cmake +++ b/CMakeCPack.cmake @@ -1,10 +1,14 @@ set(CPACK_GENERATOR ZIP - DEB - RPM - NSIS ) +if (PACKAGE_LINUX OR PACKAGE_RPI2) + list(APPEND CPACK_GENERATOR RPM DEB) +endif () +if (PACKAGE_WIN32) + list(APPEND CPACK_GENERATOR NSIS) +endif () + set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0) set(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_BINARY_DIR}" diff --git a/CMakeCPackOptions.cmake.in b/CMakeCPackOptions.cmake.in index 39661ad9..4eff2ff1 100644 --- a/CMakeCPackOptions.cmake.in +++ b/CMakeCPackOptions.cmake.in @@ -5,12 +5,12 @@ if (CPACK_GENERATOR MATCHES "ZIP") set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE OFF) set(CPACK_COMPONENTS_IGNORE_GROUPS ON) - set(CPACK_COMPONENTS_ALL propware examples win_cmake cmake osx_cmake) + set(CPACK_COMPONENTS_ALL propware examples win_cmake cmake osx_cmake standalone-cmake) elseif (CPACK_GENERATOR MATCHES "NSIS") set(CPACK_COMPONENTS_ALL propware examples win_cmake win_spin2cpp) elseif (CPACK_GENERATOR MATCHES "DEB") set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE ON) - set(CPACK_COMPONENTS_ALL propware examples cmake linux_spin2cpp) + set(CPACK_COMPONENTS_ALL propware examples cmake pi2_cmake linux_spin2cpp rpi_spin2cpp) elseif (CPACK_GENERATOR MATCHES "RPM") set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE ON) set(CPACK_COMPONENTS_ALL propware examples cmake linux_spin2cpp) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54ab7f1b..7e0e337d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,6 @@ endif () list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMakeModules") find_package(PropWare REQUIRED) -# Allow using `if (VAR IN_LIST MY_LIST)`. Requires CMake 3.3 -cmake_policy(SET CMP0057 NEW) - # Set the project, version number and all languages used project(PropWare VERSION ${VERSION} @@ -34,6 +31,11 @@ if (DOXYGEN_FOUND) WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") endif () +option(PACKAGE_LINUX "Create complete package for Linux" OFF) +option(PACKAGE_WIN32 "Create complete package for Windows" OFF) +option(PACKAGE_OSX "Create complete package for Mac OSX" OFF) +option(PACKAGE_PI2 "Create complete package for Raspberry Pi 2" OFF) + include(ExternalProject) include(./DownloadCMakeBinaries.cmake) include(./DownloadSpin2cpp.cmake) diff --git a/CMakeModules/CMakeCOGCInformation.cmake b/CMakeModules/CMakeCOGCInformation.cmake index 92621cdc..b173a1df 100644 --- a/CMakeModules/CMakeCOGCInformation.cmake +++ b/CMakeModules/CMakeCOGCInformation.cmake @@ -103,8 +103,12 @@ set(CMAKE_INCLUDE_FLAG_COGC ${CMAKE_INCLUDE_FLAG_C}) set(CMAKE_COGC_ARCHIVE_CREATE ${CMAKE_C_ARCHIVE_CREATE}) set(CMAKE_COGC_ARCHIVE_APPEND ${CMAKE_C_ARCHIVE_APPEND}) set(CMAKE_COGC_ARCHIVE_FINISH ${CMAKE_C_ARCHIVE_FINISH}) + +if (CMAKE_VERSION VERSION_EQUAL "3.4.0" OR CMAKE_VERSION VERSION_GREATER "3.4.0") + set(INCLUDES "") +endif () set(CMAKE_COGC_COMPILE_OBJECT -" ${CMAKE_COGC_FLAGS_INIT} -o " +" ${CMAKE_COGC_FLAGS_INIT} ${INCLUDES} -o " "${CMAKE_COMMAND} -DOBJCOPY=\"${CMAKE_OBJCOPY}\" -DFILE= -P ${PROPWARE_RUN_OBJCOPY}") mark_as_advanced( diff --git a/CMakeModules/CMakeCOGCXXInformation.cmake b/CMakeModules/CMakeCOGCXXInformation.cmake index 6c27eda9..fd13d7f5 100644 --- a/CMakeModules/CMakeCOGCXXInformation.cmake +++ b/CMakeModules/CMakeCOGCXXInformation.cmake @@ -101,8 +101,11 @@ set(CMAKE_INCLUDE_FLAG_COGCXX ${CMAKE_INCLUDE_FLAG_C}) set(CMAKE_COGCXX_ARCHIVE_CREATE ${CMAKE_C_ARCHIVE_CREATE}) set(CMAKE_COGCXX_ARCHIVE_APPEND ${CMAKE_C_ARCHIVE_APPEND}) set(CMAKE_COGCXX_ARCHIVE_FINISH ${CMAKE_C_ARCHIVE_FINISH}) +if (CMAKE_VERSION VERSION_EQUAL "3.4.0" OR CMAKE_VERSION VERSION_GREATER "3.4.0") + set(INCLUDES "") +endif () set(CMAKE_COGCXX_COMPILE_OBJECT - " ${CMAKE_COGCXX_FLAGS_INIT} -o " + " ${CMAKE_COGCXX_FLAGS_INIT} ${INCLUDES} -o " "${CMAKE_COMMAND} -DOBJCOPY=\"${CMAKE_OBJCOPY}\" -DFILE= -P ${PROPWARE_RUN_OBJCOPY}") mark_as_advanced( diff --git a/CMakeModules/CMakeDatSymbolConverter.cmake b/CMakeModules/CMakeDatSymbolConverter.cmake index 268a59a6..db136098 100644 --- a/CMakeModules/CMakeDatSymbolConverter.cmake +++ b/CMakeModules/CMakeDatSymbolConverter.cmake @@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.0) # OBJCOPY GCC's objcopy executable # SOURCE File for objcopy to run over # OUTPUT Output file +# STRIP Remove this string from the output filename get_filename_component(SOURCE_FILE_DIRECTORY "${SOURCE}" DIRECTORY) get_filename_component(SOURCE_FILE_DIRECTORY "${SOURCE_FILE_DIRECTORY}" ABSOLUTE) @@ -14,7 +15,7 @@ get_filename_component(OUTPUT_FILE_NAME "${OUTPUT}" NAME) # Copy file to binary directory only if it isn't already there if (NOT SOURCE_FILE_DIRECTORY STREQUAL WORKING_DIR) - if (ENV{VERBOSE}) + if ($ENV{VERBOSE}) message("${CMAKE_COMMAND} -E copy ${SOURCE} ${WORKING_DIR}/${INPUT_FILE_NAME}") endif () execute_process( @@ -23,12 +24,22 @@ if (NOT SOURCE_FILE_DIRECTORY STREQUAL WORKING_DIR) ) endif () +# If STRIP is set, remove it from the input filename +if (NOT STRIP STREQUAL "") + set(ORIGINAL_INPUT_FILE_NAME "${INPUT_FILE_NAME}") + string(REPLACE "${STRIP}" "" INPUT_FILE_NAME "${INPUT_FILE_NAME}") + if ($ENV{VERBOSE}) + message("mv ${WORKING_DIR}/${ORIGINAL_INPUT_FILE_NAME} ${WORKING_DIR}/${INPUT_FILE_NAME}") + endif () + file(RENAME "${WORKING_DIR}/${ORIGINAL_INPUT_FILE_NAME}" "${WORKING_DIR}/${INPUT_FILE_NAME}") +endif () + if (CMD_PASS) message(FATAL_ERROR "${CMD_PASS}") else () # Object copy - if (ENV{VERBOSE}) - message("${OBJCOPY} -Ibinary -Opropeller-elf-gcc -Bpropeller ${INPUT_FILE_NAME} ${INPUT_FILE_NAME}") + if ($ENV{VERBOSE}) + message("cd ${WORKING_DIR} && ${OBJCOPY} -Ibinary -Opropeller-elf-gcc -Bpropeller ${INPUT_FILE_NAME} ${INPUT_FILE_NAME}") endif () execute_process( COMMAND ${OBJCOPY} -Ibinary -Opropeller-elf-gcc -Bpropeller "${INPUT_FILE_NAME}" "${INPUT_FILE_NAME}" @@ -40,4 +51,7 @@ else () endif () endif () +if ($ENV{VERBOSE}) + message("mv ${WORKING_DIR}/${INPUT_FILE_NAME} ${WORKING_DIR}/${OUTPUT_FILE_NAME}") +endif () file(RENAME "${WORKING_DIR}/${INPUT_FILE_NAME}" "${WORKING_DIR}/${OUTPUT_FILE_NAME}") diff --git a/CMakeModules/CMakeDetermineSPIN2DATCompiler.cmake b/CMakeModules/CMakeDetermineSPIN2DATCompiler.cmake index 3ff2bf11..1d60503c 100644 --- a/CMakeModules/CMakeDetermineSPIN2DATCompiler.cmake +++ b/CMakeModules/CMakeDetermineSPIN2DATCompiler.cmake @@ -41,4 +41,4 @@ configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeSPIN2DATCompiler.cmake.in ${CMAKE_PLATFORM_INFO_DIR}/CMakeSPIN2DATCompiler.cmake @ONLY ) -set(CMAKE_SPIN2DAT_COMPILER_ENV_VAR "FOO") +set(CMAKE_SPIN2DAT_COMPILER_ENV_VAR "SPIN2CPP") diff --git a/CMakeModules/CMakeECOGCInformation.cmake b/CMakeModules/CMakeECOGCInformation.cmake index ff528aa0..eb5b5e33 100644 --- a/CMakeModules/CMakeECOGCInformation.cmake +++ b/CMakeModules/CMakeECOGCInformation.cmake @@ -101,8 +101,11 @@ set(CMAKE_INCLUDE_FLAG_ECOGC ${CMAKE_INCLUDE_FLAG_C}) set(CMAKE_ECOGC_ARCHIVE_CREATE ${CMAKE_C_ARCHIVE_CREATE}) set(CMAKE_ECOGC_ARCHIVE_APPEND ${CMAKE_C_ARCHIVE_APPEND}) set(CMAKE_ECOGC_ARCHIVE_FINISH ${CMAKE_C_ARCHIVE_FINISH}) +if (CMAKE_VERSION VERSION_EQUAL "3.4.0" OR CMAKE_VERSION VERSION_GREATER "3.4.0") + set(INCLUDES "") +endif () set(CMAKE_ECOGC_COMPILE_OBJECT -" ${CMAKE_ECOGC_FLAGS_INIT} -o -c " +" ${CMAKE_ECOGC_FLAGS_INIT} ${INCLUDES} -o -c " "${CMAKE_COMMAND} -DOBJCOPY=\"${CMAKE_OBJCOPY}\" -DFILE= -P ${PROPWARE_RUN_OBJCOPY}") mark_as_advanced( diff --git a/CMakeModules/CMakeECOGCXXInformation.cmake b/CMakeModules/CMakeECOGCXXInformation.cmake index 108391c0..e5934748 100644 --- a/CMakeModules/CMakeECOGCXXInformation.cmake +++ b/CMakeModules/CMakeECOGCXXInformation.cmake @@ -101,8 +101,11 @@ set(CMAKE_INCLUDE_FLAG_ECOGCXX ${CMAKE_INCLUDE_FLAG_C}) set(CMAKE_ECOGCXX_ARCHIVE_CREATE ${CMAKE_C_ARCHIVE_CREATE}) set(CMAKE_ECOGCXX_ARCHIVE_APPEND ${CMAKE_C_ARCHIVE_APPEND}) set(CMAKE_ECOGCXX_ARCHIVE_FINISH ${CMAKE_C_ARCHIVE_FINISH}) +if (CMAKE_VERSION VERSION_EQUAL "3.4.0" OR CMAKE_VERSION VERSION_GREATER "3.4.0") + set(INCLUDES "") +endif () set(CMAKE_ECOGCXX_COMPILE_OBJECT -" ${CMAKE_ECOGCXX_FLAGS_INIT} -o -c " +" ${CMAKE_ECOGCXX_FLAGS_INIT} ${INCLUDES} -o -c " "${CMAKE_COMMAND} -DOBJCOPY=\"${CMAKE_OBJCOPY}\" -DFILE= -P ${PROPWARE_RUN_OBJCOPY}") mark_as_advanced( diff --git a/CMakeModules/CMakeElfSizer.cmake b/CMakeModules/CMakeElfSizer.cmake new file mode 100644 index 00000000..b9e3d771 --- /dev/null +++ b/CMakeModules/CMakeElfSizer.cmake @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.0) + +# Variables that should be passed into this script +# SIZE_EXE PropGCC's propeller-elf-size executable +# BINARY Binary file to check + +execute_process( + COMMAND "${SIZE_EXE}" "${BINARY}" + RESULT_VARIABLE RETURN_CODE + OUTPUT_VARIABLE STDOUT + ERROR_VARIABLE STDERR +) + +function(remove_empty_elements_and_trim out_list in_list) + foreach (item IN LISTS ${in_list}) + if (NOT item STREQUAL "") + string(REPLACE " " "" item "${item}") + list(APPEND formatted_list "${item}") + endif () + endforeach () + + set(${out_list} "${formatted_list}" PARENT_SCOPE) +endfunction() + +if (NOT RETURN_CODE) + # Remove carriage returns + string(REPLACE "\r" "" STDOUT "${STDOUT}") + + # Split into multiple lines and save as separate variables + string(REPLACE "\n" ";" LINES "${STDOUT}") + list(GET LINES 0 HEADER) + list(GET LINES 1 SIZES) + + # Split lines into words + string(REPLACE "\t" ";" HEADER_WORDS_TEMP "${HEADER}") + remove_empty_elements_and_trim(HEADER_WORDS HEADER_WORDS_TEMP) + string(REPLACE "\t" ";" SIZE_WORDS_TEMP "${SIZES}") + remove_empty_elements_and_trim(SIZE_WORDS SIZE_WORDS_TEMP) + + # Determine index of "bss" and "dec" word + list(FIND HEADER_WORDS "bss" BSS_INDEX) + list(FIND HEADER_WORDS "dec" DEC_INDEX) + + # Determine size of bss and dec sections + list(GET SIZE_WORDS ${BSS_INDEX} BSS_SIZE) + list(GET SIZE_WORDS ${DEC_INDEX} TOTAL_SIZE) + + # Subtract bss from total to get code size + math(EXPR CODE_SIZE "${TOTAL_SIZE} - ${BSS_SIZE}") + + # All done! Print it! + message("Code size = ${CODE_SIZE}") + message("Total size = ${TOTAL_SIZE}") +endif () diff --git a/CMakeModules/CMakeRunObjcopy.cmake b/CMakeModules/CMakeRunObjcopy.cmake index b72dd6ec..43b02ce3 100644 --- a/CMakeModules/CMakeRunObjcopy.cmake +++ b/CMakeModules/CMakeRunObjcopy.cmake @@ -7,6 +7,8 @@ cmake_minimum_required(VERSION 3.0) get_filename_component(WORKING_DIR ${FILE} DIRECTORY) get_filename_component(FILE_NAME ${FILE} NAME) +get_filename_component(MODULES_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) +set(LOCALIZE_LIST_FILE "${MODULES_DIR}/PropellerCogLocalizeSymbols.txt") string(REPLACE "." ";" NAME_COMPONENTS ${FILE_NAME}) list(LENGTH NAME_COMPONENTS NUM_COMPONENTS) @@ -24,11 +26,11 @@ string(SUBSTRING ${SHORT_NAME} 1 ${SHORT_NAME_LEN} SHORT_NAME) file(RENAME "${FILE}" "${WORKING_DIR}/${SHORT_NAME}") # Object copy -if (ENV{VERBOSE}) - message("${OBJCOPY} --localize-text --rename-section .text=${SHORT_NAME} ${SHORT_NAME}") +if ($ENV{VERBOSE}) + message("${OBJCOPY} --localize-text --localize-symbols=${LOCALIZE_LIST_FILE} --rename-section .text=${SHORT_NAME} ${SHORT_NAME}") endif() execute_process( - COMMAND ${OBJCOPY} --localize-text --rename-section .text=${SHORT_NAME} ${SHORT_NAME} + COMMAND "${OBJCOPY}" --localize-text "--localize-symbols=${LOCALIZE_LIST_FILE}" --rename-section .text=${SHORT_NAME} ${SHORT_NAME} WORKING_DIRECTORY "${WORKING_DIR}" RESULT_VARIABLE CMD_PASS) if (${RESULT}) diff --git a/CMakeModules/CMakeSPIN2DATCompiler.cmake.in b/CMakeModules/CMakeSPIN2DATCompiler.cmake.in index ffe0779d..ec0853c7 100644 --- a/CMakeModules/CMakeSPIN2DATCompiler.cmake.in +++ b/CMakeModules/CMakeSPIN2DATCompiler.cmake.in @@ -1,4 +1,4 @@ -set(CMAKE_SPIN2DAT_COMPILER "@SPIN2CPP_COMMAND@") +set(CMAKE_SPIN2DAT_COMPILER "@CMAKE_SPIN2DAT_COMPILER@") set(CMAKE_SPIN2DAT_COMPILER_ARG1 "@CMAKE_C_COMPILER_ARG1@") set(CMAKE_SPIN2DAT_COMPILER_ID "@CMAKE_C_COMPILER_ID@") set(CMAKE_SPIN2DAT_COMPILER_VERSION "@CMAKE_C_COMPILER_VERSION@") diff --git a/CMakeModules/CMakeSPIN2DATInformation.cmake b/CMakeModules/CMakeSPIN2DATInformation.cmake index 26c413bf..df2aa51c 100644 --- a/CMakeModules/CMakeSPIN2DATInformation.cmake +++ b/CMakeModules/CMakeSPIN2DATInformation.cmake @@ -24,13 +24,8 @@ set(CMAKE_SPIN2DAT_ARCHIVE_APPEND "${CMAKE_C_ARCHIVE_APPEND}") set(CMAKE_SPIN2DAT_ARCHIVE_FINISH "${CMAKE_C_ARCHIVE_FINISH}") set(CMAKE_SPIN2DAT_COMPILE_OBJECT -"${CMAKE_COMMAND} \ - -DOBJCOPY=\"${CMAKE_OBJCOPY}\" \ - -DSOURCE= \ - -DOUTPUT= \ - -DSPIN2CPP_COMMAND=${SPIN2CPP_COMMAND} \ - -DPropWare_DAT_SYMBOL_CONVERTER=\"${PropWare_DAT_SYMBOL_CONVERTER}\" \ - -P ${PropWare_SPIN2DAT_SYMBOL_CONVERTER}" + "${CMAKE_SPIN2DAT_COMPILER} --dat -o " + "${CMAKE_COMMAND} -DOBJCOPY=\"${CMAKE_OBJCOPY}\" -DSTRIP=.spin -DSOURCE= -DOUTPUT= -P ${PropWare_DAT_SYMBOL_CONVERTER}" ) mark_as_advanced( diff --git a/CMakeModules/CMakeSpin2DatSymbolConverter.cmake b/CMakeModules/CMakeSpin2DatSymbolConverter.cmake deleted file mode 100644 index 6ec0de08..00000000 --- a/CMakeModules/CMakeSpin2DatSymbolConverter.cmake +++ /dev/null @@ -1,45 +0,0 @@ -cmake_minimum_required(VERSION 3.0) - -# This file is simply a wrapper to handle the Spin2dat files because spin2cpp does not allow specifying an output -# filename - -# Variables that should be passed into this script -# OBJCOPY GCC's objcopy executable -# SOURCE File for objcopy to run over -# OUTPUT Output file - - -get_filename_component(WORKING_DIR "${OUTPUT}" DIRECTORY) -get_filename_component(WORKING_DIR "${WORKING_DIR}" ABSOLUTE) - -if (ENV{VERBOSE}) - message("${SPIN2CPP_COMMAND} --dat ${SOURCE}") -endif () -execute_process( - COMMAND "${SPIN2CPP_COMMAND}" --dat "${SOURCE}" - WORKING_DIRECTORY "${WORKING_DIR}" - RESULT_VARIABLE CMD_PASS -) - -if (CMD_PASS) - message(FATAL_ERROR "${CMD_PASS}") -else () - # Source file follows the pattern *.spin and output will follow the pattern *.spin.dat, but what we _need_ is *.dat - # So, some very simple programming will get us the *.dat name that needs to be passed to the next script... - get_filename_component(SOURCE_FILE "${SOURCE}" NAME) - string(REPLACE "." ";" INPUT_FILE_NAME_COMPONENTS ${SOURCE_FILE}) - list(LENGTH INPUT_FILE_NAME_COMPONENTS NUMBER_OF_FILE_NAME_PARTS) - math(EXPR FILE_EXTENSION_INDEX "${NUMBER_OF_FILE_NAME_PARTS} - 1") - list(REMOVE_AT INPUT_FILE_NAME_COMPONENTS ${FILE_EXTENSION_INDEX}) - list(APPEND INPUT_FILE_NAME_COMPONENTS "dat") - string(REPLACE ";" "." DAT_FILE_NAME "${INPUT_FILE_NAME_COMPONENTS}") - set(DAT_FILE_PATH "${WORKING_DIR}/${DAT_FILE_NAME}") - - execute_process( - COMMAND ${CMAKE_COMMAND} "-DOBJCOPY=${OBJCOPY}" "-DSOURCE=${DAT_FILE_PATH}" "-DOUTPUT=${OUTPUT}" -P "${PropWare_DAT_SYMBOL_CONVERTER}" - RESULT_VARIABLE CMD_PASS - ) - if (CMD_PASS) - message(FATAL_ERROR "See above error") - endif () -endif () diff --git a/CMakeModules/FindPropWare.cmake b/CMakeModules/FindPropWare.cmake index ccb7f2a6..683796f3 100644 --- a/CMakeModules/FindPropWare.cmake +++ b/CMakeModules/FindPropWare.cmake @@ -54,27 +54,31 @@ # SOFTWARE. #============================================================================== -if ("${CMAKE_VERSION}" STREQUAL "3.4.0" OR "${CMAKE_VERSION}" STREQUAL "3.4.1") - message(FATAL_ERROR "PropWare is not compatible with CMake 3.4.0 or 3.4.1. Please downgrade to CMake 3.3.2.") -endif () - set(CMAKE_CONFIGURATION_TYPES None CACHE TYPE INTERNAL FORCE) +# Allow using `if (VAR IN_LIST MY_LIST)`. Requires CMake 3.3 +cmake_policy(SET CMP0057 NEW) + if (NOT PropWare_FOUND) ############################### # Compile options ############################### - # Compilation options + # General options option(32_BIT_DOUBLES "Set all doubles to 32-bits (-m32bit-doubles)" ON) option(WARN_ALL "Turn on all compiler warnings (-Wall)" ON) - option(AUTO_C_STD "Set C standard to c99 (-std=c99)" ON) - option(AUTO_CXX_STD "Set C++ standard to gnu++0x (-std=gnu++0x)" ON) - option(AUTO_OTPIMIZATION "Set optimization level to \"size\" (-Os)" ON) + option(AUTO_C_STD "Set C standard to gnu99 (-std=gnu99)" ON) + option(AUTO_CXX_STD "Set C++ standard to the latest available by the compiler" ON) - # Optimize size option + # Size optimizations + option(AUTO_OTPIMIZATION "Set optimization level to \"size\" (-Os)" ON) option(AUTO_CUT_SECTIONS "Cut out unused code (Compile: -ffunction-sections -fdata-sections; Link: --gc-sections)" ON) + # Language features + option(EXCEPTIONS "Enable exceptions (requires hundreds of kilobytes of RAM) (-fexceptions/-fno-exceptions" OFF) + option(RUNTIME_TYPE_INFORMATION "Enable runtime type information (-frtti/-fno-rtti)" OFF) + option(THREADSAFE_STATICS "Enable threadsafe statics (-fthreadsafe-statics/-fno-threadsafe-statics)" OFF) + ############################### # Libraries to link ############################### @@ -91,9 +95,7 @@ if (NOT PropWare_FOUND) endforeach() else () if (NOT DEFINED PROPWARE_PATH - OR NOT EXISTS "${PROPWARE_PATH}/include/PropWare/PropWare.h" - OR NOT EXISTS "${PROPWARE_PATH}/CMakePropWareInstall.cmake") - + OR NOT EXISTS "${PROPWARE_PATH}/lib/PropWare-targets.cmake") find_path(PROPWARE_PATH NAMES ./CMakePropWareInstall.cmake # We're either looking for PropWare's root source folder @@ -149,11 +151,11 @@ if (NOT PropWare_FOUND) PATHS "${PROPWARE_PATH}/CMakeModules" "${CMAKE_ROOT}/Modules") - find_file(PropWare_SPIN2DAT_SYMBOL_CONVERTER CMakeSpin2DatSymbolConverter.cmake + find_file(PROPWARE_RUN_OBJCOPY CMakeRunObjcopy.cmake PATHS "${PROPWARE_PATH}/CMakeModules" "${CMAKE_ROOT}/Modules") - find_file(PROPWARE_RUN_OBJCOPY CMakeRunObjcopy.cmake + find_file(ELF_SIZER CMakeElfSizer.cmake PATHS "${PROPWARE_PATH}/CMakeModules" "${CMAKE_ROOT}/Modules") @@ -215,24 +217,12 @@ if (NOT PropWare_FOUND) # PropWare helper functions & macros ########################################## function (set_linker target) - - macro (list_contains result request) - set (${result}) - foreach (listItem ${ARGN}) - if (${request} STREQUAL ${listItem}) - set (${result} TRUE) - endif () - endforeach () - endmacro() - # Set the correct linker language get_property(_languages GLOBAL PROPERTY ENABLED_LANGUAGES) - list_contains(use_c C ${_languages}) - if (use_c) + if (C IN_LIST _languages) set(linker_language C) else () - list_contains(use_cxx CXX ${_languages}) - if (use_cxx) + if (CXX IN_LIST _languages) set(linker_language CXX) else () message(FATAL_ERROR @@ -244,52 +234,60 @@ if (NOT PropWare_FOUND) PROPERTIES LINKER_LANGUAGE ${linker_language}) + endfunction () + function (append_linker_flags target) + foreach (flag IN LISTS ARGN) + set(ALL_LINK_FLAGS ${flag}) + get_target_property(EXISTING_LINK_FLAGS "${target}" LINK_FLAGS) + if (EXISTING_LINK_FLAGS) + set(ALL_LINK_FLAGS "${EXISTING_LINK_FLAGS} ${ALL_LINK_FLAGS}") + endif () + set_target_properties("${target}" PROPERTIES LINK_FLAGS "${ALL_LINK_FLAGS}") + endforeach () endfunction () - macro (set_compile_flags) - include_directories(${PropWare_INCLUDE_DIR}) + function (set_compile_flags target) + # Convert all of the user's flags into a list + foreach (variable COMMON_FLAGS COMMON_COG_FLAGS ASM_FLAGS C_FLAGS CXX_FLAGS COGC_FLAGS COGCXX_FLAGS ECOGC_FLAGS ECOGCXX_FLAGS) + separate_arguments(${variable} UNIX_COMMAND "${${separate_arguments}}") + endforeach () + if (AUTO_OTPIMIZATION) - if (NOT AUTO_OTPIMIZATION_SET) - set(AUTO_OTPIMIZATION_SET 1) - set(COMMON_FLAGS "${COMMON_FLAGS} -Os") - endif () + list(APPEND COMMON_FLAGS -Os) endif () # Handle user options if (32_BIT_DOUBLES) - if (NOT 32_BIT_DOUBLES_SET) - set(32_BIT_DOUBLES_SET 1) - set(COMMON_FLAGS "${COMMON_FLAGS} -m32bit-doubles") - endif () + list(APPEND COMMON_FLAGS -m32bit-doubles) endif () if (WARN_ALL) - if (NOT WARN_ALL_SET) - set(WARN_ALL_SET 1) - set(COMMON_FLAGS "${COMMON_FLAGS} -Wall") - endif () + list(APPEND COMMON_FLAGS -Wall) endif () if (AUTO_C_STD) - if (NOT AUTO_C_STD_SET) - set(AUTO_C_STD_SET 1) - set(C_FLAGS "${C_FLAGS} -std=c99") - endif () + # Cannot use CMake's built-in support for C standard because it will not affect COGC or ECOGC + list(APPEND C_FLAGS --std=gnu99) endif () if (AUTO_CXX_STD) - if (NOT AUTO_CXX_STD_SET) - set(AUTO_CXX_STD_SET 1) - set(CXX_FLAGS "${CXX_FLAGS} -std=gnu++0x") - endif () + # Cannot use CMake's built-in support for C++ standard because it will not affect COGCXX or ECOGCXX + list(APPEND CXX_FLAGS --std=gnu++0x) endif () - # If no model is specified, we must choose a default so that the proper libraries can be linked - if (NOT DEFINED MODEL) - set(MODEL lmm) - endif () + # C++ Language features + macro (add_language_feature_option option_name feature) + if (${option_name}) + list(APPEND CXX_FLAGS -f${feature}) + else () + list(APPEND CXX_FLAGS -fno-${feature}) + endif () + endmacro () + add_language_feature_option(EXCEPTIONS exceptions) + add_language_feature_option(RUNTIME_TYPE_INFORMATION rtti) + add_language_feature_option(THREADSAFE_STATICS threadsafe-statics) # XMM model is retroactively renamed xmm-split if ("${MODEL}" STREQUAL xmm) @@ -302,157 +300,229 @@ if (NOT PropWare_FOUND) string(TOLOWER "${MODEL}" MODEL_LOWERCASE) if (NOT((MODEL_LOWERCASE STREQUAL "cog"))) if (AUTO_CUT_SECTIONS) - if (NOT AUTO_CUT_SECTIONS_SET) - set(AUTO_CUT_SECTIONS_SET 1) - set(COMMON_FLAGS "${COMMON_FLAGS} -ffunction-sections -fdata-sections") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") - endif () + list(APPEND COMMON_FLAGS -ffunction-sections) + list(APPEND COMMON_FLAGS -fdata-sections) + append_linker_flags(${target} -Wl,--gc-sections) endif () endif () # Check if a deprecated variable name is set if (DEFINED CFLAGS OR DEFINED CXXFLAGS) - if (NOT CFLAGS_CXXFLAGS_SET) - set(CFLAGS_CXXFLAGS_SET 1) - message(WARN ": The variables `CFLAGS` and `CXXFLAGS` have been replaced by `C_FLAGS` and `CXX_FLAGS`.") - set(C_FLAGS "${C_FLAGS} ${CFLAGS}") - set(CXX_FLAGS "${CXX_FLAGS} ${CXXFLAGS}") - set(CFLAGS ) - set(CXXFLAGS ) - endif () + message(WARN ": The variables `CFLAGS` and `CXXFLAGS` have been replaced by `C_FLAGS` and `CXX_FLAGS`.") + list(APPEND C_FLAGS ${CFLAGS}) + list(APPEND CXX_FLAGS ${CXXFLAGS}) + set(CFLAGS ) + set(CXXFLAGS ) endif() - if (NOT COMMON_FLAGS_SET) - set(COMMON_FLAGS_SET 1) - set(COMMON_FLAGS "-save-temps ${COMMON_FLAGS}") - #set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=main.rawmap ${CMAKE_EXE_LINKER_FLAGS}") - endif () + list(APPEND COMMON_FLAGS -save-temps) - # Overwite the old flags - set(CMAKE_ASM_FLAGS "${COMMON_FLAGS} ${ASM_FLAGS}") - set(CMAKE_C_FLAGS "${COMMON_FLAGS} ${C_FLAGS}") - set(CMAKE_CXX_FLAGS "${COMMON_FLAGS} ${CXX_FLAGS}") + get_property(_languages GLOBAL PROPERTY ENABLED_LANGUAGES) - set(CMAKE_COGC_FLAGS "${CMAKE_C_FLAGS} ${COMMON_COG_FLAGS} ${COGC_FLAGS}") - set(CMAKE_COGCXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_COG_FLAGS} ${COGCXX_FLAGS}") - set(CMAKE_ECOGC_FLAGS "${CMAKE_C_FLAGS} ${COMMON_COG_FLAGS} ${ECOGC_FLAGS}") - set(CMAKE_ECOGCXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_COG_FLAGS} ${ECOGCXX_FLAGS}") + foreach (language ASM C CXX) + if (${language} IN_LIST _languages) + set(flags + ${COMMON_FLAGS} + ${${language}_FLAGS} + -m${MODEL} + ) + target_compile_options("${target}" PRIVATE + $<$:${flags}> + ) + endif () + endforeach () + + foreach (topLang C CXX) + foreach (subLang COG ECOG) + set(language ${subLang}${topLang}) + if (${language} IN_LIST _languages) + set(flags + ${COMMON_FLAGS} + ${${topLang}_FLAGS} + ${COMMON_COG_FLAGS} + ${${language}_FLAGS} + ) + target_compile_options("${target}" PRIVATE + $<$:${flags}> + ) + endif () + endforeach () + endforeach () + + if (DAT IN_LIST _languages) + target_compile_options("${target}" PRIVATE + $<$:${MODEL}> + ) + endif () - set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -m${MODEL}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m${MODEL}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m${MODEL}") - set(CMAKE_DAT_FLAGS "${MODEL}") + append_linker_flags(${target} -m${MODEL}) + endfunction () - endmacro() + function (add_prop_targets name target-suffix) + if (DEFINED BOARD) + set(BOARDFLAG -b${BOARD}) + endif() - macro (add_prop_targets name) + if (DEFINED GDB_BAUD) + set(BAUDFLAG -b ${GDB_BAUD}) + elseif (DEFINED ENV{GDB_BAUD}) + set(BAUDFLAG -b $ENV{GDB_BAUD}) + endif () # Add target for debugging (load to RAM and start GDB) - add_custom_target(gdb + add_custom_target(gdb${target-suffix} ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -g && ${CMAKE_GDB} ${BAUDFLAG} $ DEPENDS ${name}) # Add target for debugging (load to RAM and start terminal) - add_custom_target(debug + add_custom_target(debug${target-suffix} ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -t DEPENDS ${name}) # Add target for debugging in EEPROM (load to EEPROM and start terminal) - add_custom_target(debug-eeprom + add_custom_target(debug-eeprom${target-suffix} ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -t -e DEPENDS ${name}) + # Add target for debugging from an SD card (load to SD card and start terminal) + add_custom_target(debug-sd-cache${target-suffix} + ${CMAKE_ELF_LOADER} ${BOARDFLAG} -z $ -r -t -e + DEPENDS ${name}) + + # Add target for debugging from an SD card (load to SD card and start terminal) + add_custom_target(debug-sd-loader${target-suffix} + ${CMAKE_ELF_LOADER} ${BOARDFLAG} -l $ -r -t -e + DEPENDS ${name}) + # Add target for run (load to RAM, do not start terminal) - add_custom_target(run-ram + add_custom_target(run-ram${target-suffix} ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r DEPENDS ${name}) # Add target for run (load to EEPROM, do not start terminal) - add_custom_target(run + add_custom_target(run${target-suffix} ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -e DEPENDS ${name}) - endmacro() + # Add target for debugging from an SD card (load to SD card and start terminal) + add_custom_target(run-sd-cache${target-suffix} + ${CMAKE_ELF_LOADER} ${BOARDFLAG} -z $ -r -e + DEPENDS ${name}) - macro (add_prop_targets_with_name name) + # Add target for debugging from an SD card (load to SD card and start terminal) + add_custom_target(run-sd-loader${target-suffix} + ${CMAKE_ELF_LOADER} ${BOARDFLAG} -l $ -r -e + DEPENDS ${name}) + endfunction () - # Add target for debugging (load to RAM and start GDB) - add_custom_target(gdb-${name} - ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -g && - ${CMAKE_GDB} ${BAUDFLAG} $ - DEPENDS ${name}) + function (_pw_create_executable name suffix src1) + # If no model is specified, we must choose a default so that the proper libraries can be linked + if (NOT DEFINED MODEL) + set(MODEL lmm) + endif () - # Add target for run (load to RAM and start terminal) - add_custom_target(debug-${name} - ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -t - DEPENDS ${name}) + # Create the binary + add_executable("${name}" "${src1}" ${ARGN}) - # Add target for debugging in EEPROM (load to EEPROM and start terminal) - add_custom_target(debug-eeprom-${name} - ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -t -e - DEPENDS ${name}) + # Set flags + set_compile_flags(${name}) + target_include_directories(${name} PRIVATE ${PropWare_INCLUDE_DIR}) - # Add target for run (load to RAM, do not start terminal) - add_custom_target(run-ram-${name} - ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r - DEPENDS ${name}) + # Link it with the appropriate static libraries (and use C template for linking) + string(TOUPPER ${MODEL} _PW_UPPER_MODEL) + target_link_libraries(${name} ${PropWare_${_PW_UPPER_MODEL}_LIBRARIES}) + set_linker(${name}) - # Add target for run (load to EEPROM, do not start terminal) - add_custom_target(run-${name} - ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -e - DEPENDS ${name}) + # Create propeller-load targets + add_prop_targets(${name} "${suffix}") + endfunction () - endmacro() + function (create_executable name src1) + _pw_create_executable("${name}" "-${name}" "${src1}" ${ARGN}) + endfunction () - macro(set_propware_flags projectName) - set_compile_flags() - string(TOUPPER ${MODEL} UPPER_MODEL) - target_link_libraries(${projectName} ${PropWare_${UPPER_MODEL}_LIBRARIES}) - set_linker(${projectName}) + function (create_simple_executable name src1) + if (PROPWARE_MAIN_PACKAGE) + _pw_create_executable("${name}" "-${name}" "${src1}" ${ARGN}) + else () + _pw_create_executable("${name}" "" "${src1}" ${ARGN}) + endif () + endfunction () - if (DEFINED BOARD) - set(BOARDFLAG -b${BOARD}) - endif() + function (create_library name src1) + # If no model is specified, we must choose a default so that the proper libraries can be linked + if (NOT DEFINED MODEL) + set(MODEL lmm) + endif () + add_library(${name} STATIC "${src1}" ${ARGN}) + set_compile_flags(${name}) + target_include_directories(${name} PRIVATE ${PropWare_INCLUDE_DIR}) + set_linker(${name}) + endfunction () - if (DEFINED GDB_BAUD) - set(BAUDFLAG -b ${GDB_BAUD}) - elseif (DEFINED ENV{GDB_BAUD}) - set(BAUDFLAG -b $ENV{GDB_BAUD}) + function(spin2cpp source output_var_name) + get_filename_component(SOURCE_PATH "${source}" ABSOLUTE) + + # Find output files + execute_process(COMMAND "${SPIN2CPP_COMMAND}" --files "${SOURCE_PATH}" + OUTPUT_VARIABLE FILES_STRING + RESULT_VARIABLE SPIN2CPP_DEPENDS_CODE + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (SPIN2CPP_DEPENDS_CODE) + message(FATAL_ERROR "Spin2cpp failed to report dependencies. Exit code ${SPIN2CPP_DEPENDS_CODE}") endif () - endmacro() - macro (create_executable name src1) - add_executable(${name} "${src1}" ${ARGN}) - set_propware_flags(${name}) - add_prop_targets_with_name(${name}) - endmacro() + # Convert output files from newline-separated list to CMake list + string(REPLACE "\r" "" OUTPUT_FILE_NAMES "${FILES_STRING}") + string(REPLACE "\n" ";" OUTPUT_FILE_NAMES "${OUTPUT_FILE_NAMES}") + foreach (file_name IN LISTS OUTPUT_FILE_NAMES) + list(APPEND ALL_OUTPUT_FILES "${CMAKE_CURRENT_BINARY_DIR}/${file_name}") + endforeach () - macro (create_simple_executable name src1) - add_executable(${name} "${src1}" ${ARGN}) - set_propware_flags(${name}) + # Only save new files in the "output list" variable and add to the clean target + foreach (file_path IN LISTS ALL_OUTPUT_FILES) + list(FIND FILES_GENERATED_IN_DIRECTORY ${file_path} INDEX) + if ("-1" STREQUAL INDEX) + list(APPEND FILES_GENERATED_IN_DIRECTORY "${file_path}") + list(APPEND UNIQUE_OUTPUT_FILES "${file_path}") + endif () + endforeach () + set(FILES_GENERATED_IN_DIRECTORY ${FILES_GENERATED_IN_DIRECTORY} PARENT_SCOPE) + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${FILES_GENERATED_IN_DIRECTORY}") - if (PROPWARE_MAIN_PACKAGE) - add_prop_targets_with_name(${name}) - else () - add_prop_targets(${name}) + if (UNIQUE_OUTPUT_FILES) + if (ARGN) + set(MAIN_FLAG "--main") + endif () + include_directories(SYSTEM ${CMAKE_CURRENT_BINARY_DIR}) + add_custom_command(OUTPUT ${UNIQUE_OUTPUT_FILES} + COMMAND "${SPIN2CPP_COMMAND}" + ARGS --gas ${MAIN_FLAG} "${SOURCE_PATH}" + MAIN_DEPENDENCY "${SOURCE_PATH}" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + COMMENT "Converting ${source} to C++") endif () - endmacro() + set(${output_var_name} ${UNIQUE_OUTPUT_FILES} PARENT_SCOPE) + endfunction() + + # TODO: Add build system documentation for testing + enable_testing() + add_custom_target(test-all COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure) + function(create_test target src1) + create_executable("${target}" "${src1}" ${ARGN}) + if (DEFINED BOARD) + set(BOARDFLAG -b${BOARD}) + endif() + add_test(NAME ${target} + COMMAND ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -t -q) + add_dependencies(test-all ${target}) + add_custom_target(test-${target} + COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -R ${target} + DEPENDS ${target}) + endfunction() endif () - # TODO: Add build system documentation for testing - enable_testing() - add_custom_target(test-all COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure) - macro(create_test target src1) - create_executable(${target} "${src1}" ${ARGN}) - add_test(NAME ${target} - COMMAND ${CMAKE_ELF_LOADER} ${BOARDFLAG} $ -r -t -q) - add_dependencies(test-all ${target}) - add_custom_target(test-${target} - COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -R ${target} - DEPENDS ${target}) - endmacro() - include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PropWare FOUND_VAR PropWare_FOUND diff --git a/CMakeModules/Platform/Generic-gcc-Propeller.cmake b/CMakeModules/Platform/Generic-gcc-Propeller.cmake index 253c8da6..136b66a5 100644 --- a/CMakeModules/Platform/Generic-gcc-Propeller.cmake +++ b/CMakeModules/Platform/Generic-gcc-Propeller.cmake @@ -1,5 +1,3 @@ -message(STATUS "LOADED: Generic-gcc-Propeller.cmake") - ################################################################################ ### Set Compile Flags ################################################################################ @@ -8,7 +6,7 @@ message(STATUS "LOADED: Generic-gcc-Propeller.cmake") set(ASMFLAGS_INIT "") set(CFLAGS_INIT "") set(CSTANDARD "") -set(CXXFLAGS_INIT "-fno-threadsafe-statics -fno-rtti") +set(CXXFLAGS_INIT "") set(CMAKE_ASM_FLAGS_INIT "${ASMFLAGS_INIT}") set(CMAKE_C_FLAGS_INIT "${CFLAGS_INIT}") @@ -32,14 +30,17 @@ set(CMAKE_AR_FLAGS "cr") ################################################################################ ### Compilers ################################################################################ +if (CMAKE_VERSION VERSION_EQUAL "3.4.0" OR CMAKE_VERSION VERSION_GREATER "3.4.0") + set(INCLUDES "") +endif () set(CMAKE_C_COMPILE_OBJECT -" ${CMAKE_C_FLAGS_INIT} -o -c ") +" ${CMAKE_C_FLAGS_INIT} ${INCLUDES} -o -c ") set(CMAKE_CXX_COMPILE_OBJECT -" ${CMAKE_CXX_FLAGS_INIT} -o -c ") +" ${CMAKE_CXX_FLAGS_INIT} ${INCLUDES} -o -c ") set(CMAKE_ASM_COMPILE_OBJECT -" ${CMAKE_ASM_FLAGS_INIT} -o -c ") +" ${CMAKE_ASM_FLAGS_INIT} ${INCLUDES} -o -c ") ################################################################################ ### Linkers @@ -54,7 +55,8 @@ set(CMAKE_C_ARCHIVE_FINISH " ") set(CMAKE_C_LINK_EXECUTABLE -" -o ") +" -o " +"${CMAKE_COMMAND} -DBINARY= -DSIZE_EXE=${CMAKE_ELF_SIZE} -P ${ELF_SIZER}") mark_as_advanced( CMAKE_BUILD_TYPE diff --git a/CMakeModules/PropellerCogLocalizeSymbols.txt b/CMakeModules/PropellerCogLocalizeSymbols.txt new file mode 100644 index 00000000..c4e95343 --- /dev/null +++ b/CMakeModules/PropellerCogLocalizeSymbols.txt @@ -0,0 +1,25 @@ +CNT +CTRA +CTRB +DIRA +DIRB +DIRC +DIRD +FRQA +FRQB +INA +INB +OUTA +OUTB +PAR +PHSA +PHSB +PINA +PINB +PINC +PIND +__stack_end +VCFG +VSCL +__clkfreqval +__clkmodeval diff --git a/CMakeModules/PropellerToolchain.cmake b/CMakeModules/PropellerToolchain.cmake index 55176be4..b9cf4f77 100644 --- a/CMakeModules/PropellerToolchain.cmake +++ b/CMakeModules/PropellerToolchain.cmake @@ -10,12 +10,12 @@ if (NOT DEFINED GCC_PATH) # search mechanism and then manually adding it into the end find_path(GCC_PATH NAMES - propeller-elf-gcc${EXE_SUFFIX} + propeller-elf-gcc${EXE_SUFFIX} PATHS - "$ENV{GCC_PATH}" - "${PROPGCC_PREFIX}/bin" - "$ENV{PROPGCC_PREFIX}/bin" - ENV PATH + "$ENV{GCC_PATH}" + "${PROPGCC_PREFIX}/bin" + "$ENV{PROPGCC_PREFIX}/bin" + ENV PATH NO_SYSTEM_ENVIRONMENT_PATH) file(TO_CMAKE_PATH "/opt/parallax/bin" DEFAULT_LINUX_PATH_1) @@ -27,13 +27,13 @@ if (NOT DEFINED GCC_PATH) if (NOT GCC_PATH) find_path(GCC_PATH NAMES - propeller-elf-gcc${EXE_SUFFIX} + propeller-elf-gcc${EXE_SUFFIX} PATHS - "${DEFAULT_LINUX_PATH_1}" - "${DEFAULT_WINDOWS_PATH_1}" - "${DEFAULT_WINDOWS_PATH_2}" - "${DEFAULT_WINDOWS_PATH_3}" - "${DEFAULT_WINDOWS_PATH_4}") + "${DEFAULT_LINUX_PATH_1}" + "${DEFAULT_WINDOWS_PATH_1}" + "${DEFAULT_WINDOWS_PATH_2}" + "${DEFAULT_WINDOWS_PATH_3}" + "${DEFAULT_WINDOWS_PATH_4}") endif () endif () @@ -65,13 +65,20 @@ find_program(CMAKE_ELF_LOADER propeller-load find_program(CMAKE_GDB propeller-elf-gdb PATHS "${GCC_PATH}" NO_SYSTEM_ENVIRONMENT_PATH) +find_program(CMAKE_ELF_SIZE propeller-elf-size + PATHS "${GCC_PATH}" + NO_SYSTEM_ENVIRONMENT_PATH) +find_program(CMAKE_SPIN2DAT_COMPILER spin2cpp + PATHS "${GCC_PATH}") + +find_program(ELF_SIZER elfsizer + PATHS "${GCC_PATH}") set(CMAKE_COGC_COMPILER "${CMAKE_C_COMPILER}") set(CMAKE_COGCXX_COMPILER "${CMAKE_CXX_COMPILER}") set(CMAKE_ECOGC_COMPILER "${CMAKE_C_COMPILER}") set(CMAKE_ECOGCXX_COMPILER "${CMAKE_CXX_COMPILER}") set(CMAKE_DAT_COMPILER "${CMAKE_C_COMPILER}") -set(CMAKE_SPIN2DAT_COMPILER "${SPIN2CPP_COMMAND}") get_filename_component(GCC_PATH "${CMAKE_C_COMPILER}" DIRECTORY CACHE) diff --git a/CMakePropWareInstall.cmake b/CMakePropWareInstall.cmake index 666f3678..3f630358 100644 --- a/CMakePropWareInstall.cmake +++ b/CMakePropWareInstall.cmake @@ -1,9 +1,5 @@ -install(DIRECTORY ${CMAKE_BINARY_DIR}/${CUSTOM_LINUX_CMAKE_INSTALL_DIR} - DESTINATION . - USE_SOURCE_PERMISSIONS - COMPONENT cmake) -if (NOT WIN32) - macro(InstallSymlink _filepath _sympath) +macro(InstallSymlink _filepath _sympath) + if (NOT WIN32) get_filename_component(_symname ${_sympath} NAME) # Don't use get_filename_component because it corrupts escape characters @@ -34,8 +30,14 @@ if (NOT WIN32) \${_realInstallDir}/${_symname})" ${ARGN}) endif () - endmacro(InstallSymlink) + endif () +endmacro(InstallSymlink) +if (PACKAGE_LINUX) + install(DIRECTORY ${CMAKE_BINARY_DIR}/${CUSTOM_LINUX_CMAKE_INSTALL_DIR} + DESTINATION . + USE_SOURCE_PERMISSIONS + COMPONENT cmake) InstallSymlink(../${CUSTOM_LINUX_CMAKE_INSTALL_DIR}/bin/cmake \\\${CMAKE_INSTALL_PREFIX}/bin/cmake @@ -52,35 +54,76 @@ if (NOT WIN32) InstallSymlink(../${CUSTOM_LINUX_CMAKE_INSTALL_DIR}/bin/ctest \\\${CMAKE_INSTALL_PREFIX}/bin/ctest COMPONENT cmake) + install(DIRECTORY CMakeModules/ + DESTINATION ${CUSTOM_LINUX_CMAKE_INSTALL_DIR}/share/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules + COMPONENT cmake) + + install(PROGRAMS ${CMAKE_BINARY_DIR}/Spin2Cpp/src/Spin2Cpp/build/spin2cpp + DESTINATION bin + COMPONENT linux_spin2cpp) +endif () + +if (PACKAGE_WIN32) + install(DIRECTORY ${CMAKE_BINARY_DIR}/${CUSTOM_WIN32_CMAKE_INSTALL_DIR} + DESTINATION . + USE_SOURCE_PERMISSIONS + COMPONENT win_cmake) + install(DIRECTORY CMakeModules/ + DESTINATION ${CUSTOM_WIN32_CMAKE_INSTALL_DIR}/share/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules + COMPONENT win_cmake) + + install(PROGRAMS ${CMAKE_BINARY_DIR}/Spin2Cpp/src/Spin2Cpp/build-win32/spin2cpp.exe + DESTINATION . + COMPONENT win_spin2cpp) +endif () + +if (PACKAGE_OSX) + install(DIRECTORY ${CMAKE_BINARY_DIR}/${CUSTOM_OSX_CMAKE_INSTALL_DIR}/CMake.app/ + DESTINATION pwcmake.app + USE_SOURCE_PERMISSIONS + COMPONENT osx_cmake) + install(DIRECTORY CMakeModules/ + DESTINATION pwcmake.app/Contents/share/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules + COMPONENT osx_cmake) +endif () + +if (PACKAGE_PI2) + set(PI2_CMAKE_VERSION_MAJOR_MINOR "3.5") + install(DIRECTORY ${CMAKE_BINARY_DIR}/${CUSTOM_PI2_CMAKE_INSTALL_DIR} + DESTINATION . + USE_SOURCE_PERMISSIONS + COMPONENT pi2_cmake) + install(DIRECTORY CMakeModules/ + DESTINATION ${CUSTOM_PI2_CMAKE_INSTALL_DIR}/share/cmake-${PI2_CMAKE_VERSION_MAJOR_MINOR}/Modules + COMPONENT pi2_cmake) + + InstallSymlink(../${CUSTOM_PI2_CMAKE_INSTALL_DIR}/bin/cmake + \\\${CMAKE_INSTALL_PREFIX}/bin/cmake + COMPONENT pi2_cmake) + InstallSymlink(../${CUSTOM_PI2_CMAKE_INSTALL_DIR}/bin/ccmake + \\\${CMAKE_INSTALL_PREFIX}/bin/ccmake + COMPONENT pi2_cmake) + InstallSymlink(../${CUSTOM_PI2_CMAKE_INSTALL_DIR}/bin/cmake-gui + \\\${CMAKE_INSTALL_PREFIX}/bin/cmake-gui + COMPONENT pi2_cmake) + InstallSymlink(../${CUSTOM_PI2_CMAKE_INSTALL_DIR}/bin/cpack + \\\${CMAKE_INSTALL_PREFIX}/bin/cpack + COMPONENT pi2_cmake) + InstallSymlink(../${CUSTOM_PI2_CMAKE_INSTALL_DIR}/bin/ctest + \\\${CMAKE_INSTALL_PREFIX}/bin/ctest + COMPONENT pi2_cmake) + install(DIRECTORY CMakeModules/ + DESTINATION ${CUSTOM_PI2_CMAKE_INSTALL_DIR}/share/cmake-${PI2_CMAKE_VERSION_MAJOR_MINOR}/Modules + COMPONENT pi2_cmake) + + install(PROGRAMS ${CMAKE_BINARY_DIR}/Spin2Cpp/src/Spin2Cpp/build-rpi/spin2cpp + DESTINATION . + COMPONENT rpi_spin2cpp) endif () -install(DIRECTORY ${CMAKE_BINARY_DIR}/${CUSTOM_WIN32_CMAKE_INSTALL_DIR} - DESTINATION . - USE_SOURCE_PERMISSIONS - COMPONENT win_cmake) -install(DIRECTORY ${CMAKE_BINARY_DIR}/${CUSTOM_OSX_CMAKE_INSTALL_DIR}/CMake.app/ - DESTINATION pwcmake.app - USE_SOURCE_PERMISSIONS - COMPONENT osx_cmake) install(DIRECTORY CMakeModules/ - DESTINATION ${CUSTOM_LINUX_CMAKE_INSTALL_DIR}/share/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules - COMPONENT cmake) -install(DIRECTORY CMakeModules/ - DESTINATION ${CUSTOM_WIN32_CMAKE_INSTALL_DIR}/share/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules - COMPONENT win_cmake) -install(DIRECTORY CMakeModules/ - DESTINATION pwcmake.app/Contents/share/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/Modules - COMPONENT osx_cmake) - -# Spin2cpp -install(FILES ${CMAKE_BINARY_DIR}/Spin2Cpp/src/Spin2Cpp/build/spin2cpp - DESTINATION bin - PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ - COMPONENT linux_spin2cpp) -install(FILES ${CMAKE_BINARY_DIR}/Spin2Cpp/src/Spin2Cpp/build-win32/spin2cpp.exe - DESTINATION . - PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ - COMPONENT win_spin2cpp) + DESTINATION Modules + COMPONENT standalone-cmake) # PropWare & libpropeller includes install(DIRECTORY diff --git a/DownloadCMakeBinaries.cmake b/DownloadCMakeBinaries.cmake index 2bafe0a4..a9e8757a 100644 --- a/DownloadCMakeBinaries.cmake +++ b/DownloadCMakeBinaries.cmake @@ -1,24 +1,43 @@ set(CMAKE_MAJOR_VERSION 3) -set(CMAKE_MINOR_VERSION 3) -set(CMAKE_PATCH_VERSION 2) +set(CMAKE_MINOR_VERSION 4) +set(CMAKE_PATCH_VERSION 3) set(CUSTOM_LINUX_CMAKE_INSTALL_DIR pwcmake) set(CUSTOM_WIN32_CMAKE_INSTALL_DIR PWCMake) set(CUSTOM_OSX_CMAKE_INSTALL_DIR OSXCMake) -ExternalProject_Add(CMake - PREFIX CMake-src - URL http://www.cmake.org/files/v${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}-Linux-x86_64.tar.gz - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo_append - BUILD_COMMAND ${CMAKE_COMMAND} -E echo_append - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/${CUSTOM_LINUX_CMAKE_INSTALL_DIR}) -ExternalProject_Add(WinCMake - PREFIX WinCMake-src - URL http://www.cmake.org/files/v${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}-win32-x86.zip - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo_append - BUILD_COMMAND ${CMAKE_COMMAND} -E echo_append - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/${CUSTOM_WIN32_CMAKE_INSTALL_DIR}) -ExternalProject_Add(OSXCMake - PREFIX OSXCMake-src - URL http://www.cmake.org/files/v${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}-Darwin-x86_64.tar.gz - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo_append - BUILD_COMMAND ${CMAKE_COMMAND} -E echo_append - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/${CUSTOM_OSX_CMAKE_INSTALL_DIR}) +set(CUSTOM_PI2_CMAKE_INSTALL_DIR Pi2CMake) + +if (PACKAGE_LINUX) + externalproject_add(CMake + PREFIX CMake-src + URL https://www.cmake.org/files/v${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}-Linux-x86_64.tar.gz + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo_append + BUILD_COMMAND ${CMAKE_COMMAND} -E echo_append + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/${CUSTOM_LINUX_CMAKE_INSTALL_DIR}) +endif () + +if (PACKAGE_WIN32) + externalproject_add(WinCMake + PREFIX WinCMake-src + URL https://www.cmake.org/files/v${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}-win32-x86.zip + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo_append + BUILD_COMMAND ${CMAKE_COMMAND} -E echo_append + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/${CUSTOM_WIN32_CMAKE_INSTALL_DIR}) +endif () + +if (PACKAGE_OSX) + externalproject_add(OSXCMake + PREFIX OSXCMake-src + URL https://www.cmake.org/files/v${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}/cmake-${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}-Darwin-x86_64.tar.gz + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo_append + BUILD_COMMAND ${CMAKE_COMMAND} -E echo_append + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/${CUSTOM_OSX_CMAKE_INSTALL_DIR}) +endif () + +if (PACKAGE_PI2) + externalproject_add(Pi2CMake + PREFIX Pi2CMake-src + URL http://david.zemon.name/downloads/cmake-3.5.20160306-g7cc82-Linux-armv7l.tar.gz + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo_append + BUILD_COMMAND ${CMAKE_COMMAND} -E echo_append + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/${CUSTOM_PI2_CMAKE_INSTALL_DIR}) +endif () diff --git a/DownloadSpin2cpp.cmake b/DownloadSpin2cpp.cmake index 5c9f1490..af1244f0 100644 --- a/DownloadSpin2cpp.cmake +++ b/DownloadSpin2cpp.cmake @@ -1,8 +1,25 @@ -externalproject_add(Spin2Cpp - PREFIX Spin2Cpp - BINARY_DIR Spin2Cpp/src/Spin2Cpp - GIT_REPOSITORY https://github.com/totalspectrum/spin2cpp.git - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo_append - BUILD_COMMAND make && make CROSS=win32 - INSTALL_COMMAND ${CMAKE_COMMAND} -E echo_append - ) +if (PACKAGE_LINUX OR PACKAGE_WIN32 OR PACKAGE_PI2) + # Build the make line + set(MAKES ) + if (PACKAGE_LINUX) + list(APPEND MAKES make) + endif () + if (PACKAGE_WIN32) + list(APPEND MAKES "make CROSS=win32") + endif () + if (PACKAGE_PI2) + list(APPEND MAKES "make CROSS=rpi") + endif () + + string(REPLACE ";" " && " BUILD_COMMAND "${MAKES}") + string(REPLACE " " ";" BUILD_COMMAND "${BUILD_COMMAND}") + + externalproject_add(Spin2Cpp + PREFIX Spin2Cpp + BINARY_DIR Spin2Cpp/src/Spin2Cpp + GIT_REPOSITORY https://github.com/totalspectrum/spin2cpp.git + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo_append + BUILD_COMMAND ${BUILD_COMMAND} + INSTALL_COMMAND ${CMAKE_COMMAND} -E echo_append + ) +endif () diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 42934abb..b480f9cf 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -1,9 +1,12 @@ +set(BOARD activityboard) + add_subdirectory(Cogc) add_subdirectory(GettingStarted) add_subdirectory(Hello) add_subdirectory(Libpropeller_Pwm32) add_subdirectory(PropWare_Blinky) add_subdirectory(PropWare_DuplexUART) +add_subdirectory(PropWare_Eeprom) add_subdirectory(PropWare_FileReader) add_subdirectory(PropWare_FileWriter) add_subdirectory(PropWare_HD44780) @@ -13,6 +16,7 @@ add_subdirectory(PropWare_MAX6675) add_subdirectory(PropWare_MCP3000) add_subdirectory(PropWare_MultiCogBlinky) add_subdirectory(PropWare_PCF8591) +add_subdirectory(PropWare_Ping) add_subdirectory(PropWare_Queue) add_subdirectory(PropWare_Runnable) add_subdirectory(PropWare_Scanner) @@ -30,3 +34,4 @@ add_subdirectory(Simple_FdSerial) add_subdirectory(Simple_libadcACpropab) add_subdirectory(Simple_MeasureVolts) add_subdirectory(Simple_SimpleText) +add_subdirectory(Spin2Cpp) diff --git a/Examples/PropWare_Eeprom/CMakeLists.txt b/Examples/PropWare_Eeprom/CMakeLists.txt new file mode 100644 index 00000000..984a3ee7 --- /dev/null +++ b/Examples/PropWare_Eeprom/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.3) +find_package(PropWare REQUIRED) + +project(Eeprom_Demo) + +create_simple_executable(${PROJECT_NAME} Eeprom_Demo.cpp) diff --git a/Examples/PropWare_Eeprom/Eeprom_Demo.cpp b/Examples/PropWare_Eeprom/Eeprom_Demo.cpp new file mode 100644 index 00000000..ff47af47 --- /dev/null +++ b/Examples/PropWare_Eeprom/Eeprom_Demo.cpp @@ -0,0 +1,81 @@ +/** + * @file PropWareEeprom_Demo.cpp + * + * @author David Zemon + * + * @copyright + * The MIT License (MIT)
+ *
Copyright (c) 2013 David Zemon
+ *
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
The above copyright notice and this permission notice shall be included in all copies or substantial portions + * of the Software.
+ *
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include + +const uint8_t MAGIC_ARRAY_1[] = "DCBA0"; +const size_t ARRAY_SIZE_1 = sizeof(MAGIC_ARRAY_1); +const char MAGIC_ARRAY_2[] = "Hello, world!"; +const size_t ARRAY_SIZE_2 = sizeof(MAGIC_ARRAY_2); +const uint16_t TEST_ADDRESS = 32 * 1024; // Place the data immediately above the first 32k of data + +/** + * @example PropWareEeprom_Demo.cpp + * + * Read from and write to the EEPROM that comes with your Propeller + * + * @include PropWare_Eeprom/CMakeLists.txt + */ +int main() { + PropWare::Eeprom eeprom; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Here we have some core access of the EEPROM, passing it the address with every call. This is great for non-ASCII + // data, but it gets tedious. + + pwOut << "EEPROM ack = " << eeprom.ping() << '\n'; + + bool success = eeprom.put(TEST_ADDRESS, MAGIC_ARRAY_1, ARRAY_SIZE_1); + pwOut << "Put status: " << success << '\n'; + + pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS) << '\n'; + pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS + 1) << '\n'; + pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS + 2) << '\n'; + pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS + 3) << '\n'; + pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS + 4) << '\n'; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // This is great for ASCII data, because we have access to the Printer and Scanner classes. + + pwOut << "Notice that PropWare::Eeprom also implements the PropWare::PrintCapable \n" + "and PropWare::ScanCapable interfaces. So we could also use the Propware::Printer \n" + "and PropWare::Scanner objects for reading and writing.\n"; + + + PropWare::Printer eepromPrinter(&eeprom); + PropWare::Scanner eepromScanner(&eeprom); + + // Reset the EEPROM address + eeprom.set_memory_address(TEST_ADDRESS); + // Note that the newline is required, or else the scanner won't know when to stop reading + eepromPrinter << MAGIC_ARRAY_2 << '\n'; + + char buffer[ARRAY_SIZE_2]; + // Reset the EEPROM address so that we can read what we just wrote + eeprom.set_memory_address(TEST_ADDRESS); + // Read from the EEPROM + eepromScanner.gets(buffer, ARRAY_SIZE_2); + pwOut << "Received \"" << buffer << "\" from the EEPROM!\n"; + + return 0; +} diff --git a/Examples/PropWare_FileReader/CMakeLists.txt b/Examples/PropWare_FileReader/CMakeLists.txt index e2354c2c..5aa22e16 100644 --- a/Examples/PropWare_FileReader/CMakeLists.txt +++ b/Examples/PropWare_FileReader/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 3.3) find_package(PropWare REQUIRED) -set(BOARD dna) - project(FileReader_Demo) create_simple_executable(${PROJECT_NAME} FileReader_Demo.cpp) diff --git a/Examples/PropWare_FileReader/FileReader_Demo.cpp b/Examples/PropWare_FileReader/FileReader_Demo.cpp index aaa974bf..3b08bdcf 100644 --- a/Examples/PropWare_FileReader/FileReader_Demo.cpp +++ b/Examples/PropWare_FileReader/FileReader_Demo.cpp @@ -38,9 +38,9 @@ using namespace PropWare; * * @include PropWare_FileReader/CMakeLists.txt */ -int main () { +int main() { const SD driver; - FatFS filesystem(&driver); + FatFS filesystem(&driver); filesystem.mount(); FatFileReader reader(filesystem, "fat_test.txt"); diff --git a/Examples/PropWare_FileWriter/CMakeLists.txt b/Examples/PropWare_FileWriter/CMakeLists.txt index a2cfc901..b152b49c 100644 --- a/Examples/PropWare_FileWriter/CMakeLists.txt +++ b/Examples/PropWare_FileWriter/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.3) find_package(PropWare REQUIRED) -set(BOARD dna) +set(BOARD activityboard) set(MODEL cmm) project(FileWriter_Demo) diff --git a/Examples/PropWare_I2C/PropWareI2C_Demo.cpp b/Examples/PropWare_I2C/PropWareI2C_Demo.cpp index 0887b0de..f7d73baa 100644 --- a/Examples/PropWare_I2C/PropWareI2C_Demo.cpp +++ b/Examples/PropWare_I2C/PropWareI2C_Demo.cpp @@ -23,8 +23,8 @@ #include #include -const uint8_t MAGIC_ARRAY[] = "DCBA0"; -const size_t ARRAY_SIZE = sizeof(MAGIC_ARRAY); +const uint8_t MAGIC_ARRAY_1[] = "DCBA0"; +const size_t ARRAY_SIZE_1 = sizeof(MAGIC_ARRAY_1); const uint8_t SHIFTED_DEVICE_ADDR = EEPROM_ADDR << 1; const uint16_t TEST_ADDRESS = 32 * 1024; // Place the data immediately above the first 32k of data @@ -40,14 +40,14 @@ int main () { const PropWare::I2C pwI2C; pwOut << "EEPROM ack = " << pwI2C.ping(SHIFTED_DEVICE_ADDR) << '\n'; - bool success = pwI2C.put(SHIFTED_DEVICE_ADDR, TEST_ADDRESS, MAGIC_ARRAY, ARRAY_SIZE); + bool success = pwI2C.put(SHIFTED_DEVICE_ADDR, TEST_ADDRESS, MAGIC_ARRAY_1, ARRAY_SIZE_1); pwOut << "Put status: " << success << '\n'; // Wait for write to finish while (!pwI2C.ping(SHIFTED_DEVICE_ADDR)); - uint8_t buffer[ARRAY_SIZE]; - success &= pwI2C.get(SHIFTED_DEVICE_ADDR, TEST_ADDRESS, buffer, ARRAY_SIZE); + uint8_t buffer[ARRAY_SIZE_1]; + success &= pwI2C.get(SHIFTED_DEVICE_ADDR, TEST_ADDRESS, buffer, ARRAY_SIZE_1); pwOut << "Get status: " << success << '\n'; pwOut << "Returned string = '" << (char *) buffer << "'\n"; diff --git a/Examples/PropWare_MultiCogBlinky/CMakeLists.txt b/Examples/PropWare_MultiCogBlinky/CMakeLists.txt index 8b6650e9..42e2025e 100644 --- a/Examples/PropWare_MultiCogBlinky/CMakeLists.txt +++ b/Examples/PropWare_MultiCogBlinky/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 3.3) find_package(PropWare REQUIRED) -set(BOARD QUICKSTART) - project(MultiCogBlinky_Demo) create_simple_executable(${PROJECT_NAME} MultiCogBlinky_Demo.cpp) diff --git a/Examples/PropWare_Ping/CMakeLists.txt b/Examples/PropWare_Ping/CMakeLists.txt new file mode 100644 index 00000000..55814711 --- /dev/null +++ b/Examples/PropWare_Ping/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.3) +find_package(PropWare REQUIRED) + +project(Ping_Demo) + +create_simple_executable(${PROJECT_NAME} Ping_Demo.cpp) diff --git a/Examples/PropWare_Ping/Ping_Demo.cpp b/Examples/PropWare_Ping/Ping_Demo.cpp new file mode 100644 index 00000000..8b55007c --- /dev/null +++ b/Examples/PropWare_Ping/Ping_Demo.cpp @@ -0,0 +1,45 @@ +/** + * @file Ping_Demo.cpp + * + * @author David Zemon + * + * @copyright + * The MIT License (MIT)
+ *
Copyright (c) 2013 David Zemon
+ *
Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions:
+ *
The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.
+ *
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +/** + * @example Ping_Demo.cpp + * + * Basic usage of the PropWare::Ping class to measure distance via an ultrasonic sensor + * + * @include PropWare_Blinky/CMakeLists.txt + */ +int main () { + const PropWare::Ping ping(PropWare::Port::P14, PropWare::Port::P15); + + while (1) { + pwOut << "Millimeters: " << ping.get_millimeters() << '\n'; + pwOut << "Centimeters: " << ping.get_centimeters() << '\n'; + pwOut << "Inches: " << ping.get_inches() << '\n'; + waitcnt(SECOND / 2 + CNT); + } +} diff --git a/Examples/PropWare_Queue/Queue_Demo.cpp b/Examples/PropWare_Queue/Queue_Demo.cpp index 65a94c45..aca4a0b9 100644 --- a/Examples/PropWare_Queue/Queue_Demo.cpp +++ b/Examples/PropWare_Queue/Queue_Demo.cpp @@ -9,7 +9,7 @@ #include #include -static const size_t ARRAY_SIZE = 4; +static const size_t ARRAY_SIZE_1 = 4; /** * @example Queue_Demo.cpp @@ -19,7 +19,7 @@ static const size_t ARRAY_SIZE = 4; * @include PropWare_Queue/CMakeLists.txt */ int main () { - int array[ARRAY_SIZE]; + int array[ARRAY_SIZE_1]; PropWare::Queue buffer(array); pwOut.printf("Please enter a number at each of the following six prompts:\n"); @@ -30,7 +30,7 @@ int main () { buffer.enqueue(x); } - pwOut << "I received the following (" << ARRAY_SIZE << ") values in this order:\n"; + pwOut << "I received the following (" << ARRAY_SIZE_1 << ") values in this order:\n"; while (buffer.size()) pwOut << " " << buffer.dequeue() << "\n"; pwOut << "The Queue instance only had space for four objects, so you'll notice that\n" diff --git a/Examples/PropWare_WS2812/WS2812_Demo.cpp b/Examples/PropWare_WS2812/WS2812_Demo.cpp index c08a5d1c..c08ad199 100644 --- a/Examples/PropWare_WS2812/WS2812_Demo.cpp +++ b/Examples/PropWare_WS2812/WS2812_Demo.cpp @@ -25,7 +25,10 @@ #include -const PropWare::Pin::Mask LED_TX_PIN_MASK = PropWare::Pin::P27; +const PropWare::Pin::Mask LED_TX_PIN_MASK = PropWare::Pin::P0; +const PropWare::WS2812::Type LED_TYPE = PropWare::WS2812::GRB; +const unsigned int MAX_BRIGHTNESS = 0x0C0C0C; + /** * @example WS2812_Demo.cpp * @@ -33,15 +36,15 @@ const PropWare::Pin::Mask LED_TX_PIN_MASK = PropWare::Pin::P27; * * @include PropWare_WS2812/CMakeLists.txt */ -int main () { - const PropWare::WS2812 led(LED_TX_PIN_MASK, PropWare::WS2812::GRB); +int main() { + const PropWare::WS2812 led(LED_TX_PIN_MASK, LED_TYPE); const int delay = 40 * MILLISECOND; while (1) { unsigned int i; // Go bright - for (i = 0; i < 0x101010; i += 0x010101) { + for (i = 0; i < MAX_BRIGHTNESS; i += 0x010101) { led.send(i); waitcnt(delay + CNT); } @@ -53,4 +56,3 @@ int main () { } } } - diff --git a/Examples/Spin2Cpp/CMakeLists.txt b/Examples/Spin2Cpp/CMakeLists.txt new file mode 100644 index 00000000..64cd7c5f --- /dev/null +++ b/Examples/Spin2Cpp/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.3) + +# Spin2Cpp is a PropWare 2.1 veature, so you must have at least PropWare 2.1 +find_package(PropWare 2.1 REQUIRED) + +project(Spin2Cpp_Demo) + +# FullDuplexSerial.spin is just a library, so we only pass the name of the Spin file and a name for the output variable +spin2cpp(FullDuplexSerial.spin FullDuplexSerial_CXX_FILES) + +# Hello.spin contains our "main" method, so we need to pass a third parameter which marks it as the main file +spin2cpp(Hello.spin Hello_CXX_FILES 1) + +# Now we create an executable and include source files that match up to our spin files. +create_simple_executable(Spin2Cpp_Demo ${Hello_CXX_FILES} ${FullDuplexSerial_CXX_FILES}) diff --git a/Examples/Spin2Cpp/FullDuplexSerial.spin b/Examples/Spin2Cpp/FullDuplexSerial.spin new file mode 100644 index 00000000..899b8994 Binary files /dev/null and b/Examples/Spin2Cpp/FullDuplexSerial.spin differ diff --git a/Examples/Spin2Cpp/Hello.spin b/Examples/Spin2Cpp/Hello.spin new file mode 100644 index 00000000..53d17b01 --- /dev/null +++ b/Examples/Spin2Cpp/Hello.spin @@ -0,0 +1,16 @@ +CON + _clkmode = xtal1 + pll16x + _clkfreq = 80_000_000 + +OBJ + fds : "FullDuplexSerial.spin" + +PUB demo | i + + '' start up the serial port + fds.start(31, 30, 0, 115200) + + '' and say hello + repeat 3 + fds.str(string("Hello, world!", 13, 10)) + diff --git a/PropWare/CMakeLists.txt b/PropWare/CMakeLists.txt index 16659693..2b3ec1d1 100644 --- a/PropWare/CMakeLists.txt +++ b/PropWare/CMakeLists.txt @@ -1,6 +1,7 @@ set(PROPWARE_SOURCES ${CMAKE_CURRENT_LIST_DIR}/c++allocate.h ${CMAKE_CURRENT_LIST_DIR}/comparator + ${CMAKE_CURRENT_LIST_DIR}/eeprom ${CMAKE_CURRENT_LIST_DIR}/filesystem/blockstorage ${CMAKE_CURRENT_LIST_DIR}/filesystem/fat/fatfile ${CMAKE_CURRENT_LIST_DIR}/filesystem/fat/fatfilereader @@ -20,6 +21,7 @@ set(PROPWARE_SOURCES ${CMAKE_CURRENT_LIST_DIR}/motor/stepper ${CMAKE_CURRENT_LIST_DIR}/pcf8591 ${CMAKE_CURRENT_LIST_DIR}/pin + ${CMAKE_CURRENT_LIST_DIR}/ping ${CMAKE_CURRENT_LIST_DIR}/port ${CMAKE_CURRENT_LIST_DIR}/printcapable ${CMAKE_CURRENT_LIST_DIR}/printer/printer diff --git a/PropWare/PropWare.h b/PropWare/PropWare.h index 32e6491c..2f83f30f 100644 --- a/PropWare/PropWare.h +++ b/PropWare/PropWare.h @@ -76,38 +76,39 @@ namespace PropWare { typedef int ErrorCode; typedef enum { - BIT_0 = 0x1, - BIT_1 = 0x2, - BIT_2 = 0x4, - BIT_3 = 0x8, - BIT_4 = 0x10, - BIT_5 = 0x20, - BIT_6 = 0x40, - BIT_7 = 0x80, - BIT_8 = 0x100, - BIT_9 = 0x200, - BIT_10 = 0x400, - BIT_11 = 0x800, - BIT_12 = 0x1000, - BIT_13 = 0x2000, - BIT_14 = 0x4000, - BIT_15 = 0x8000, - BIT_16 = 0x10000, - BIT_17 = 0x20000, - BIT_18 = 0x40000, - BIT_19 = 0x80000, - BIT_20 = 0x100000, - BIT_21 = 0x200000, - BIT_22 = 0x400000, - BIT_23 = 0x800000, - BIT_24 = 0x1000000, - BIT_25 = 0x2000000, - BIT_26 = 0x4000000, - BIT_27 = 0x8000000, - BIT_28 = 0x10000000, - BIT_29 = 0x20000000, - BIT_30 = 0x40000000, - BIT_31 = 0x80000000 + NULL_BIT = 0x0, + BIT_0 = 0x1, + BIT_1 = 0x2, + BIT_2 = 0x4, + BIT_3 = 0x8, + BIT_4 = 0x10, + BIT_5 = 0x20, + BIT_6 = 0x40, + BIT_7 = 0x80, + BIT_8 = 0x100, + BIT_9 = 0x200, + BIT_10 = 0x400, + BIT_11 = 0x800, + BIT_12 = 0x1000, + BIT_13 = 0x2000, + BIT_14 = 0x4000, + BIT_15 = 0x8000, + BIT_16 = 0x10000, + BIT_17 = 0x20000, + BIT_18 = 0x40000, + BIT_19 = 0x80000, + BIT_20 = 0x100000, + BIT_21 = 0x200000, + BIT_22 = 0x400000, + BIT_23 = 0x800000, + BIT_24 = 0x1000000, + BIT_25 = 0x2000000, + BIT_26 = 0x4000000, + BIT_27 = 0x8000000, + BIT_28 = 0x10000000, + BIT_29 = 0x20000000, + BIT_30 = 0x40000000, + BIT_31 = 0x80000000 } Bit; typedef enum { diff --git a/PropWare/c++allocate.h b/PropWare/c++allocate.h index 59f84361..14bea983 100644 --- a/PropWare/c++allocate.h +++ b/PropWare/c++allocate.h @@ -3,49 +3,49 @@ #include #include -using std::new_handler; -new_handler __new_handler; +std::new_handler __new_handler; void * -operator new (std::size_t sz) -{ -void *p; +operator new (std::size_t sz) { + void *p; /* malloc (0) is unpredictable; avoid it. */ -if (sz == 0) - sz = 1; -p = (void *) malloc (sz); -while (p == 0) - { - new_handler handler = __new_handler; - if (! handler) - ::abort(); - handler (); - // FIXME: Replace std namespace when GCCv5+ C++ headers are installed - p = (void *) ::malloc (sz); - } - -return p; + if (sz == 0) + sz = 1; + p = (void *) malloc(sz); + while (p == 0) { + std::new_handler handler = __new_handler; + if (!handler) + ::abort(); + handler(); + // FIXME: Replace std namespace when GCCv5+ C++ headers are installed + p = (void *) ::malloc(sz); + } + + return p; } -void* -operator new[] (std::size_t sz) -{ -return ::operator new(sz); +void * +operator new[] (std::size_t sz) { + return ::operator new(sz); +} + +void +operator delete (void *ptr) { + if (ptr) + // FIXME: Replace std namespace when GCCv5+ C++ headers are installed + ::free(ptr); } +#if __GNUC__ >= 5 void -operator delete(void* ptr) -{ -if (ptr) - // FIXME: Replace std namespace when GCCv5+ C++ headers are installed - ::free(ptr); +operator delete (void *ptr, std::size_t size) { + operator delete(ptr); } +#endif -new_handler -std::set_new_handler (new_handler handler) -{ -new_handler prev_handler = __new_handler; -__new_handler = handler; -return prev_handler; +std::new_handler std::set_new_handler (std::new_handler handler) { + std::new_handler prev_handler = __new_handler; + __new_handler = handler; + return prev_handler; } diff --git a/PropWare/eeprom.h b/PropWare/eeprom.h new file mode 100644 index 00000000..761e19f5 --- /dev/null +++ b/PropWare/eeprom.h @@ -0,0 +1,211 @@ +/** + * @file eeprom.h + * + * @author David Zemon + * + * @copyright + * The MIT License (MIT)
+ *
Copyright (c) 2013 David Zemon
+ *
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
The above copyright notice and this permission notice shall be included in all copies or substantial portions + * of the Software.
+ *
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#pragma once + +#include +#include +#include + +namespace PropWare { + +/** + * @brief EEPROM reader/writer + */ +class Eeprom: public PrintCapable, + public ScanCapable { + public: + /** First byte above the standard 32kB EEPROM */ + static const uint16_t DEFAULT_INITIAL_MEMORY_ADDRESS = 32 * 1024; + /** Standard EEPROM I2C address used for Propeller microcontrollers */ + static const uint8_t DEFAULT_DEVICE_ADDRESS = 0x50 << 1; + + public: + /** + * @brief Construct an instance that, by default, will read from and write to the standard EEPROM + * + * @param[in] driver I2C bus driver + * @param[in] initialMemoryAddress Byte of EEPROM that should be read from or written to first when using + * methods that do not accept an address as a parameter + * @param[in] deviceAddress EEPROM address on the I2C bus (for instance, the default device + * address would be passed in as `0x50 << 1`, _not_ `0x50`) + * @param[in] autoIncrement Should the memory address pointer be automatically incremented upon + * reading and writing bytes from and to the EEPROM, similar to + * reading/writing files + */ + Eeprom(const I2C &driver = pwI2c, + const uint16_t initialMemoryAddress = DEFAULT_INITIAL_MEMORY_ADDRESS, + const uint8_t deviceAddress = DEFAULT_DEVICE_ADDRESS, + const bool autoIncrement = true) + : m_driver(&driver), + m_memoryAddress(initialMemoryAddress), + m_deviceAddress(deviceAddress), + m_autoIncrement(autoIncrement) { } + + /** + * @brief Check that the EEPROM is responding + * + * @returns True if the EEPROM is responding, false otherwise + */ + bool ping() const { + return this->m_driver->ping(this->m_deviceAddress); + } + + /** + * @brief Place a byte of data into a specific address + * + * @param[in] address Address in EEPROM to place data + * @param[in] byte Data to be written to EEPROM + * + * @returns True if the data was successfully written, false otherwise + */ + bool put(const uint16_t address, const uint8_t byte) const { + // Wait for any current operation to finish + while (!this->ping()); + + return this->m_driver->put(this->m_deviceAddress, address, byte); + } + + /** + * @brief Place multiple bytes of data into sequential memory locations in EEPROM + * + * @param[in] startAddress Address to store the first byte of data + * @param[in] bytes[] Array of data - no null-terminator necessary + * @param[in] length Number of bytes in the array that should be sent + * + * @returns True if the data was successfully written, false otherwise + */ + bool put(const uint16_t startAddress, const uint8_t bytes[], const size_t length) const { + // Wait for any current operation to finish + while (!this->ping()); + + return this->m_driver->put(this->m_deviceAddress, startAddress, bytes, length); + } + + /** + * @see PropWare::PrintCapable::put_char + * + * @post Internal memory address pointer will be incremented + */ + virtual void put_char(const char c) { + this->put(this->m_memoryAddress, (uint8_t) c); + if (this->m_autoIncrement) + ++this->m_memoryAddress; + } + + /** + * @see PropWare::PrintCapable::puts + * + * @post Internal memory address pointer will be incremented by the length of the string + */ + virtual void puts(const char *string) { + const size_t stringLength = strlen(string); + this->put(this->m_memoryAddress, (const uint8_t *) string, stringLength); + if (this->m_autoIncrement) + this->m_memoryAddress += stringLength; + } + + /** + * @brief Read a byte from EEPROM + * + * @param[in] address Address in EEPROM to be read + * + * @returns Data in EEPROM + */ + uint8_t get(const uint16_t address) const { + // Wait for any current operation to finish + while (!this->ping()); + + return this->m_driver->get(this->m_deviceAddress, address); + } + + /** + * @brief Read an array of sequential bytes from EEPROM + * + * @param[in] address Address of the first byte in EEPROM + * @param[in] *buffer Address in HUB memory to store data + * @param[in] length Number of bytes to read + * + * @returns True if successful, false otherwise + */ + bool get(const uint16_t address, uint8_t *buffer, const size_t length) { + // Wait for any current operation to finish + while (!this->ping()); + + return this->m_driver->get(this->m_deviceAddress, address, buffer, length); + } + + /** + * @see PropWare::PrintCapable::get_char + * + * @post Internal memory address pointer will be incremented + */ + virtual char get_char() { + const uint8_t byte = this->get(this->m_memoryAddress); + if (this->m_autoIncrement) + ++this->m_memoryAddress; + return byte; + } + + /** + * @brief Retrieve the current address of the internal pointer + * + * @returns Address in EEPROM used for reading or writing the next byte + */ + uint16_t get_memory_address() const { + return this->m_memoryAddress; + } + + /** + * @brief Set the current address of the internal pointer + * + * @param[in] address Address in EEPROM used for reading or writing the next byte + */ + void set_memory_address(const uint16_t address) { + this->m_memoryAddress = address; + } + + /** + * @brief Determine if auto incrementing of the internal address pointer is enabled + * + * @returns True if enabled, false otherwise + */ + bool is_auto_increment() const { + return m_autoIncrement; + } + + /** + * @brief Set auto incrementing of the internal address pointer to enabled or disabled + * + * @param[in] autoIncrement True to enabled, false to disable + */ + void set_auto_increment(const bool autoIncrement) { + m_autoIncrement = autoIncrement; + } + + private: + const I2C *m_driver; + uint16_t m_memoryAddress; + const uint8_t m_deviceAddress; + bool m_autoIncrement; +}; + +} diff --git a/PropWare/filesystem/blockstorage.h b/PropWare/filesystem/blockstorage.h index 45ff6287..7b246060 100644 --- a/PropWare/filesystem/blockstorage.h +++ b/PropWare/filesystem/blockstorage.h @@ -100,26 +100,32 @@ class BlockStorage { */ static void print_block (const Printer &printer, const uint8_t data[], const size_t words = 512, const uint8_t wordsPerLine = 16) { - uint8_t lines = words / wordsPerLine; + uint_fast8_t lines = words / wordsPerLine; if (words % wordsPerLine) ++lines; // Printer header row printer << " 0 "; - for (uint8_t i = 1; i < wordsPerLine; ++i) + for (uint_fast8_t i = 1; i < wordsPerLine; ++i) { + if (8 == i) + printer.print(" "); printer.printf("%2X ", i); + } printer << '\n'; - for (uint16_t line = 0; line < lines; ++line) { - const uint16_t baseAddress = line * wordsPerLine; + for (uint_fast16_t line = 0; line < lines; ++line) { + const uint_fast16_t baseAddress = line * wordsPerLine; printer.printf("0x%04X: ", baseAddress); // Print hex values - for (uint8_t offset = 0; offset < wordsPerLine; ++offset) + for (uint_fast8_t offset = 0; offset < wordsPerLine; ++offset) { + if (8 == offset) + printer.print("- "); printer.printf("%02X ", (unsigned int) data[baseAddress + offset]); + } // Print ASCII values - for (uint8_t offset = 0; offset < wordsPerLine; ++offset) { + for (uint_fast8_t offset = 0; offset < wordsPerLine; ++offset) { const char nextChar = data[baseAddress + offset]; if (32 <= nextChar && nextChar <= 126) printer << nextChar; diff --git a/PropWare/filesystem/fat/fatfile.h b/PropWare/filesystem/fat/fatfile.h index a5b3ff36..5ddd4e0f 100644 --- a/PropWare/filesystem/fat/fatfile.h +++ b/PropWare/filesystem/fat/fatfile.h @@ -326,7 +326,7 @@ class FatFile : virtual public File { if (!this->buffer_holds_directory_start()) { PropWare::ErrorCode err; - this->m_driver->flush(m_buf); + this->m_driver->flush(this->m_buf); BlockStorage::MetaData *dirMeta = &this->m_fs->m_dirMeta; // Reset metadata to beginning of directory diff --git a/PropWare/filesystem/fat/fatfilereader.h b/PropWare/filesystem/fat/fatfilereader.h index 80b39d5c..5d21000d 100644 --- a/PropWare/filesystem/fat/fatfilereader.h +++ b/PropWare/filesystem/fat/fatfilereader.h @@ -81,7 +81,7 @@ class FatFileReader : virtual public FatFile, virtual public FileReader { * * @param[in] fs The filesystem is needed for opening the file * @param[in] name Name of the file to open - it must exist in the current working directory (see - * [issue 55](https://github.com/DavidZemon/PropWare/issues/55) for opening from a + * [issue 55](https://github.com/parallaxinc/PropWare/issues/55) for opening from a * relative or absolute path) * @param[in] *buffer Address of a dedicated buffer that should be used for this file. If left as the * NULL (the default), a shared buffer will be used. diff --git a/PropWare/filesystem/fat/fatfs.h b/PropWare/filesystem/fat/fatfs.h index bcb7d8b0..6ae92c4c 100644 --- a/PropWare/filesystem/fat/fatfs.h +++ b/PropWare/filesystem/fat/fatfs.h @@ -250,12 +250,9 @@ class FatFS : public Filesystem { 0x8B, 0x8D, 0x90, 0x92, 0x97, 0x98, 0x9A, 0xAA, 0xB6, 0xBB, 0xBC, 0xC0, 0xC1, 0xC6, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCE, 0xD0, 0xD1, 0xD4, 0xD6, 0xDB, 0xDE, 0xE1, 0xE4, 0xE5, 0xEF, 0xF2, 0xFE}; - - for (uint8_t i = 0; i < sizeof(PARTITION_IDS); ++i) - if (PARTITION_IDS[i] == partitionId) { + for (auto id : PARTITION_IDS) + if (id == partitionId) return NO_ERROR; - } - return UNSUPPORTED_FILESYSTEM; } @@ -355,28 +352,27 @@ class FatFS : public Filesystem { } inline void store_root_info () { + // Create some variables for legibility's sake + const uint_fast32_t bootSector = this->m_initFatInfo.bootSector; + const uint_fast32_t reservedSectors = this->m_initFatInfo.rsvdSectorCount; + const uint_fast8_t numFATs = this->m_initFatInfo.numFATs; + this->m_fatSize = this->m_initFatInfo.FATSize; + // Find start of FAT - this->m_fatStart = this->m_initFatInfo.bootSector + this->m_initFatInfo.rsvdSectorCount; + this->m_fatStart = bootSector + reservedSectors; - // this->m_filesystem = FAT_16; // Find root directory address + this->m_firstDataAddr = this->m_fatStart + this->m_fatSize * numFATs; switch (this->m_filesystem) { case FAT_16: - this->m_rootAddr = this->m_initFatInfo.FATSize * this->m_initFatInfo.numFATs - + this->m_fatStart; - this->m_firstDataAddr = this->m_rootAddr + this->m_rootDirSectors; + this->m_rootAddr = this->m_firstDataAddr; + this->m_firstDataAddr += this->m_rootDirSectors; break; case FAT_32: - this->m_firstDataAddr = this->m_rootAddr = this->m_initFatInfo.bootSector + - this->m_initFatInfo.rsvdSectorCount + this->m_initFatInfo.FATSize - * this->m_initFatInfo.numFATs; - this->m_rootAllocUnit = this->m_driver->get_long(ROOT_CLUSTER_ADDR, this->m_buf.buf); + this->m_rootCluster = this->m_driver->get_long(ROOT_CLUSTER_ADDR, this->m_buf.buf); + this->m_rootAddr = this->compute_tier1_from_tier2(this->m_rootCluster); break; } - - // If files will be writable, the second FAT must also be updated - - // the first sector's address is stored here - this->m_fatSize = this->m_initFatInfo.FATSize; } inline PropWare::ErrorCode read_fat_and_root_sectors () { @@ -393,7 +389,7 @@ class FatFS : public Filesystem { this->m_dir_firstCluster = (uint32_t) -1; this->m_buf.meta->curTier2 = (uint32_t) -1; } else { - this->m_buf.meta->curTier2 = this->m_dir_firstCluster = this->m_rootAllocUnit; + this->m_buf.meta->curTier2 = this->m_dir_firstCluster = this->m_rootCluster; check_errors(this->get_fat_value(this->m_buf.meta->curTier2, &this->m_buf.meta->nextTier2)); } this->m_buf.meta->curTier2Addr = this->m_rootAddr; @@ -417,16 +413,15 @@ class FatFS : public Filesystem { /** * @brief Read an entry from the FAT * - * @param[in] fatEntry Entry number (allocation unit) to read in + * @param[in] fatEntry Entry number (cluster) to read in * the FAT - * @param[out] *value Address to store the value into (the next - * allocation unit) + * @param[out] *value Address to store the value into (the next cluster) * * @return Returns 0 upon success, error code otherwise */ PropWare::ErrorCode get_fat_value (const uint32_t fatEntry, uint32_t *value) { PropWare::ErrorCode err; - uint32_t firstAvailableAllocUnit; + uint32_t firstAvailableCluster; // Do we need to load a new fat sector? if ((fatEntry >> this->m_entriesPerFatSector_Shift) != this->m_curFatSector) { @@ -434,18 +429,17 @@ class FatFS : public Filesystem { this->m_curFatSector = fatEntry >> this->m_entriesPerFatSector_Shift; check_errors(this->m_driver->read_data_block(this->m_curFatSector + this->m_fatStart, this->m_fat)); } - firstAvailableAllocUnit = this->m_curFatSector << this->m_entriesPerFatSector_Shift; + firstAvailableCluster = this->m_curFatSector << this->m_entriesPerFatSector_Shift; - // The necessary FAT sector has been loaded and the next allocation - // unit is known, proceed with loading the next data sector and - // incrementing the cluster variables + // The necessary FAT sector has been loaded and the next cluster is known, proceed with loading + // the next data sector and incrementing the cluster variables - // Retrieve the next allocation unit number + // Retrieve the next cluster number if (FAT_16 == this->m_filesystem) { - *value = this->m_driver->get_short((uint16_t) ((fatEntry - firstAvailableAllocUnit) << 1), this->m_fat); + *value = this->m_driver->get_short((uint16_t) ((fatEntry - firstAvailableCluster) << 1), this->m_fat); *value &= WORD_0; } else if (FAT_32 == this->m_filesystem) { - *value = this->m_driver->get_long((uint16_t) ((fatEntry - firstAvailableAllocUnit) << 2), this->m_fat); + *value = this->m_driver->get_long((uint16_t) ((fatEntry - firstAvailableCluster) << 2), this->m_fat); // Clear the highest 4 bits - they are always reserved *value &= 0x0FFFFFFF; } @@ -454,18 +448,14 @@ class FatFS : public Filesystem { } /** - * @brief Find and return the starting sector's address for a - * given allocation unit (note - not cluster) + * @brief Find and return the starting sector's address for a given cluster * - * @param[in] tier2 Allocation unit in FAT filesystem + * @param[in] tier2 Cluster in FAT filesystem * - * @return Returns sector address of the desired allocation unit + * @return Returns sector address of the desired cluster */ uint32_t compute_tier1_from_tier2 (uint32_t tier2) const { - if (FatFS::FAT_32 == this->m_filesystem) - tier2 -= this->m_rootAllocUnit; - else - tier2 -= 2; + tier2 -= 2; // Magical offset, as described in section 6.7 of the MS FAT32 spec tier2 <<= this->m_tier1sPerTier2Shift; tier2 += this->m_firstDataAddr; return tier2; @@ -656,66 +646,65 @@ class FatFS : public Filesystem { // FILESYSTEM this->m_logger->println("Filesystem Constants"); this->m_logger->println("===================="); - if (!this->m_mounted) { - this->m_logger->println("\nNot mounted"); - return; - } - - // FILESYSTEM - FAT Initialization Constants - this->m_logger->println("\tInitialization Numbers"); - this->m_logger->println("\t----------------------------"); - this->m_logger->printf("\tNumber of FATs: %u\n", this->m_initFatInfo.numFATs); - this->m_logger->printf("\tRoot entry count: 0x%08X/%u\n", this->m_initFatInfo.rootEntryCount, - this->m_initFatInfo.rootEntryCount); - this->m_logger->printf("\tRoot dir sectors: 0x%08X/%u\n", this->m_initFatInfo.rootDirSectors, - this->m_initFatInfo.rootDirSectors); - this->m_logger->printf("\tReserved sector count: 0x%08X/%u\n", this->m_initFatInfo.rsvdSectorCount, - this->m_initFatInfo.rsvdSectorCount); - this->m_logger->printf("\tTotal sectors: 0x%08X/%u\n", this->m_initFatInfo.totalSectors, - this->m_initFatInfo.totalSectors); - this->m_logger->printf("\tFAT Start: 0x%08X/%u\n", this->m_fatStart, this->m_fatStart); - this->m_logger->printf("\tFAT size: 0x%08X/%u\n", this->m_initFatInfo.FATSize, this->m_initFatInfo - .FATSize); - this->m_logger->printf("\tData sectors: 0x%08X/%u\n", this->m_initFatInfo.dataSectors, - this->m_initFatInfo.dataSectors); - this->m_logger->printf("\tBoot sector: 0x%08X/%u\n", this->m_initFatInfo.bootSector, - this->m_initFatInfo.bootSector); - this->m_logger->printf("\tCluster count: 0x%08X/%u\n", this->m_initFatInfo.clusterCount, - this->m_initFatInfo.clusterCount); - this->m_logger->println(); + if (this->m_mounted) { + // FILESYSTEM - FAT Initialization Constants + this->m_logger->println("\tInitialization Numbers"); + this->m_logger->println("\t----------------------------"); + this->m_logger->printf("\tNumber of FATs: %u\n", this->m_initFatInfo.numFATs); + this->m_logger->printf("\tRoot entry count: 0x%08X/%u\n", this->m_initFatInfo.rootEntryCount, + this->m_initFatInfo.rootEntryCount); + this->m_logger->printf("\tRoot dir sectors: 0x%08X/%u\n", this->m_initFatInfo.rootDirSectors, + this->m_initFatInfo.rootDirSectors); + this->m_logger->printf("\tReserved sector count: 0x%08X/%u\n", this->m_initFatInfo.rsvdSectorCount, + this->m_initFatInfo.rsvdSectorCount); + this->m_logger->printf("\tTotal sectors: 0x%08X/%u\n", this->m_initFatInfo.totalSectors, + this->m_initFatInfo.totalSectors); + this->m_logger->printf("\tFAT Start: 0x%08X/%u\n", this->m_fatStart, this->m_fatStart); + this->m_logger->printf("\tFAT size: 0x%08X/%u\n", this->m_initFatInfo.FATSize, + this->m_initFatInfo.FATSize); + this->m_logger->printf("\tData sectors: 0x%08X/%u\n", this->m_initFatInfo.dataSectors, + this->m_initFatInfo.dataSectors); + this->m_logger->printf("\tBoot sector: 0x%08X/%u\n", this->m_initFatInfo.bootSector, + this->m_initFatInfo.bootSector); + this->m_logger->printf("\tCluster count: 0x%08X/%u\n", this->m_initFatInfo.clusterCount, + this->m_initFatInfo.clusterCount); + this->m_logger->println(); - // FILESYSTEM - Partition - this->m_logger->println("\tPartition"); - this->m_logger->println("\t========="); - this->m_logger->printf("\tLabel: %s\n", this->m_label); - switch (this->m_filesystem) { - case FAT_32: - this->m_logger->printf("\tFilesystem: FAT 32\n"); - break; - case FAT_16: - this->m_logger->printf("\tFilesystem: FAT 16\n"); - break; - default: - this->m_logger->printf("\tFilesystem: unknown (%d)\n", this->m_filesystem); + // FILESYSTEM - Partition + this->m_logger->println("Partition"); + this->m_logger->println("========="); + this->m_logger->printf("\tLabel: %s\n", this->m_label); + switch (this->m_filesystem) { + case FAT_32: + this->m_logger->printf("\tFilesystem: FAT 32\n"); + break; + case FAT_16: + this->m_logger->printf("\tFilesystem: FAT 16\n"); + break; + default: + this->m_logger->printf("\tFilesystem: unknown (%d)\n", this->m_filesystem); + } + this->m_logger->printf("\tFirst FAT sector: 0x%08X\n", this->m_fatStart); + this->m_logger->printf("\tRoot directory alloc. unit: 0x%08X\n", this->m_rootCluster); + this->m_logger->printf("\tCalculated root directory sector: 0x%08X\n", + this->compute_tier1_from_tier2(this->m_rootCluster)); + this->m_logger->printf("\tRoot directory sector: 0x%08X\n", this->m_rootAddr); + this->m_logger->printf("\tRoot directory size (in sectors): %u\n", this->m_rootDirSectors); + this->m_logger->printf("\tFirst data sector: 0x%08X\n", this->m_firstDataAddr); + this->m_logger->println(); + } else { + this->m_logger->println("\nNot mounted"); } - this->m_logger->printf("\tFirst FAT sector: 0x%08X\n", this->m_fatStart); - this->m_logger->printf("\tRoot directory alloc. unit: 0x%08X\n", this->m_rootAllocUnit); - this->m_logger->printf("\tCalculated root directory sector: 0x%08X\n", - this->compute_tier1_from_tier2(this->m_rootAllocUnit)); - this->m_logger->printf("\tRoot directory sector: 0x%08X\n", this->m_rootAddr); - this->m_logger->printf("\tRoot directory size (in sectors): %u\n", this->m_rootDirSectors); - this->m_logger->printf("\tFirst data sector: 0x%08X\n", this->m_firstDataAddr); - this->m_logger->println(); if (printBlocks) { - this->m_logger->println("\tFAT Buffer"); - this->m_logger->println("\t----------"); + this->m_logger->println("FAT Buffer"); + this->m_logger->println("=========="); BlockStorage::print_block(*this->m_logger, this->m_fat, this->m_sectorSize); this->m_logger->println(); } - this->m_logger->println("\tCommon Buffer"); - this->m_logger->println("\t============="); + this->m_logger->println("Common Buffer"); + this->m_logger->println("============="); if (this->m_buf.buf == NULL) this->m_logger->println("\tEmpty"); else { @@ -738,7 +727,7 @@ class FatFS : public Filesystem { uint8_t m_filesystem; // File system type - one of FAT_16 or FAT_32 char m_label[9]; // Filesystem label uint32_t m_fatStart; // Starting block address of the FAT - uint32_t m_rootAllocUnit; // Allocation unit of root directory/first data sector (FAT32 only) + uint32_t m_rootCluster; // Cluster of root directory/first data sector (FAT32 only) uint32_t m_rootAddr; // Starting block address of the root directory uint32_t m_rootDirSectors; // Number of sectors for the root directory uint32_t m_firstDataAddr; // Starting block address of the first data cluster @@ -748,7 +737,7 @@ class FatFS : public Filesystem { bool m_fatMod; uint32_t m_curFatSector; // Store the current FAT sector loaded into m_fat - uint32_t m_dir_firstCluster; // Store the current directory's starting allocation unit + uint32_t m_dir_firstCluster; // Store the current directory's starting cluster }; } diff --git a/PropWare/models/cmm/CMakeLists.txt b/PropWare/models/cmm/CMakeLists.txt index 2b050c55..add0ac36 100644 --- a/PropWare/models/cmm/CMakeLists.txt +++ b/PropWare/models/cmm/CMakeLists.txt @@ -1,9 +1,9 @@ set(MODEL cmm) -set_compile_flags() -add_library(PropWare_${MODEL} STATIC ${PROPWARE_SOURCES}) -set_target_properties(PropWare_${MODEL} PROPERTIES OUTPUT_NAME PropWare) -install(TARGETS PropWare_${MODEL} +set(TARGET PropWare_${MODEL}) +create_library(${TARGET} ${PROPWARE_SOURCES}) +set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME PropWare) +install(TARGETS ${TARGET} DESTINATION PropWare/lib/${MODEL} COMPONENT propware EXPORT PropWare-targets) diff --git a/PropWare/models/cog/CMakeLists.txt b/PropWare/models/cog/CMakeLists.txt index d1616e46..31115675 100644 --- a/PropWare/models/cog/CMakeLists.txt +++ b/PropWare/models/cog/CMakeLists.txt @@ -1,9 +1,9 @@ set(MODEL cog) -set_compile_flags() -add_library(PropWare_${MODEL} STATIC ${PROPWARE_SOURCES}) -set_target_properties(PropWare_${MODEL} PROPERTIES OUTPUT_NAME PropWare) -install(TARGETS PropWare_${MODEL} +set(TARGET PropWare_${MODEL}) +create_library(${TARGET} ${PROPWARE_SOURCES}) +set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME PropWare) +install(TARGETS ${TARGET} DESTINATION PropWare/lib/${MODEL} COMPONENT propware EXPORT PropWare-targets) diff --git a/PropWare/models/lmm/CMakeLists.txt b/PropWare/models/lmm/CMakeLists.txt index 928f061a..c90c8f95 100644 --- a/PropWare/models/lmm/CMakeLists.txt +++ b/PropWare/models/lmm/CMakeLists.txt @@ -1,9 +1,9 @@ set(MODEL lmm) -set_compile_flags() -add_library(PropWare_${MODEL} STATIC ${PROPWARE_SOURCES}) -set_target_properties(PropWare_${MODEL} PROPERTIES OUTPUT_NAME PropWare) -install(TARGETS PropWare_${MODEL} +set(TARGET PropWare_${MODEL}) +create_library(${TARGET} ${PROPWARE_SOURCES}) +set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME PropWare) +install(TARGETS ${TARGET} DESTINATION PropWare/lib/${MODEL} COMPONENT propware EXPORT PropWare-targets) diff --git a/PropWare/models/xmm-single/CMakeLists.txt b/PropWare/models/xmm-single/CMakeLists.txt index 446cd23d..4f424e5d 100644 --- a/PropWare/models/xmm-single/CMakeLists.txt +++ b/PropWare/models/xmm-single/CMakeLists.txt @@ -1,9 +1,9 @@ set(MODEL xmm-single) -set_compile_flags() -add_library(PropWare_${MODEL} STATIC ${PROPWARE_SOURCES}) -set_target_properties(PropWare_${MODEL} PROPERTIES OUTPUT_NAME PropWare) -install(TARGETS PropWare_${MODEL} +set(TARGET PropWare_${MODEL}) +create_library(${TARGET} ${PROPWARE_SOURCES}) +set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME PropWare) +install(TARGETS ${TARGET} DESTINATION PropWare/lib/${MODEL} COMPONENT propware EXPORT PropWare-targets) diff --git a/PropWare/models/xmm-split/CMakeLists.txt b/PropWare/models/xmm-split/CMakeLists.txt index e83932bb..d4a8fdfd 100644 --- a/PropWare/models/xmm-split/CMakeLists.txt +++ b/PropWare/models/xmm-split/CMakeLists.txt @@ -1,9 +1,9 @@ set(MODEL xmm-split) -set_compile_flags() -add_library(PropWare_${MODEL} STATIC ${PROPWARE_SOURCES}) -set_target_properties(PropWare_${MODEL} PROPERTIES OUTPUT_NAME PropWare) -install(TARGETS PropWare_${MODEL} +set(TARGET PropWare_${MODEL}) +create_library(${TARGET} ${PROPWARE_SOURCES}) +set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME PropWare) +install(TARGETS ${TARGET} DESTINATION PropWare/lib/${MODEL} COMPONENT propware EXPORT PropWare-targets) diff --git a/PropWare/models/xmmc/CMakeLists.txt b/PropWare/models/xmmc/CMakeLists.txt index 4d39d633..6812bd94 100644 --- a/PropWare/models/xmmc/CMakeLists.txt +++ b/PropWare/models/xmmc/CMakeLists.txt @@ -1,9 +1,9 @@ set(MODEL xmmc) -set_compile_flags() -add_library(PropWare_${MODEL} STATIC ${PROPWARE_SOURCES}) -set_target_properties(PropWare_${MODEL} PROPERTIES OUTPUT_NAME PropWare) -install(TARGETS PropWare_${MODEL} +set(TARGET PropWare_${MODEL}) +create_library(${TARGET} ${PROPWARE_SOURCES}) +set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME PropWare) +install(TARGETS ${TARGET} DESTINATION PropWare/lib/${MODEL} COMPONENT propware EXPORT PropWare-targets) diff --git a/PropWare/pin.h b/PropWare/pin.h index 4134f0d1..ba9a6358 100644 --- a/PropWare/pin.h +++ b/PropWare/pin.h @@ -164,6 +164,60 @@ class Pin : public PropWare::Port { return false; } + /** + * @brief Set to input and measure the time it takes a signal to transition from a start state to the + * opposite state. + * + * Named rc_time because it is often used to measure a resistor-capacitor circuit's tendency to "decay" to + * either ground or 5 V (depending on wiring). Default time increments are specified in 1 microsecond units. + * Unit size can be changed with a call to set_io_dt function. The pulse will be positive if the I/O pin is + * transmitting a low signal before the call. + * + * @param[in] state Starting pin state; `true` for high, `false` for low + * @param[in] timeout Time to wait (in clock ticks) before canceling the function call + * [Default = 1/4 second] + * + * @returns Time from starting pin (in clock ticks) + */ + int rc_time (const bool state, const int timeout = SECOND / 4) { + // Taken from Simple's rc_time(int pin, int state) in rcTime.C + /* +if(iodt == 0) // If dt not initialized +{ + set_io_dt(CLKFREQ/1000000); // Set up timed I/O time increment + set_io_timeout(CLKFREQ/4); // Set up timeout +} +*/ + uint32_t ctr = ((8 + ((!state & 1) * 4)) << 26); // POS detector counter setup + ctr += Pin::convert(this->m_mask); // Add pin to setup + const uint32_t startTime = CNT; // Mark current time + if (CTRA == 0) { + // If CTRA unused + CTRA = ctr; // Configure CTRA + FRQA = 1; // FRQA increments PHSA by 1 + this->set_dir_in(); + PHSA = 0; // Clear PHSA + // Wait for decay or timeout + while (state == this->read() && (CNT - startTime <= timeout)); + CTRA = 0; // Stop the counter module + return PHSA; + } + else if (CTRB == 0) { + // If CTRA used, try CTRB + CTRB = ctr; // Same procedure as for CTRA + FRQB = 1; + this->set_dir_in(); + PHSB = 0; + while (state == this->read() && (CNT - startTime <= timeout)); + CTRB = 0; + return PHSB; + } + else { + // If CTRA & CTRB in use + return -1; + } + } + public: /** * @brief Copy one pin object into another; Only copies pin mask, not diff --git a/PropWare/ping.h b/PropWare/ping.h new file mode 100644 index 00000000..88c15817 --- /dev/null +++ b/PropWare/ping.h @@ -0,0 +1,142 @@ +/** + * @file ping.h + * + * @author David Zemon + * + * @copyright + * The MIT License (MIT)
+ *
Copyright (c) 2013 David Zemon
+ *
Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions:
+ *
The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.
+ *
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +namespace PropWare { + +/** + * @brief Ultrasonic distance sensor such as the Parallax PING))) + * + * For 3-pin variants like the Parallax PING))) sensor, use the following template: + * + * @code + * #include + * #include + * + * int main () { + * // Propeller pin P01 connected to the signal line of the PING))) + * const PropWare::Ping ping(PropWare::Pin::P01); + * unsigned int centimeters = ping.get_centimeters(); + * + * // User code here... + * pwOut << centimeters << '\n'; + * + * return 0; + * } + * @endcode + */ +class Ping { + public: + /** + * @brief Construct an instance for a 3-pin variant such as the Parallax PING))) sensor + * + * @param[in] signalMask Pin mask for the signal pin of the sensor + */ + Ping(const PropWare::Pin::Mask signalMask) { + this->m_trigger.set_mask(signalMask); + this->m_echo.set_mask(signalMask); + }; + + /** + * @brief Construct an instance for a 4-pin variant, commonly found on eBay. + * + * @param[in] triggerMask Pin mask for the trigger pin + * @param[in] echoMask Pin mask for the echo pin + */ + Ping(const PropWare::Pin::Mask triggerMask, const PropWare::Pin::Mask echoMask) { + this->m_trigger.set_mask(triggerMask); + this->m_echo.set_mask(echoMask); + }; + + /** + * @brief Detect distance as measured in millimeters between sensor and object + * + * @note Ultrasonic sensors and the Parallax Propeller are _not_ accurate enough for 1 mm precision. This + * method is only provided to give a finer grain of precision than Ping::get_centimeters without + * reverting to floating point numbers. + * + * @returns Millimeters between sensor and object + */ + unsigned int get_millimeters() const { + return this->get_microseconds() * 17; + } + + /** + * @brief Detect distance as measured in centimeters between sensor and object + * + * @returns Centimeters between sensor and object. Fractional values are truncated. + */ + unsigned int get_centimeters() const { + return this->get_millimeters() / 1000; + } + + /** + * @brief Detect distance as measured in inches between sensor and object + * + * @returns Inches between sensor and object. Fractional values are truncated. + */ + unsigned int get_inches() const { + return this->get_microseconds() / 148; + } + + /** + * @brief Time measured in microseconds for a sound wave to travel from the sensor to an object and back. + * + * @returns Microseconds for a round trip. Fractional values are truncated. + */ + unsigned int get_microseconds() const { + return this->get_clock_ticks() / MICROSECOND; + } + + /** + * @brief Time measured in system clock ticks for a sound wave to travel from the sensor to an object and + * back. This is the most accurate method on the Ping class. + * + * @returns Clock ticks for a round trip. + */ +#ifdef PROPWARE_TEST +virtual +#endif + unsigned int get_clock_ticks() const { + this->m_trigger.set_dir_out(); + this->m_trigger.set(); + waitcnt(20 * MICROSECOND + CNT); // The spec for the ping sensor is 2us, but 20us is the fastest at CMM mode + this->m_trigger.clear(); + + this->m_echo.set_dir_in(); + waitpeq(this->m_echo.get_mask(), this->m_echo.get_mask()); + volatile uint32_t start = CNT; + waitpne(this->m_echo.get_mask(), this->m_echo.get_mask()); + return CNT - start; + } + + private: + PropWare::Pin m_trigger; + PropWare::Pin m_echo; +}; + +}; diff --git a/PropWare/spi.h b/PropWare/spi.h index 7d0e89e6..2e7024cf 100644 --- a/PropWare/spi.h +++ b/PropWare/spi.h @@ -269,13 +269,10 @@ class SPI : public PrintCapable, * @param[in] numberOfBytes Number of bytes to receive */ void shift_out_block_msb_first_fast (const uint8_t buffer[], size_t numberOfBytes) { -#define ASMVAR(name) "__LMM_FCACHE_START+(" #name "%= - SpiBlockWriteStart%=)" __asm__ volatile ( - " fcache #(SpiBlockWriteEnd%= - SpiBlockWriteStart%=) \n\t" - " .compress off \n\t" - - "SpiBlockWriteStart%=: \n\t" - " jmp #__LMM_FCACHE_START+(outerLoop%= - SpiBlockWriteStart%=) \n\t" +#define ASMVAR(name) FC_ADDR(#name "%=", "SpiBlockWriteStart%=") + FC_START("SpiBlockWriteStart%=", "SpiBlockWriteEnd%=") + " jmp #" FC_ADDR("outerLoop%=", "SpiBlockWriteStart%=") " \n\t" // Temporary variables "bitIdx%=: \n\t" @@ -294,23 +291,21 @@ class SPI : public PrintCapable, " muxc outa, %[_mosi] \n\t" " xor outa, %[_sclk] \n\t" " xor outa, %[_sclk] \n\t" - " djnz " ASMVAR(bitIdx) ", #__LMM_FCACHE_START+(loop%= - SpiBlockWriteStart%=) \n\t" + " djnz " ASMVAR(bitIdx) ", #" FC_ADDR("loop%=", "SpiBlockWriteStart%=") " \n\t" // Write the word back to the buffer in HUB memory " add %[_bufAdr], #1 \n\t" - " djnz %[_numberOfBytes], #__LMM_FCACHE_START+(outerLoop%= - SpiBlockWriteStart%=) \n\t" + " djnz %[_numberOfBytes], #" FC_ADDR("outerLoop%=", "SpiBlockWriteStart%=") " \n\t" " or outa, %[_mosi] \n\t" - " jmp __LMM_RET \n\t" - "SpiBlockWriteEnd%=: \n\t" - " .compress default \n\t" + FC_END("SpiBlockWriteEnd%=") +#undef ASMVAR : [_bufAdr] "+r"(buffer), [_numberOfBytes] "+r"(numberOfBytes) :[_mosi] "r"(this->m_mosi.get_mask()), [_sclk] "r"(this->m_sclk.get_mask()) ); -#undef ASMVAR } /** @@ -321,15 +316,10 @@ class SPI : public PrintCapable, * @param[in] numberOfBytes Number of bytes to receive */ void shift_in_block_mode0_msb_first_fast (uint8_t *buffer, size_t numberOfBytes) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" -#define ASMVAR(name) "__LMM_FCACHE_START+(" #name "%= - SpiBlockReadStart%=)" __asm__ volatile ( - " fcache #(SpiBlockReadEnd%= - SpiBlockReadStart%=) \n\t" - " .compress off \n\t" - - "SpiBlockReadStart%=: \n\t" - " jmp #__LMM_FCACHE_START+(outerLoop%= - SpiBlockReadStart%=) \n\t" +#define ASMVAR(name) FC_ADDR(#name "%=", "SpiBlockReadStart%=") + FC_START("SpiBlockReadStart%=", "SpiBlockReadEnd%=") + " jmp #" FC_ADDR("outerLoop%=", "SpiBlockReadStart%=") " \n\t" // Temporary variables "bitIdx%=: \n\t" @@ -347,24 +337,20 @@ class SPI : public PrintCapable, " xor outa, %[_sclk] \n\t" " rcl " ASMVAR(data) ", #1 \n\t" " xor outa, %[_sclk] \n\t" - " djnz " ASMVAR(bitIdx) ", #__LMM_FCACHE_START+(loop%= - SpiBlockReadStart%=) \n\t" + " djnz " ASMVAR(bitIdx) ", #" FC_ADDR("loop%=", "SpiBlockReadStart%=") " \n\t" // Write the word back to the buffer in HUB memory " wrbyte " ASMVAR(data) ", %[_bufAdr] \n\t" " add %[_bufAdr], #1 \n\t" - " djnz %[_numberOfBytes], #__LMM_FCACHE_START+(outerLoop%= - SpiBlockReadStart%=) \n\t" - - " jmp __LMM_RET \n\t" - "SpiBlockReadEnd%=: \n\t" - " .compress default \n\t" + " djnz %[_numberOfBytes], #" FC_ADDR("outerLoop%=", "SpiBlockReadStart%=") " \n\t" + FC_END("SpiBlockReadEnd%=") : [_bufAdr] "+r"(buffer), [_numberOfBytes] "+r"(numberOfBytes) :[_miso] "r"(this->m_miso.get_mask()), [_sclk] "r"(this->m_sclk.get_mask()) ); #undef ASMVAR -#pragma GCC diagnostic pop } void put_char (const char c) { @@ -412,10 +398,7 @@ class SPI : public PrintCapable, #pragma GCC diagnostic ignored "-Wuninitialized" unsigned int clock; __asm__ volatile ( - " fcache #(SpiSendMsbFirstEnd%= - SpiSendMsbFirstStart%=) \n\t" - " .compress off \n\t" - "SpiSendMsbFirstStart%=: \n\t" - + FC_START("SpiSendMsbFirstStart%=", "SpiSendMsbFirstEnd%=") " ror %[_data], %[_bitCount] \n\t" " mov %[_clock], %[_clkDelay] \n\t" " add %[_clock], CNT \n\t" @@ -427,12 +410,10 @@ class SPI : public PrintCapable, " xor outa, %[_sclk] \n\t" " waitcnt %[_clock], %[_clkDelay] \n\t" " xor outa, %[_sclk] \n\t" - " djnz %[_bitCount], #__LMM_FCACHE_START+(loop%= - SpiSendMsbFirstStart%=) \n\t" + " djnz %[_bitCount], #" FC_ADDR("loop%=", "SpiSendMsbFirstStart%=") " \n\t" " or outa, %[_mosi] \n\t" - " jmp __LMM_RET \n\t" - "SpiSendMsbFirstEnd%=: \n\t" - " .compress default \n\t" + FC_END("SpiSendMsbFirstEnd%=") : [_bitCount] "+r"(bits), [_data] "+r"(data), [_clock] "+r"(clock) @@ -448,10 +429,7 @@ class SPI : public PrintCapable, #pragma GCC diagnostic ignored "-Wuninitialized" unsigned int clock; __asm__ volatile ( - " fcache #(SpiSendLsbFirstEnd%= - SpiSendLsbFirstStart%=) \n\t" - " .compress off \n\t" - - "SpiSendLsbFirstStart%=: \n\t" + FC_START("SpiSendLsbFirstStart%=", "SpiSendLsbFirstEnd%=") // Local variable declaration " mov %[_clock], CNT \n\t" " add %[_clock], %[_clkDelay] \n\t" @@ -463,13 +441,10 @@ class SPI : public PrintCapable, " xor OUTA, %[_sclk] \n\t" " waitcnt %[_clock], %[_clkDelay] \n\t" " xor OUTA, %[_sclk] \n\t" - " djnz %[_bitCount], #__LMM_FCACHE_START+(loop%= - SpiSendLsbFirstStart%=) \n\t" + " djnz %[_bitCount], #" FC_ADDR("loop%=", "SpiSendLsbFirstStart%=") " \n\t" " or outa, %[_mosi] \n\t" - " jmp __LMM_RET \n\t" - - "SpiSendLsbFirstEnd%=: \n\t" - " .compress default \n\t" + FC_END("SpiSendLsbFirstEnd%=") : [_bitCount] "+r"(bits), [_data] "+r"(data), [_clock] "+r"(clock) @@ -486,10 +461,7 @@ class SPI : public PrintCapable, unsigned int clock; unsigned int tempData; __asm__ volatile ( - " fcache #(SpiReadMsbPhs0End%= - SpiReadMsbPhs0Start%=) \n\t" - " .compress off \n\t" - - "SpiReadMsbPhs0Start%=: \n\t" + FC_START("SpiReadMsbPhs0Start%=", "SpiReadMsbPhs0End%=") " ror %[_data], %[_bitCount] '' move MSB into bit 31 \n\t" " mov %[_clock], %[_clkDelay] \n\t" " add %[_clock], CNT \n\t" @@ -501,11 +473,8 @@ class SPI : public PrintCapable, " rcl %[_data], #1 \n\t" " waitcnt %[_clock], %[_clkDelay] \n\t" " xor outa, %[_sclk] \n\t" - " djnz %[_bitCount], #__LMM_FCACHE_START+(loop%= - SpiReadMsbPhs0Start%=) \n\t" - - " jmp __LMM_RET \n\t" - "SpiReadMsbPhs0End%=: \n\t" - " .compress default \n\t" + " djnz %[_bitCount], #" FC_ADDR("loop%=", "SpiReadMsbPhs0Start%=") " \n\t" + FC_END("SpiReadMsbPhs0End%=") : [_bitCount] "+r"(bits), [_clock] "+r"(clock), [_data] "+r"(tempData) @@ -524,10 +493,7 @@ class SPI : public PrintCapable, unsigned int tempData; unsigned int modifiableBits = bits; __asm__ volatile ( - " fcache #(SpiReadLsbPhs0End%= - SpiReadLsbPhs0Start%=) \n\t" - " .compress off \n\t" - - "SpiReadLsbPhs0Start%=: \n\t" + FC_START("SpiReadLsbPhs0Start%=", "SpiReadLsbPhs0End%=") " ror %[_data], %[_bitCount] '' move MSB into bit 31 \n\t" " mov %[_clock], %[_clkDelay] \n\t" " add %[_clock], CNT \n\t" @@ -539,11 +505,8 @@ class SPI : public PrintCapable, " rcr %[_data], #1 \n\t" " waitcnt %[_clock], %[_clkDelay] \n\t" " xor outa, %[_sclk] \n\t" - " djnz %[_bitCount], #__LMM_FCACHE_START+(loop%= - SpiReadLsbPhs0Start%=) \n\t" - - " jmp __LMM_RET \n\t" - "SpiReadLsbPhs0End%=: \n\t" - " .compress default \n\t" + " djnz %[_bitCount], #" FC_ADDR("loop%=", "SpiReadLsbPhs0Start%=") " \n\t" + FC_END("SpiReadLsbPhs0End%=") : [_bitCount] "+r"(modifiableBits), [_clock] "+r"(clock), [_data] "+r"(tempData) @@ -561,10 +524,7 @@ class SPI : public PrintCapable, unsigned int clock; unsigned int tempData; __asm__ volatile ( - " fcache #(SpiReadMsbPhs1End%= - SpiReadMsbPhs1Start%=) \n\t" - " .compress off \n\t" - - "SpiReadMsbPhs1Start%=: \n\t" + FC_START("SpiReadMsbPhs1Start%=", "SpiReadMsbPhs1End%=") " ror %[_data], %[_bitCount] '' move MSB into bit 31 \n\t" " mov %[_clock], %[_clkDelay] \n\t" " add %[_clock], CNT \n\t" @@ -576,11 +536,8 @@ class SPI : public PrintCapable, " xor outa, %[_sclk] \n\t" " waitcnt %[_clock], %[_clkDelay] \n\t" " rcl %[_data], #1 \n\t" - " djnz %[_bitCount], #__LMM_FCACHE_START+(loop%= - SpiReadMsbPhs1Start%=) \n\t" - - " jmp __LMM_RET \n\t" - "SpiReadMsbPhs1End%=: \n\t" - " .compress default \n\t" + " djnz %[_bitCount], #" FC_ADDR("loop%=", "SpiReadMsbPhs1Start%=") " \n\t" + FC_END("SpiReadMsbPhs1End%=") : [_bitCount] "+r"(bits), [_clock] "+r"(clock), [_data] "+r"(tempData) @@ -598,10 +555,7 @@ class SPI : public PrintCapable, unsigned int clock; unsigned int tempData; __asm__ volatile ( - " fcache #(SpiReadLsbPhs1End%= - SpiReadLsbPhs1Start%=) \n\t" - " .compress off \n\t" - - "SpiReadLsbPhs1Start%=: \n\t" + FC_START("SpiReadLsbPhs1Start%=", "SpiReadLsbPhs1End%=") " ror %[_data], %[_bitCount] '' move MSB into bit 31 \n\t" " mov %[_clock], %[_clkDelay] \n\t" " add %[_clock], CNT \n\t" @@ -613,11 +567,8 @@ class SPI : public PrintCapable, " xor outa, %[_sclk] \n\t" " waitcnt %[_clock], %[_clkDelay] \n\t" " rcr %[_data], #1 \n\t" - " djnz %[_bitCount], #__LMM_FCACHE_START+(loop%= - SpiReadLsbPhs1Start%=) \n\t" - - " jmp __LMM_RET \n\t" - "SpiReadLsbPhs1End%=: \n\t" - " .compress default \n\t" + " djnz %[_bitCount], #" FC_ADDR("loop%=", "SpiReadLsbPhs1Start%=") " \n\t" + FC_END("SpiReadLsbPhs1End%=") : [_bitCount] "+r"(bits), [_clock] "+r"(clock), [_data] "+r"(tempData) diff --git a/PropWare/utility.h b/PropWare/utility.h index 4d248203..0fe61500 100644 --- a/PropWare/utility.h +++ b/PropWare/utility.h @@ -41,7 +41,7 @@ class Utility { * * @return Number of bits that are non-zero in par */ - static uint8_t count_bits (uint32_t par) { + static uint8_t count_bits(uint32_t par) { // Brian Kernighan's method for counting set bits in a variable uint8_t totalBits = 0; @@ -60,7 +60,7 @@ class Utility { * * @return Number of bits that are non-zero in par */ - static uint8_t count_bits (int32_t par) { + static uint8_t count_bits(int32_t par) { return count_bits((uint32_t) par); } @@ -99,14 +99,14 @@ class Utility { * * @return Microseconds since start */ - static inline uint32_t measure_time_interval (const register uint32_t start) { + static inline uint32_t measure_time_interval(const register uint32_t start) { return (CNT - start) / MICROSECOND; } /** * @overload */ - static inline uint32_t measure_time_interval (const register int32_t start) { + static inline uint32_t measure_time_interval(const register int32_t start) { return measure_time_interval((uint32_t) start); } @@ -121,7 +121,7 @@ class Utility { * * @return Returns the size of the largest free block of memory */ - static size_t get_largest_free_block_size (const uint8_t precision = 32) { + static size_t get_largest_free_block_size(const uint8_t precision = 32) { size_t largestSuccess = 0; size_t smallestFailure = 32 * 1024; size_t nextAttempt = 32 * 1024; @@ -142,7 +142,7 @@ class Utility { nextAttempt = (smallestFailure - largestSuccess) / 2 + - largestSuccess; + largestSuccess; } while (precision < (smallestFailure - largestSuccess)); return largestSuccess; @@ -153,7 +153,7 @@ class Utility { * * @param[out] string[] Characters array to be converted */ - static void to_lower (char string[]) { + static void to_lower(char string[]) { for (size_t i = 0; i < strlen(string); ++i) string[i] = tolower(string[i]); } @@ -163,7 +163,7 @@ class Utility { * * @param[out] string[] Characters array to be converted */ - static void to_upper (char string[]) { + static void to_upper(char string[]) { for (size_t i = 0; i < strlen(string); ++i) string[i] = toupper(string[i]); } @@ -173,7 +173,7 @@ class Utility { * * @param[in] b Boolean to be checked */ - static const char *to_string (const bool b) { + static const char *to_string(const bool b) { return b ? "true" : "false"; } @@ -187,7 +187,7 @@ class Utility { * * @return Result of log function */ - static int rom_log (int x) { + static int rom_log(int x) { int exp; unsigned short *ptr; @@ -208,11 +208,11 @@ class Utility { * * @return A bitwise flip of some of the bits in `x` */ - inline static unsigned int reverse (unsigned int x, unsigned int bits = 0) { + inline static unsigned int reverse(unsigned int x, unsigned int bits = 0) { return __builtin_propeller_rev(x, bits); } - static bool empty (const char string[]) { + static bool empty(const char string[]) { return '\0' == string[0]; } @@ -227,7 +227,7 @@ class Utility { * @return Number of elements in the array */ template - static inline size_t size_of_array (const T(&array)[N]) { + static inline size_t size_of_array(const T(&array)[N]) { return N; } @@ -237,16 +237,45 @@ class Utility { * Also known as reset or power down/up, this will restart the entire chip as if power was just applied. Note * that this will reboot __all 8 cogs__, not just one. */ - static inline void reboot () { + static inline void reboot() { __builtin_propeller_clkset(0x80); } + static Bit to_bit(const uint_fast8_t bitNumber) { + if (32 > bitNumber) + return (Bit) (1 << bitNumber); + else + return NULL_BIT; + } + + static bool bit_read(const uint32_t x, const Bit bit) { + return 0 != (x & bit); + } + + template + static void bit_write(T &x, const Bit bit, const bool value) { + if (value) + bit_set(x, bit); + else + bit_clear(x, bit); + } + + template + static void bit_set(T &x, const Bit bit) { + x |= bit; + } + + template + static void bit_clear(T &x, const Bit bit) { + x &= ~bit; + } + private: /** * @brief Static Utility class should never be instantiated. Call methods with code such as * `uint8_t bits = PropWare::Utility::count_bits(0x03);` */ - Utility () { + Utility() { } }; diff --git a/PropWare/ws2812.h b/PropWare/ws2812.h index d58039ef..2e620017 100644 --- a/PropWare/ws2812.h +++ b/PropWare/ws2812.h @@ -134,10 +134,7 @@ class WS2812 { unsigned int bitCounter = 0; __asm__ volatile ( - " fcache #(Ws2812End - Ws2812Start) \n\t" - " .compress off \n\t" - "Ws2812Start: \n\t" - + FC_START("Ws2812Start", "Ws2812End") " add %[_clock], CNT \n\t" " waitcnt %[_clock], #0 \n\t" @@ -147,7 +144,7 @@ class WS2812 { " add %[_nextLed], #4 \n\t" "fix_colors%=: \n\t" - " tjz %[_swaprg], #__LMM_FCACHE_START+(shift_out%= - Ws2812Start) \n\t" + " tjz %[_swaprg], #" FC_ADDR("shift_out%=", "Ws2812Start") " \n\t" " mov %[_t1], %[_colorbits] \n\t" " mov %[_t2], %[_colorbits] \n\t" " and %[_colorbits], #0xff \n\t" @@ -172,12 +169,9 @@ class WS2812 { " if_nc waitcnt %[_clock], %[_longPulse] ' bit0lo \n\t" " andn OUTA, %[_pinMask] \n\t" " waitcnt %[_clock], #0 \n\t" - " djnz %[_bitCounter], #__LMM_FCACHE_START+(shift_out.loop%= - Ws2812Start) \n\t" - " djnz %[_nleds], #__LMM_FCACHE_START+(frame_loop%= - Ws2812Start) \n\t" - - " jmp __LMM_RET \n\t" - "Ws2812End: \n\t" - " .compress default \n\t" + " djnz %[_bitCounter], #" FC_ADDR("shift_out.loop%=", "Ws2812Start") " \n\t" + " djnz %[_nleds], #" FC_ADDR("frame_loop%=", "Ws2812Start") " \n\t" + FC_END("Ws2812End") : [_clock] "+r"(clock), [_t1] "+r"(t1), [_t2] "+r"(t2), diff --git a/docs/BuildSystem.md b/docs/BuildSystem.md index 22f75226..c62fc92d 100644 --- a/docs/BuildSystem.md +++ b/docs/BuildSystem.md @@ -136,7 +136,8 @@ Sets the C standard to C99. Equivalent to adding "-std=c99" to `C_FLAGS` ### AUTO_CXX_STD \[default: ON\] -Sets the C++ standard to gnu++0x. Equivalent to adding "-std=gnu++0x" to `CXX_FLAGS`. +Sets the C++ standard to the latest available for the compiler. This is `gnu++0x` in GCC 4.6.1 (current PropGCC) and +`gnu++14` in GCC5 version of PropGCC. Equivalent to adding "-std=" to `CXX_FLAGS`. Default Compile Flags --------------------- diff --git a/docs/Contribute.md b/docs/Contribute.md index 69019787..13bd72b0 100644 --- a/docs/Contribute.md +++ b/docs/Contribute.md @@ -3,7 +3,7 @@ Contribute to %PropWare {#Contribute} Code contributions can be made by either [contacting David Zemon](mailto:david@zemon.name) or forking the repository and creating a pull request. If you'd like to help but don't know how, start by perusing the -[issue tracker](https://github.com/DavidZemon/PropWare/issues/) and finding something that piques your interest. +[issue tracker](https://github.com/parallaxinc/PropWare/issues/) and finding something that piques your interest. Before submitting your pull request, please be sure to read the following guidelines for %PropWare's codebase. diff --git a/docs/Download.md b/docs/Download.md index b6f1ed98..b0ff801d 100644 --- a/docs/Download.md +++ b/docs/Download.md @@ -36,31 +36,43 @@ Microsoft Windows PATH exist [here][3]. For instance, if you installed %PropWare to `C:\%PropWare` and PATH currently contains `C:\propgcc\bin`, the new value would be `C:\%PropWare\PWCMake\bin;C:\propgcc\bin`. -Linux - Debian/Ubuntu/Mint/etc +Linux (x86-64) - Debian/Ubuntu/Mint/etc ------------------------------ 1. Download the [`deb` package file][4]. -2. Use `dpkg` to install the file with: `sudo dpkg -i PropWare-2.0.0-Generic.deb`. If `cmake` is already installed, +2. Use `dpkg` to install the file with: `sudo dpkg -i PropWare-2.0.1-Generic.deb`. If `cmake` is already installed, remove it with `sudo dpkg -r cmake`. 3. `make` is the recommended build tool to use with %PropWare. If it is not already installed, install it with `sudo apt-get install make`. -Linux - RedHat/Fedora/CentOS/etc +Linux (x86-64) - RedHat/Fedora/CentOS/etc -------------------------------- 1. Download the [`rpm` package file][5]. -2. Use `rpm` to install the file with: `sudo rpm -i PropWare-2.0.0-Generic.rpm`. If `cmake` is already installed, +2. Use `rpm` to install the file with: `sudo rpm -i PropWare-2.0.1-Generic.rpm`. If `cmake` is already installed, remove it with `sudo rpm -e cmake`. 3. `make` is the recommended build tool to use with %PropWare. If it is not already installed, install it with `sudo yum install make`. +Linux (ARMv7/Raspbery Pi 2 & 3) - Raspbian/Debian/Ubuntu/etc +------------------------------------------------------------ +Raspberry Pis and other ARM platforms are not officially supported. I have run some basic and preliminary tests with the +following packages. The packages must be built manually and will therefore not be updated with the same frequency as +Windows, Linux x86-64, or Mac OSX packages. + +1. Download the [`deb` package file][6]. +2. Use `dpkg` to install the file with: `sudo dpkg -i PropWare-2.1.0-Generic.deb`. If `cmake` is already installed, + remove it with `sudo dpkg -r cmake`. +3. `make` is the recommended build tool to use with %PropWare. If it is not already installed, install it with + `sudo apt-get install make`. + Mac OSX ------- I am unable to produce easy installation packages for Mac. My apologies. Please execute the following lines at the command line to install %PropWare on your Mac: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.sh} -wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic-osx_cmake.zip?guest=1 -Ocmake.zip -wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic-propware.zip?guest=1 -Opropware.zip -wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic-examples.zip?guest=1 -Oexamples.zip +wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic-osx_cmake.zip?guest=1 -Ocmake.zip +wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic-propware.zip?guest=1 -Opropware.zip +wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic-examples.zip?guest=1 -Oexamples.zip unzip cmake.zip unzip propware.zip unzip examples.zip @@ -76,9 +88,9 @@ sudo ln -s /Applications/pwcmake.app/Contents/bin/cmakexbuild /usr/local/bin/cma To upgrade: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.sh} -wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic-osx_cmake.zip?guest=1 -Ocmake.zip -wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic-propware.zip?guest=1 -Opropware.zip -wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic-examples.zip?guest=1 -Oexamples.zip +wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic-osx_cmake.zip?guest=1 -Ocmake.zip +wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic-propware.zip?guest=1 -Opropware.zip +wget http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic-examples.zip?guest=1 -Oexamples.zip unzip cmake.zip unzip propware.zip unzip examples.zip @@ -96,8 +108,9 @@ sudo rm -rf /Applications/pwcmake.app.bak sudo rm -rf /Applications/PropWare.bak ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -[1]: http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic-propware.zip?guest=1 -[2]: http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic.exe?guest=1 +[1]: http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic-propware.zip?guest=1 +[2]: http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic.exe?guest=1 [3]: http://www.computerhope.com/issues/ch000549.htm -[4]: http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic.deb?guest=1 -[5]: http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.0-Generic.rpm?guest=1 +[4]: http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic.deb?guest=1 +[5]: http://david.zemon.name:8111/repository/download/PropWare_Release20/.lastSuccessful/PropWare-2.0.1-Generic.rpm?guest=1 +[6]: http://david.zemon.name/downloads/PropWare-2.1.0-Generic.deb diff --git a/docs/RelatedLinks.md b/docs/RelatedLinks.md index cb5f8ae2..3b65796a 100644 --- a/docs/RelatedLinks.md +++ b/docs/RelatedLinks.md @@ -5,8 +5,8 @@ Related Links {#RelatedLinks} --------- * [Download](@ref Download) * [Forum Thread](http://forums.parallax.com/showthread.php/157005-FYI-PropWare-Complete-build-system-and-library-for-PropGCC) -* [Issue Tracker](https://github.com/DavidZemon/PropWare/issues) -* [Source code](https://github.com/DavidZemon/PropWare) +* [Issue Tracker](https://github.com/parallaxinc/PropWare/issues) +* [Source code](https://github.com/parallaxinc/PropWare) * [Build Server](http://david.zemon.name:8111/project.html?projectId=PropWare&tab=projectOverview&guest=1) Forums @@ -22,7 +22,7 @@ PropGCC: GCC compiler for Parallax Propeller * [Linux][2] * [Mac][3] * [Raspberry Pi][4] -* GCC5 +* GCC6 * [Windows][5] * [Linux][6] * [Raspberry Pi][7] diff --git a/docs/images/PropWare_Logo_16.png b/docs/images/PropWare_Logo_16.png index 7c95c451..ad397752 100644 Binary files a/docs/images/PropWare_Logo_16.png and b/docs/images/PropWare_Logo_16.png differ diff --git a/docs/images/PropWare_Logo_64.png b/docs/images/PropWare_Logo_64.png index 62f05077..b0cd941a 100644 Binary files a/docs/images/PropWare_Logo_64.png and b/docs/images/PropWare_Logo_64.png differ diff --git a/docs/images/open_cmd_window.png b/docs/images/open_cmd_window.png deleted file mode 100755 index 1d2d0d74..00000000 Binary files a/docs/images/open_cmd_window.png and /dev/null differ diff --git a/docs/images/python_install.png b/docs/images/python_install.png deleted file mode 100755 index 7c82de49..00000000 Binary files a/docs/images/python_install.png and /dev/null differ diff --git a/external_libs/CMakeLists.txt b/external_libs/CMakeLists.txt index d3602de5..8965ef42 100644 --- a/external_libs/CMakeLists.txt +++ b/external_libs/CMakeLists.txt @@ -1,3 +1,6 @@ +# Turn off warnings for code that I don't own +set(WARN_ALL OFF) + #################################################################### # Find libpropeller sources #################################################################### @@ -40,7 +43,7 @@ set(HEADER_FILE_EXTENSIONS *.HPP *.Hpp) -macro(subdirlist result curdir) +function(subdirlist result curdir) file(GLOB children RELATIVE "${curdir}" "${curdir}/*") set(dirlist "") foreach (child IN LISTS children) @@ -48,17 +51,17 @@ macro(subdirlist result curdir) list(APPEND dirlist "${child}") endif () endforeach () - set(${result} ${dirlist}) -endmacro() + set(${result} ${dirlist} PARENT_SCOPE) +endfunction() -macro(compute_demo_filenames result library) +function(compute_demo_filenames result library) set(cdf_FILES "") get_filename_component(library_name "${library}" NAME) foreach (extension ".c" ".h") list(APPEND cdf_FILES "${library}/${library_name}${extension}") endforeach () - set(${result} ${cdf_FILES}) -endmacro() + set(${result} ${cdf_FILES} PARENT_SCOPE) +endfunction() # Get most categories subdirlist(CATEGORIES "${SIMPLE_ROOT}") diff --git a/external_libs/cmm/CMakeLists.txt b/external_libs/cmm/CMakeLists.txt index e57eed0c..346ed252 100644 --- a/external_libs/cmm/CMakeLists.txt +++ b/external_libs/cmm/CMakeLists.txt @@ -1,10 +1,11 @@ set(MODEL cmm) -set_compile_flags() -add_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) -add_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) -set_linker(Libpropeller_${MODEL}) -set_linker(Simple_${MODEL}) +# WAV player need to be optimized for speed, not size +set_source_files_properties("${PROJECT_SOURCE_DIR}/propsideworkspace/Learn/Simple Libraries/Audio/libwavplayer/wavplayer.c" + PROPERTIES COMPILE_FLAGS "-O3") + +create_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) +create_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) set_target_properties(Libpropeller_${MODEL} PROPERTIES OUTPUT_NAME Libpropeller) set_target_properties(Simple_${MODEL} PROPERTIES OUTPUT_NAME Simple) install(TARGETS Libpropeller_${MODEL} Simple_${MODEL} diff --git a/external_libs/cog/CMakeLists.txt b/external_libs/cog/CMakeLists.txt index 5ed82e0a..58a02a6f 100644 --- a/external_libs/cog/CMakeLists.txt +++ b/external_libs/cog/CMakeLists.txt @@ -1,10 +1,11 @@ set(MODEL cog) -set_compile_flags() -add_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) -add_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) -set_linker(Libpropeller_${MODEL}) -set_linker(Simple_${MODEL}) +# WAV player need to be optimized for speed, not size +set_source_files_properties("${PROJECT_SOURCE_DIR}/propsideworkspace/Learn/Simple Libraries/Audio/libwavplayer/wavplayer.c" + PROPERTIES COMPILE_FLAGS "-O3") + +create_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) +create_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) set_target_properties(Libpropeller_${MODEL} PROPERTIES OUTPUT_NAME Libpropeller) set_target_properties(Simple_${MODEL} PROPERTIES OUTPUT_NAME Simple) install(TARGETS Libpropeller_${MODEL} Simple_${MODEL} diff --git a/external_libs/lmm/CMakeLists.txt b/external_libs/lmm/CMakeLists.txt index c97b5074..7d9bcb4f 100644 --- a/external_libs/lmm/CMakeLists.txt +++ b/external_libs/lmm/CMakeLists.txt @@ -1,10 +1,11 @@ set(MODEL lmm) -set_compile_flags() -add_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) -add_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) -set_linker(Libpropeller_${MODEL}) -set_linker(Simple_${MODEL}) +# WAV player need to be optimized for speed, not size +set_source_files_properties("${PROJECT_SOURCE_DIR}/propsideworkspace/Learn/Simple Libraries/Audio/libwavplayer/wavplayer.c" + PROPERTIES COMPILE_FLAGS "-O3") + +create_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) +create_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) set_target_properties(Libpropeller_${MODEL} PROPERTIES OUTPUT_NAME Libpropeller) set_target_properties(Simple_${MODEL} PROPERTIES OUTPUT_NAME Simple) install(TARGETS Libpropeller_${MODEL} Simple_${MODEL} diff --git a/external_libs/xmm-single/CMakeLists.txt b/external_libs/xmm-single/CMakeLists.txt index 8d910681..a17c4d82 100644 --- a/external_libs/xmm-single/CMakeLists.txt +++ b/external_libs/xmm-single/CMakeLists.txt @@ -1,10 +1,11 @@ set(MODEL xmm-single) -set_compile_flags() -add_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) -add_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) -set_linker(Libpropeller_${MODEL}) -set_linker(Simple_${MODEL}) +# WAV player need to be optimized for speed, not size +set_source_files_properties("${PROJECT_SOURCE_DIR}/propsideworkspace/Learn/Simple Libraries/Audio/libwavplayer/wavplayer.c" + PROPERTIES COMPILE_FLAGS "-O3") + +create_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) +create_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) set_target_properties(Libpropeller_${MODEL} PROPERTIES OUTPUT_NAME Libpropeller) set_target_properties(Simple_${MODEL} PROPERTIES OUTPUT_NAME Simple) install(TARGETS Libpropeller_${MODEL} Simple_${MODEL} diff --git a/external_libs/xmm-split/CMakeLists.txt b/external_libs/xmm-split/CMakeLists.txt index e9837cd6..d540da76 100644 --- a/external_libs/xmm-split/CMakeLists.txt +++ b/external_libs/xmm-split/CMakeLists.txt @@ -1,10 +1,11 @@ set(MODEL xmm-split) -set_compile_flags() -add_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) -add_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) -set_linker(Libpropeller_${MODEL}) -set_linker(Simple_${MODEL}) +# WAV player need to be optimized for speed, not size +set_source_files_properties("${PROJECT_SOURCE_DIR}/propsideworkspace/Learn/Simple Libraries/Audio/libwavplayer/wavplayer.c" + PROPERTIES COMPILE_FLAGS "-O3") + +create_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) +create_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) set_target_properties(Libpropeller_${MODEL} PROPERTIES OUTPUT_NAME Libpropeller) set_target_properties(Simple_${MODEL} PROPERTIES OUTPUT_NAME Simple) install(TARGETS Libpropeller_${MODEL} Simple_${MODEL} diff --git a/external_libs/xmmc/CMakeLists.txt b/external_libs/xmmc/CMakeLists.txt index 04cfb44d..d51b78ee 100644 --- a/external_libs/xmmc/CMakeLists.txt +++ b/external_libs/xmmc/CMakeLists.txt @@ -1,10 +1,11 @@ set(MODEL xmmc) -set_compile_flags() -add_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) -add_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) -set_linker(Libpropeller_${MODEL}) -set_linker(Simple_${MODEL}) +# WAV player need to be optimized for speed, not size +set_source_files_properties("${PROJECT_SOURCE_DIR}/propsideworkspace/Learn/Simple Libraries/Audio/libwavplayer/wavplayer.c" + PROPERTIES COMPILE_FLAGS "-O3") + +create_library(Libpropeller_${MODEL} STATIC ${LIBPROPELLER_OBJECTS}) +create_library(Simple_${MODEL} STATIC ${SIMPLE_OBJECTS}) set_target_properties(Libpropeller_${MODEL} PROPERTIES OUTPUT_NAME Libpropeller) set_target_properties(Simple_${MODEL} PROPERTIES OUTPUT_NAME Simple) install(TARGETS Libpropeller_${MODEL} Simple_${MODEL} diff --git a/site.yml b/site.yml index bea10e60..8774e9c4 100644 --- a/site.yml +++ b/site.yml @@ -3,6 +3,6 @@ type: tools|libraries links: Documentation: http://david.zemon.name/PropWare/ Forum Thread: http://forums.parallax.com/showthread.php/157005-FYI-PropWare-Complete-build-system-and-library-for-PropGCC - Issue Tracker: https://github.com/DavidZemon/PropWare/issues - Source Code: https://github.com/DavidZemon/PropWare + Issue Tracker: https://github.com/parallaxinc/PropWare/issues + Source Code: https://github.com/parallaxinc/PropWare Build Server: http://david.zemon.name:8111/project.html?projectId=PropWare&tab=projectOverview&guest=1 diff --git a/test/PropWare/CMakeLists.txt b/test/PropWare/CMakeLists.txt index 858005a1..dd8d7157 100644 --- a/test/PropWare/CMakeLists.txt +++ b/test/PropWare/CMakeLists.txt @@ -12,13 +12,16 @@ create_test(stringbuilder_test stringbuilder_test) create_test(queue_test queue_test) create_test(utility_test utility_test) create_test(spi_test spi_test) +create_test(eeprom_test eeprom_test) +create_test(ping_test ping_test) set_tests_properties( sample_test - pin_test stringbuilder_test queue_test utility_test + eeprom_test + ping_test PROPERTIES LABELS hardware-independent) install(FILES PropWareTests.h diff --git a/test/PropWare/PropWareTests.h b/test/PropWare/PropWareTests.h index 382aa910..298bcedf 100644 --- a/test/PropWare/PropWareTests.h +++ b/test/PropWare/PropWareTests.h @@ -29,6 +29,7 @@ #include #include +#define PROPWARE_TEST #define protected public #define private public diff --git a/test/PropWare/eeprom_test.cpp b/test/PropWare/eeprom_test.cpp new file mode 100644 index 00000000..df547e92 --- /dev/null +++ b/test/PropWare/eeprom_test.cpp @@ -0,0 +1,231 @@ +/** + * @file eeprom_test.cpp + * + * @author David Zemon + * + * Hardware: + * Standard Propeller with an EEPROM 64 kB or greater + * + * @copyright + * The MIT License (MIT)
+ *
Copyright (c) 2013 David Zemon
+ *
Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions:
+ *
The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.
+ *
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "PropWareTests.h" +#include + +using namespace PropWare; + +Eeprom *testable; + +SETUP { + testable = new Eeprom(); +}; + +TEARDOWN { + if (testable) + delete testable; + testable = NULL; +}; + +TEST(Constructor_DefaultArguments) { + setUp(); + + ASSERT_EQ_MSG(&pwI2c, testable->m_driver); + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + ASSERT_EQ_MSG(Eeprom::DEFAULT_DEVICE_ADDRESS, testable->m_deviceAddress); + ASSERT_TRUE(testable->m_autoIncrement); + + tearDown(); +} + +TEST(Constructor_NonDefaultArguments) { + I2C bogus; + Eeprom localTestable(bogus, 1, 2, false); + + ASSERT_EQ_MSG((unsigned int) &bogus, (unsigned int) localTestable.m_driver); + ASSERT_EQ_MSG(1, localTestable.get_memory_address()); + ASSERT_EQ_MSG(2, localTestable.m_deviceAddress); + ASSERT_FALSE(localTestable.m_autoIncrement); + + tearDown(); +} + +TEST(GetSetMemoryAddress) { + setUp(); + + testable->set_memory_address(0x1234); + ASSERT_EQ_MSG(0x1234, testable->m_memoryAddress); + ASSERT_EQ_MSG(0x1234, testable->get_memory_address()); + + testable->set_memory_address(0x4321); + ASSERT_EQ_MSG(0x4321, testable->m_memoryAddress); + ASSERT_EQ_MSG(0x4321, testable->get_memory_address()); + + tearDown(); +} + +TEST(GetSetAutoIncrement) { + setUp(); + + testable->set_auto_increment(false); + ASSERT_FALSE(testable->m_autoIncrement); + ASSERT_FALSE(testable->is_auto_increment()); + + testable->set_auto_increment(true); + ASSERT_TRUE(testable->m_autoIncrement); + ASSERT_TRUE(testable->is_auto_increment()); + + tearDown(); +} + +TEST(Ping) { + setUp(); + + ASSERT_TRUE(testable->ping()); + + tearDown(); +} + +TEST(PutGet_SingleByte) { + setUp(); + + const uint8_t sampleByte1 = 0x5A; + + ASSERT_TRUE(testable->put(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, sampleByte1)); + ASSERT_EQ_MSG(sampleByte1, testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS)); + + const uint8_t sampleByte2 = 0xA5; + + ASSERT_TRUE(testable->put(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, sampleByte2)); + ASSERT_EQ_MSG(sampleByte2, testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS)); + + tearDown(); +} + +TEST(PutGet_Array) { + setUp(); + + uint8_t buffer[64]; + const uint8_t sampleBytes1[] = "Hello"; + + ASSERT_TRUE(testable->put(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, sampleBytes1, sizeof(sampleBytes1))); + ASSERT_TRUE(testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, buffer, sizeof(sampleBytes1))); + ASSERT_EQ_MSG(0, strcmp((char *) sampleBytes1, (char *) buffer)); + + const uint8_t sampleBytes2[] = "Goodbye"; + + ASSERT_TRUE(testable->put(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, sampleBytes2, sizeof(sampleBytes2))); + ASSERT_TRUE(testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, buffer, sizeof(sampleBytes2))); + ASSERT_EQ_MSG(0, strcmp((char *) sampleBytes2, (char *) buffer)); + + tearDown(); +} + +TEST(PutChar_IncrementEnabled) { + setUp(); + + testable->set_auto_increment(true); + + testable->put_char('H'); + testable->put_char('e'); + testable->put_char('l'); + testable->put_char('l'); + testable->put_char('o'); + + testable->set_memory_address(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS); + + ASSERT_EQ_MSG('H', testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS)); + ASSERT_EQ_MSG('e', testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS + 1)); + ASSERT_EQ_MSG('l', testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS + 2)); + ASSERT_EQ_MSG('l', testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS + 3)); + ASSERT_EQ_MSG('o', testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS + 4)); + + tearDown(); +} + +TEST(PutChar_IncrementDisabled) { + setUp(); + + testable->set_auto_increment(false); + + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + testable->put_char('H'); + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + testable->put_char('e'); + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + testable->put_char('l'); + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + testable->put_char('l'); + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + testable->put_char('o'); + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + + ASSERT_EQ_MSG('o', testable->get(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS)); + + tearDown(); +} + +TEST(GetChar_IncrementEnabled) { + setUp(); + + testable->set_auto_increment(true); + testable->puts("Hello"); + testable->set_memory_address(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS); + + ASSERT_EQ_MSG('H', testable->get_char()); + ASSERT_EQ_MSG('e', testable->get_char()); + ASSERT_EQ_MSG('l', testable->get_char()); + ASSERT_EQ_MSG('l', testable->get_char()); + ASSERT_EQ_MSG('o', testable->get_char()); + + tearDown(); +} + +TEST(GetChar_IncrementDisabled) { + setUp(); + + testable->set_auto_increment(false); + testable->puts("Hello"); + + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + ASSERT_EQ_MSG('H', testable->get_char()); + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + ASSERT_EQ_MSG('H', testable->get_char()); + ASSERT_EQ_MSG(Eeprom::DEFAULT_INITIAL_MEMORY_ADDRESS, testable->get_memory_address()); + + tearDown(); +} + +int main() { + START(EEPROM); + + RUN_TEST(Constructor_DefaultArguments); + RUN_TEST(Constructor_NonDefaultArguments); + RUN_TEST(GetSetMemoryAddress); + RUN_TEST(GetSetAutoIncrement); + RUN_TEST(Ping); + RUN_TEST(PutGet_SingleByte); + RUN_TEST(PutGet_Array); + RUN_TEST(PutChar_IncrementEnabled); + RUN_TEST(PutChar_IncrementDisabled); + RUN_TEST(GetChar_IncrementEnabled); + RUN_TEST(GetChar_IncrementDisabled); + + COMPLETE(); +} diff --git a/test/PropWare/fatfilereader_test.cpp b/test/PropWare/fatfilereader_test.cpp index d5b49118..6e1d0cb4 100644 --- a/test/PropWare/fatfilereader_test.cpp +++ b/test/PropWare/fatfilereader_test.cpp @@ -43,14 +43,14 @@ using namespace PropWare; static const char FILE_NAME[] = "fat_test.txt"; static const char FILE_NAME_UPPER[] = "FAT_TEST.TXT"; static const char BOGUS_FILE_NAME[] = "bogus.txt"; -static FatFS *g_fs; +static FatFS g_fs(new SD()); static FatFileReader *testable; void error_checker (const ErrorCode err) { if (SPI::BEG_ERROR <= err && err <= SPI::END_ERROR) SPI::get_instance()->print_error_str(&pwOut, (const SPI::ErrorCode) err); else if (SD::BEG_ERROR <= err && err <= SD::END_ERROR) - ((SD *) g_fs->m_driver)->print_error_str(pwOut, (const SD::ErrorCode) err); + ((SD *) g_fs.m_driver)->print_error_str(pwOut, (const SD::ErrorCode) err); else if (Filesystem::BEG_ERROR <= err && err <= Filesystem::END_ERROR) FatFS::print_error_str(pwOut, (const Filesystem::ErrorCode) err); else if (FatFS::BEG_ERROR <= err && err <= FatFS::END_ERROR) @@ -69,7 +69,7 @@ void clear_buffer (File *file) { SETUP { PropWare::ErrorCode err; - testable = new FatFileReader(*g_fs, FILE_NAME); + testable = new FatFileReader(g_fs, FILE_NAME); err = testable->open(); if (err) { MESSAGE("Setup failed!"); @@ -87,25 +87,25 @@ TEARDOWN { } TEST(ConstructorDestructor) { - testable = new FatFileReader(*g_fs, FILE_NAME); + testable = new FatFileReader(g_fs, FILE_NAME); // Ensure the requested filename was not all upper case (that wouldn't be a very good test if it were) ASSERT_NEQ_MSG(0, strcmp(FILE_NAME, FILE_NAME_UPPER)); ASSERT_EQ_MSG(0, strcmp(FILE_NAME_UPPER, testable->get_name())); ASSERT_EQ_MSG((unsigned int) &pwOut, (unsigned int) testable->m_logger); - ASSERT_EQ_MSG((unsigned int) g_fs->get_driver(), (unsigned int) testable->m_driver); - ASSERT_EQ_MSG((unsigned int) &g_fs->m_buf, (unsigned int) testable->m_buf); + ASSERT_EQ_MSG((unsigned int) g_fs.get_driver(), (unsigned int) testable->m_driver); + ASSERT_EQ_MSG((unsigned int) &g_fs.m_buf, (unsigned int) testable->m_buf); ASSERT_NEQ_MSG((unsigned int) NULL, (unsigned int) testable->m_buf->buf); - ASSERT_EQ_MSG((unsigned int) &g_fs->m_dirMeta, (unsigned int) testable->m_fsBufMeta); - ASSERT_EQ_MSG((unsigned int) g_fs, (unsigned int) testable->m_fs); + ASSERT_EQ_MSG((unsigned int) &g_fs.m_dirMeta, (unsigned int) testable->m_fsBufMeta); + ASSERT_EQ_MSG((unsigned int) &g_fs, (unsigned int) testable->m_fs); ASSERT_EQ_MSG(-1, testable->get_length()); tearDown(); } TEST(Exists_doesExist) { - testable = new FatFileReader(*g_fs, FILE_NAME); + testable = new FatFileReader(g_fs, FILE_NAME); PropWare::ErrorCode err; const bool exists = testable->exists(err); @@ -115,14 +115,14 @@ TEST(Exists_doesExist) { } TEST(Exists_doeesNotExist) { - testable = new FatFileReader(*g_fs, BOGUS_FILE_NAME); + testable = new FatFileReader(g_fs, BOGUS_FILE_NAME); ASSERT_FALSE(testable->exists()); tearDown(); } TEST(OpenClose) { ErrorCode err; - testable = new FatFileReader(*g_fs, FILE_NAME); + testable = new FatFileReader(g_fs, FILE_NAME); err = testable->open(); error_checker(err); @@ -140,7 +140,7 @@ TEST(OpenClose) { } TEST(Open_NonExistantFile) { - testable = new FatFileReader(*g_fs, BOGUS_FILE_NAME); + testable = new FatFileReader(g_fs, BOGUS_FILE_NAME); ASSERT_EQ_MSG(FatFile::FILENAME_NOT_FOUND, testable->open()); tearDown(); @@ -212,13 +212,11 @@ int main () { PropWare::ErrorCode err; - FatFS fs(new SD()); - if ((err = fs.mount())) { + if ((err = g_fs.mount())) { error_checker(err); failures = (uint8_t) -1; COMPLETE(); } - g_fs = &fs; RUN_TEST(ConstructorDestructor); RUN_TEST(Exists_doesExist); @@ -229,7 +227,7 @@ int main () { RUN_TEST(Tell); RUN_TEST(Seek); - delete fs.get_driver(); + delete g_fs.get_driver(); COMPLETE(); } diff --git a/test/PropWare/fatfilewriter_test.cpp b/test/PropWare/fatfilewriter_test.cpp index 283e216d..ca5f25d3 100644 --- a/test/PropWare/fatfilewriter_test.cpp +++ b/test/PropWare/fatfilewriter_test.cpp @@ -43,7 +43,7 @@ using namespace PropWare; static const char EXISTING_FILE[] = "fat_test.txt"; static const char EXISTING_FILE_UPPER[] = "FAT_TEST.TXT"; static const char NEW_FILE_NAME[] = "new_test.txt"; -static FatFS *g_fs; +static FatFS g_fs(new SD()); static FatFileWriter *testable; void error_checker (const ErrorCode err) { @@ -51,7 +51,7 @@ void error_checker (const ErrorCode err) { if (SPI::BEG_ERROR <= err && err <= SPI::END_ERROR) SPI::get_instance()->print_error_str(&pwOut, (const SPI::ErrorCode) err); else if (SD::BEG_ERROR <= err && err <= SD::END_ERROR) - ((SD *) g_fs->m_driver)->print_error_str(pwOut, (const SD::ErrorCode) err); + ((SD *) g_fs.m_driver)->print_error_str(pwOut, (const SD::ErrorCode) err); else if (Filesystem::BEG_ERROR <= err && err <= Filesystem::END_ERROR) FatFS::print_error_str(pwOut, (const Filesystem::ErrorCode) err); else if (FatFS::BEG_ERROR <= err && err <= FatFS::END_ERROR) @@ -74,7 +74,7 @@ void clear_buffer (File *file) { SETUP { PropWare::ErrorCode err; - testable = new FatFileWriter(*g_fs, NEW_FILE_NAME); + testable = new FatFileWriter(g_fs, NEW_FILE_NAME); err = testable->open(); if (err) { MESSAGE("Setup failed!"); @@ -89,20 +89,20 @@ TEARDOWN { delete testable; testable = NULL; } - g_fs->flush_fat(); + g_fs.flush_fat(); } TEST(ConstructorDestructor) { // Ensure the requested filename was not all upper case (that wouldn't be a very good test if it were) ASSERT_NEQ_MSG(0, strcmp(EXISTING_FILE, EXISTING_FILE_UPPER)); - testable = new FatFileWriter(*g_fs, EXISTING_FILE); + testable = new FatFileWriter(g_fs, EXISTING_FILE); ASSERT_EQ_MSG(0, strcmp(EXISTING_FILE_UPPER, testable->get_name())); ASSERT_EQ_MSG((unsigned int) &pwOut, (unsigned int) testable->m_logger); - ASSERT_EQ_MSG((unsigned int) g_fs->get_driver(), (unsigned int) testable->m_driver); - ASSERT_EQ_MSG((unsigned int) &g_fs->m_buf, (unsigned int) testable->m_buf); - ASSERT_EQ_MSG((unsigned int) testable->m_fs, (unsigned int) g_fs); + ASSERT_EQ_MSG((unsigned int) g_fs.get_driver(), (unsigned int) testable->m_driver); + ASSERT_EQ_MSG((unsigned int) &g_fs.m_buf, (unsigned int) testable->m_buf); + ASSERT_EQ_MSG((unsigned int) testable->m_fs, (unsigned int) &g_fs); ASSERT_EQ_MSG(-1, testable->get_length()); ASSERT_EQ_MSG(false, testable->m_fileMetadataModified); @@ -110,13 +110,13 @@ TEST(ConstructorDestructor) { } TEST(Exists_doesNotExist) { - testable = new FatFileWriter(*g_fs, NEW_FILE_NAME); + testable = new FatFileWriter(g_fs, NEW_FILE_NAME); ASSERT_FALSE(testable->exists()); tearDown(); } TEST(Exists_doesExist) { - testable = new FatFileWriter(*g_fs, EXISTING_FILE); + testable = new FatFileWriter(g_fs, EXISTING_FILE); PropWare::ErrorCode err; const bool exists = testable->exists(err); @@ -128,7 +128,7 @@ TEST(Exists_doesExist) { TEST(OpenClose_ExistingFile) { ErrorCode err; - testable = new FatFileWriter(*g_fs, EXISTING_FILE); + testable = new FatFileWriter(g_fs, EXISTING_FILE); err = testable->open(); error_checker(err); @@ -146,7 +146,7 @@ TEST(OpenClose_ExistingFile) { TEST(OpenCloseDelete_NonExistingFile) { ErrorCode err; - testable = new FatFileWriter(*g_fs, NEW_FILE_NAME); + testable = new FatFileWriter(g_fs, NEW_FILE_NAME); ASSERT_FALSE(testable->exists()); @@ -201,18 +201,18 @@ TEST(SafePutChar_singleChar) { const BlockStorage *driver = testable->m_driver; BlockStorage::Buffer *buffer = testable->m_buf; delete testable; - g_fs->flush_fat(); + g_fs.flush_fat(); clear_buffer(driver, buffer); } - FatFileReader reader(*g_fs, NEW_FILE_NAME); + FatFileReader reader(g_fs, NEW_FILE_NAME); ASSERT_EQ_MSG(0, reader.open()); ASSERT_EQ_MSG(1, reader.get_length()); // Reader opens file after write ASSERT_EQ_MSG(sampleChar, reader.get_char()); reader.close(); - testable = new FatFileWriter(*g_fs, NEW_FILE_NAME); + testable = new FatFileWriter(g_fs, NEW_FILE_NAME); err = testable->remove(); error_checker(err); ASSERT_EQ_MSG(0, err); // testable->remove() @@ -247,19 +247,19 @@ TEST(SafePutChar_MultiLine) { const BlockStorage *driver = testable->m_driver; BlockStorage::Buffer *buffer = testable->m_buf; delete testable; - g_fs->flush_fat(); + g_fs.flush_fat(); clear_buffer(driver, buffer); } - FatFileReader reader(*g_fs, NEW_FILE_NAME); + FatFileReader reader(g_fs, NEW_FILE_NAME); ASSERT_EQ_MSG(0, reader.open()); ASSERT_EQ_MSG(sizeof(testString), reader.get_length()); for (unsigned int i = 0; i < sizeof(testString); ++i) ASSERT_EQ_MSG(testString[i], reader.get_char()); reader.close(); - testable = new FatFileWriter(*g_fs, NEW_FILE_NAME); + testable = new FatFileWriter(g_fs, NEW_FILE_NAME); err = testable->remove(); error_checker(err); ASSERT_EQ_MSG(0, err); // testable->remove() @@ -280,7 +280,7 @@ TEST(CopyFile) { uint8_t rawBuffer[SD::SECTOR_SIZE]; BlockStorage::MetaData bufferMeta; BlockStorage::Buffer readBuffer = {rawBuffer, &bufferMeta}; - FatFileReader reader(*g_fs, EXISTING_FILE, &readBuffer); + FatFileReader reader(g_fs, EXISTING_FILE, &readBuffer); ASSERT_EQ_MSG(0, reader.open()); MESSAGE("Files opened..."); @@ -301,7 +301,7 @@ TEST(CopyFile) { const BlockStorage *driver = testable->m_driver; BlockStorage::Buffer *buffer = testable->m_buf; delete testable; - ASSERT_EQ_MSG(0, g_fs->flush_fat()); + ASSERT_EQ_MSG(0, g_fs.flush_fat()); clear_buffer(driver, buffer); } @@ -311,7 +311,7 @@ TEST(CopyFile) { // Reset reader ASSERT_EQ_MSG(0, reader.seek(0, File::BEG)); - FatFileReader fileWriterChecker(*g_fs, NEW_FILE_NAME); + FatFileReader fileWriterChecker(g_fs, NEW_FILE_NAME); ASSERT_EQ_MSG(0, fileWriterChecker.open()); ASSERT_EQ_MSG(reader.get_length(), fileWriterChecker.get_length()); @@ -331,7 +331,7 @@ TEST(CopyFile) { fileWriterChecker.close(); - testable = new FatFileWriter(*g_fs, NEW_FILE_NAME); + testable = new FatFileWriter(g_fs, NEW_FILE_NAME); err = testable->remove(); error_checker(err); ASSERT_EQ_MSG(0, err); // testable->remove() @@ -350,8 +350,7 @@ int main () { START(FatFileReaderTest); - g_fs = new FatFS(new SD()); - if ((err = g_fs->mount())) { + if ((err = g_fs.mount(1))) { error_checker(err); failures = (uint8_t) -1; COMPLETE(); @@ -366,9 +365,7 @@ int main () { RUN_TEST(SafePutChar_MultiLine); RUN_TEST(CopyFile); - const BlockStorage *driver = g_fs->get_driver(); - delete g_fs; - delete driver; + delete g_fs.get_driver(); COMPLETE(); } diff --git a/test/PropWare/fatfs_test.cpp b/test/PropWare/fatfs_test.cpp index 543b43e7..a88a7ac0 100644 --- a/test/PropWare/fatfs_test.cpp +++ b/test/PropWare/fatfs_test.cpp @@ -112,6 +112,18 @@ TEST(Mount_withParameter0) { tearDown(); } +TEST(Mount_withParameter1) { + setUp(); + + ErrorCode err; + + err = testable->mount(1); + error_checker(err); + ASSERT_EQ_MSG(FatFS::NO_ERROR, err); + + tearDown(); +} + TEST(Mount_withParameter4) { setUp(); @@ -136,6 +148,7 @@ int main () { RUN_TEST(ReadMasterBootRecord); RUN_TEST(Mount_defaultParameters); RUN_TEST(Mount_withParameter0); + RUN_TEST(Mount_withParameter1); RUN_TEST(Mount_withParameter4); COMPLETE(); diff --git a/test/PropWare/ping_test.cpp b/test/PropWare/ping_test.cpp new file mode 100644 index 00000000..e62b7cc0 --- /dev/null +++ b/test/PropWare/ping_test.cpp @@ -0,0 +1,88 @@ +/** + * @file ping_test.cpp + * + * @author David Zemon + * + * @copyright + * The MIT License (MIT)
+ *
Copyright (c) 2013 David Zemon
+ *
Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions:
+ *
The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.
+ *
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "PropWareTests.h" +#include + +unsigned int g_clockTicks; + +class MockPing: public PropWare::Ping { + public: + MockPing() + : Ping(PropWare::Pin::NULL_PIN) { + } + + virtual unsigned int get_clock_ticks() const { + return g_clockTicks; + } +}; + +MockPing testable; + +TEARDOWN { +} + +TEST(GetMicroseconds) { + g_clockTicks = 10*MICROSECOND; + + ASSERT_EQ_MSG(10, testable.get_microseconds()); + + tearDown(); +} + +TEST(GetMillimeters) { + g_clockTicks = MICROSECOND; + + ASSERT_EQ_MSG(17, testable.get_millimeters()); + + tearDown(); +} + +TEST(GetCentimeters) { + g_clockTicks = 1000*MICROSECOND; + + ASSERT_EQ_MSG(17, testable.get_centimeters()); + + tearDown(); +} + +TEST(GetInches) { + g_clockTicks = 1480*MICROSECOND; + + ASSERT_EQ_MSG(10, testable.get_inches()); + + tearDown(); +} + +int main() { + START(PingTest); + + RUN_TEST(GetMicroseconds); + RUN_TEST(GetMillimeters); + RUN_TEST(GetCentimeters); + RUN_TEST(GetInches); + + COMPLETE(); +} diff --git a/test/PropWare/queue_test.cpp b/test/PropWare/queue_test.cpp index 237db46f..6d1cd0a9 100644 --- a/test/PropWare/queue_test.cpp +++ b/test/PropWare/queue_test.cpp @@ -185,13 +185,13 @@ TEST(ManyElements) { } else { ASSERT_EQ_MSG(SIZE, testable->size()); } - ASSERT_EQ_MSG(i, testable->m_array[testable->m_head]); + ASSERT_EQ_MSG((int) i, testable->m_array[testable->m_head]); } // Dequeue many elements const size_t DEQUEUE_LOOP_START = TEST_SIZE - SIZE; for (unsigned int i = DEQUEUE_LOOP_START; i < TEST_SIZE; ++i) { - ASSERT_EQ_MSG(i, testable->dequeue()); + ASSERT_EQ_MSG((int) i, testable->dequeue()); } tearDown(); diff --git a/test/PropWare/utility_test.cpp b/test/PropWare/utility_test.cpp index 110f85e2..81a23667 100644 --- a/test/PropWare/utility_test.cpp +++ b/test/PropWare/utility_test.cpp @@ -169,6 +169,48 @@ TEST(MeasureTimeInterval) { tearDown(); } +TEST(BitRead) { + const uint32_t x = BIT_0; + ASSERT_TRUE(Utility::bit_read(x, BIT_0)); + ASSERT_FALSE(Utility::bit_read(x, BIT_1)); + + const uint32_t y = BIT_1; + ASSERT_FALSE(Utility::bit_read(y, BIT_0)); + ASSERT_TRUE(Utility::bit_read(y, BIT_1)); + + const uint32_t z = BIT_31 | BIT_16; + ASSERT_FALSE(Utility::bit_read(z, BIT_0)); + ASSERT_FALSE(Utility::bit_read(z, BIT_1)); + ASSERT_TRUE(Utility::bit_read(z, BIT_16)); + ASSERT_TRUE(Utility::bit_read(z, BIT_31)); + + tearDown(); +} + +TEST(BitWrite) { + uint32_t x = 0; + Utility::bit_write(x, BIT_0, true); + ASSERT_EQ(BIT_0, x); + + Utility::bit_write(x, BIT_1, true); + ASSERT_EQ(BIT_0 | BIT_1, x); + + Utility::bit_write(x, BIT_31, true); + ASSERT_EQ(BIT_0 | BIT_1 | BIT_31, x); + + + Utility::bit_write(x, BIT_0, false); + ASSERT_EQ(BIT_1 | BIT_31, x); + + Utility::bit_write(x, BIT_1, false); + ASSERT_EQ(BIT_31, x); + + Utility::bit_write(x, BIT_31, false); + ASSERT_EQ(0, x); + + tearDown(); +} + int main () { START(UtilityTest); @@ -180,6 +222,7 @@ int main () { RUN_TEST(ToString); RUN_TEST(RomLog); RUN_TEST(MeasureTimeInterval); + RUN_TEST(BitRead); COMPLETE(); } diff --git a/version.txt b/version.txt index 38f77a65..7ec1d6db 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.0.1 +2.1.0