Skip to content
Snippets Groups Projects
Commit 6884e112 authored by Cristian Maglie's avatar Cristian Maglie Committed by Cristian Maglie
Browse files

Added pulseIn implementation

parent d20e0d2a
No related branches found
No related tags found
No related merge requests found
......@@ -71,7 +71,7 @@ void loop( void ) ;
#include "Tone.h"
#include "WMath.h"
#include "HardwareSerial.h"
// #include "wiring_pulse.h"
#include "pulse.h"
#include "delay.h"
#include "Uart.h"
#endif // __cplusplus
......
/*
Copyright (c) 2015 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
// See pulse_asm.S
extern unsigned long countPulseASM(const volatile uint32_t *port, uint32_t bit, uint32_t stateMask, unsigned long maxloops);
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse. */
uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout)
{
// cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution. calling
// digitalRead() instead yields much coarser resolution.
PinDescription p = g_APinDescription[pin];
uint32_t bit = 1 << p.ulPin;
uint32_t stateMask = state ? bit : 0;
// convert the timeout from microseconds to a number of times through
// the initial loop; it takes (roughly) 13 clock cycles per iteration.
uint32_t maxloops = microsecondsToClockCycles(timeout) / 13;
uint32_t width = countPulseASM(&(PORT->Group[p.ulPort].IN.reg), bit, stateMask, maxloops);
// convert the reading to microseconds. The loop has been determined
// to be 13 clock cycles long and have about 16 clocks between the edge
// and the start of the loop. There will be some error introduced by
// the interrupt handlers.
if (width)
return clockCyclesToMicroseconds(width * 13 + 16);
else
return 0;
}
/*
Copyright (c) 2015 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/*
* \brief Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse.
*/
uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout);
#ifdef __cplusplus
// Provides a version of pulseIn with a default argument (C++ only)
uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout = 1000000L);
} // extern "C"
#endif
/*
Copyright (c) 2015 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
The following function has been compiled to ASM with gcc
unsigned long countPulseASM(const volatile uint32_t *port, uint32_t bit, uint32_t stateMask, unsigned long maxloops)
{
unsigned long width = 0;
// wait for any previous pulse to end
while ((*port & bit) == stateMask)
if (--maxloops == 0)
return 0;
// wait for the pulse to start
while ((*port & bit) != stateMask)
if (--maxloops == 0)
return 0;
// wait for the pulse to stop
while ((*port & bit) == stateMask) {
if (++width == maxloops)
return 0;
}
return width;
}
using the command line:
arm-none-eabi-gcc -mcpu=cortex-m0plus -mthumb -c -Os -W -ffunction-sections -fdata-sections \
-nostdlib --param max-inline-insns-single=500 -fno-exceptions -MMD \
-DF_CPU=48000000L -DARDUINO=10602 -DARDUINO_SAMD_ZERO -DARDUINO_ARCH_SAMD \
-D__SAMD21G18A__ -DUSB_VID=0x2341 -DUSB_PID=0x004d -DUSBCON \
-DUSB_MANUFACTURER="Arduino LLC" -DUSB_PRODUCT="Arduino Zero" \
-I/Code/arduino/build/linux/work/hardware/tools/CMSIS/CMSIS/Include/ \
-I/Code/arduino/build/linux/work/hardware/tools/CMSIS/Device/ATMEL/ \
-I/Code/arduino/build/linux/work/hardware/arduino/samd/cores/arduino \
-I/Code/arduino/build/linux/work/hardware/arduino/samd/variants/arduino_zero \
count.c -Wa,-ahlmsd=output.lst -dp -fverbose-asm -S
The result has been slightly edited to increase readability.
*/
.cpu cortex-m0plus
.fpu softvfp
.eabi_attribute 20, 1 @ Tag_ABI_FP_denormal
.eabi_attribute 21, 1 @ Tag_ABI_FP_exceptions
.eabi_attribute 23, 3 @ Tag_ABI_FP_number_model
.eabi_attribute 24, 1 @ Tag_ABI_align8_needed
.eabi_attribute 25, 1 @ Tag_ABI_align8_preserved
.eabi_attribute 26, 1 @ Tag_ABI_enum_size
.eabi_attribute 30, 4 @ Tag_ABI_optimization_goals
.eabi_attribute 34, 0 @ Tag_CPU_unaligned_access
.eabi_attribute 18, 4 @ Tag_ABI_PCS_wchar_t
.file "count.c"
@ GNU C (GNU Tools for ARM Embedded Processors (Arduino build)) version 4.8.3 20140228 (release) [ARM/embedded-4_8-branch revision 208322] (arm-none-eabi)
@ compiled by GNU C version 4.3.2, GMP version 4.3.2, MPFR version 2.4.2, MPC version 0.8.1
@ GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
@ options passed:
@ -I /Code/arduino/build/linux/work/hardware/tools/CMSIS/CMSIS/Include/
@ -I /Code/arduino/build/linux/work/hardware/tools/CMSIS/Device/ATMEL/
@ -I /Code/arduino/build/linux/work/hardware/arduino/samd/cores/arduino
@ -I /Code/arduino/build/linux/work/hardware/arduino/samd/variants/arduino_zero
@ -imultilib armv6-m
@ -iprefix /Code/arduino/build/linux/work/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin/../lib/gcc/arm-none-eabi/4.8.3/
@ -isysroot /Code/arduino/build/linux/work/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin/../arm-none-eabi
@ -MMD count.d -D__USES_INITFINI__ -D F_CPU=48000000L -D ARDUINO=10602
@ -D ARDUINO_SAMD_ZERO -D ARDUINO_ARCH_SAMD -D __SAMD21G18A__
@ -D USB_VID=0x2341 -D USB_PID=0x004d -D USBCON
@ -D USB_MANUFACTURER=Arduino LLC -D USB_PRODUCT=Arduino Zero count.c
@ -mcpu=cortex-m0plus -mthumb -Os -Wextra -ffunction-sections
@ -fdata-sections -fno-exceptions -fverbose-asm
@ --param max-inline-insns-single=500
@ options enabled: -faggressive-loop-optimizations -fauto-inc-dec
@ -fbranch-count-reg -fcaller-saves -fcombine-stack-adjustments -fcommon
@ -fcompare-elim -fcprop-registers -fcrossjumping -fcse-follow-jumps
@ -fdata-sections -fdefer-pop -fdelete-null-pointer-checks -fdevirtualize
@ -fdwarf2-cfi-asm -fearly-inlining -feliminate-unused-debug-types
@ -fexpensive-optimizations -fforward-propagate -ffunction-cse
@ -ffunction-sections -fgcse -fgcse-lm -fgnu-runtime
@ -fguess-branch-probability -fhoist-adjacent-loads -fident -fif-conversion
@ -fif-conversion2 -findirect-inlining -finline -finline-atomics
@ -finline-functions -finline-functions-called-once
@ -finline-small-functions -fipa-cp -fipa-profile -fipa-pure-const
@ -fipa-reference -fipa-sra -fira-hoist-pressure -fira-share-save-slots
@ -fira-share-spill-slots -fivopts -fkeep-static-consts
@ -fleading-underscore -fmath-errno -fmerge-constants -fmerge-debug-strings
@ -fomit-frame-pointer -foptimize-register-move -foptimize-sibling-calls
@ -fpartial-inlining -fpeephole -fpeephole2 -fprefetch-loop-arrays
@ -freg-struct-return -fregmove -freorder-blocks -freorder-functions
@ -frerun-cse-after-loop -fsched-critical-path-heuristic
@ -fsched-dep-count-heuristic -fsched-group-heuristic -fsched-interblock
@ -fsched-last-insn-heuristic -fsched-pressure -fsched-rank-heuristic
@ -fsched-spec -fsched-spec-insn-heuristic -fsched-stalled-insns-dep
@ -fschedule-insns2 -fsection-anchors -fshow-column -fshrink-wrap
@ -fsigned-zeros -fsplit-ivs-in-unroller -fsplit-wide-types
@ -fstrict-aliasing -fstrict-overflow -fstrict-volatile-bitfields
@ -fsync-libcalls -fthread-jumps -ftoplevel-reorder -ftrapping-math
@ -ftree-bit-ccp -ftree-builtin-call-dce -ftree-ccp -ftree-ch
@ -ftree-coalesce-vars -ftree-copy-prop -ftree-copyrename -ftree-cselim
@ -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre
@ -ftree-loop-if-convert -ftree-loop-im -ftree-loop-ivcanon
@ -ftree-loop-optimize -ftree-parallelize-loops= -ftree-phiprop -ftree-pre
@ -ftree-pta -ftree-reassoc -ftree-scev-cprop -ftree-sink
@ -ftree-slp-vectorize -ftree-slsr -ftree-sra -ftree-switch-conversion
@ -ftree-tail-merge -ftree-ter -ftree-vect-loop-version -ftree-vrp
@ -funit-at-a-time -fverbose-asm -fzero-initialized-in-bss -mlittle-endian
@ -mpic-data-is-text-relative -msched-prolog -mthumb
@ -mvectorize-with-neon-quad
.section .text.countPulseASM,"ax",%progbits
.align 1
.global countPulseASM
.code 16
.thumb_func
.type countPulseASM, %function
countPulseASM:
push {r4, r5, lr} @ @ 112 *push_multi [length = 2]
.L2:
ldr r4, [r0] @ D.11539, *port_7(D) @ 22 *thumb1_movsi_insn/7 [length = 2]
and r4, r1 @ D.11539, bit @ 24 *thumb1_andsi3_insn [length = 2]
cmp r4, r2 @ D.11539, stateMask @ 25 cbranchsi4_insn/1 [length = 4]
bne .L5 @,
sub r3, r3, #1 @ maxloops, @ 17 *thumb1_addsi3/2 [length = 2]
cmp r3, #0 @ maxloops, @ 18 cbranchsi4_insn/1 [length = 4]
bne .L2 @,
b .L10 @ @ 127 *thumb_jump [length = 2]
.L6:
sub r3, r3, #1 @ maxloops, @ 30 *thumb1_addsi3/2 [length = 2]
cmp r3, #0 @ maxloops, @ 31 cbranchsi4_insn/1 [length = 4]
beq .L10 @,
.L5:
ldr r4, [r0] @ D.11539, *port_7(D) @ 35 *thumb1_movsi_insn/7 [length = 2]
and r4, r1 @ D.11539, bit @ 37 *thumb1_andsi3_insn [length = 2]
cmp r4, r2 @ D.11539, stateMask @ 38 cbranchsi4_insn/1 [length = 4]
bne .L6 @,
mov r4, #0 @ width, @ 7 *thumb1_movsi_insn/2 [length = 2]
.L7:
ldr r5, [r0] @ D.11539, *port_7(D) @ 48 *thumb1_movsi_insn/7 [length = 2]
and r5, r1 @ D.11539, bit @ 50 *thumb1_andsi3_insn [length = 2]
cmp r5, r2 @ D.11539, stateMask @ 51 cbranchsi4_insn/1 [length = 4]
bne .L13 @,
add r4, r4, #1 @ width, @ 43 *thumb1_addsi3/1 [length = 2]
cmp r4, r3 @ width, maxloops @ 44 cbranchsi4_insn/1 [length = 4]
bne .L7 @,
mov r0, #0 @ D.11539, @ 11 *thumb1_movsi_insn/2 [length = 2]
b .L3 @ @ 130 *thumb_jump [length = 2]
.L13:
mov r0, r4 @ D.11539, width @ 9 *thumb1_movsi_insn/1 [length = 2]
b .L3 @ @ 132 *thumb_jump [length = 2]
.L10:
mov r0, r3 @ D.11539, maxloops @ 8 *thumb1_movsi_insn/1 [length = 2]
.L3:
@ sp needed @ @ 115 force_register_use [length = 0]
pop {r4, r5, pc}
.size countPulseASM, .-countPulseASM
.ident "GCC: (GNU Tools for ARM Embedded Processors (Arduino build)) 4.8.3 20140228 (release) [ARM/embedded-4_8-branch revision 208322]"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment