arduino-nRF5 icon indicating copy to clipboard operation
arduino-nRF5 copied to clipboard

Implement pin output modes

Open d00616 opened this issue 8 years ago • 11 comments

When a pin is switched to OUTPUT the GPIO_PIN_CNF_DRIVE_S0S1 profile is enabled. What is your opinion to implement mode switching via OUTPUT_S0S1, OUTPUT_H0S1, OUTPUT_H0H1, OUTPUT_D0S1.... OUTPUT_H0D1?

d00616 avatar Oct 10 '16 19:10 d00616

Can you please explain the differences with these modes?

Also, how do they map to the existing Arduino pinMode API and modes: https://www.arduino.cc/en/Reference/PinMode

sandeepmistry avatar Oct 10 '16 19:10 sandeepmistry

Extending output modes breaks the Arduino compatibility like INPUT_PULLDOWN it already does. This is implemented here but not available when using AVR.

The modes allows to switch a port into High Drive mode. This allows a higher current. The allowed current is:

nRF51: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.3.pdf (Table 62)

  • Low Drive: 0.5 mA
  • High Drive: 5 mA

nRF52: http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/gpio.html?cp=2_2_0_19_3_0#unique_1110673565

  • Low Drive maximum: 2-5 mA (0.5 mA)
  • High Drive maximum: 9-14/10-15 mA (5 mA)

I don't find a regulation about how many ports are allowed to use high drive at the same time for nRF52. For nRF51there is a Note "Maximum number of pins with 5 mA high drive is 3" in nRF51822 Product Specification v3.3 Table 63.

In my opinion the GPIO cannot be used without understanding and reading the data sheet. With actual settings driving a LED woks, but outside electrical specification. Switching any port into High Drive mode is not possible because there is a limit for nRF51 and maybe nRF52.

The next feature is the D0S1/D0H1 mode which means disconnect when Low. The S0D1 and H0D1 Mode is only available using a nRF52.

d00616 avatar Oct 11 '16 16:10 d00616

@d00616 thanks for the explanation.

Let's wait and see how the official Arduino SAMD core decides to handle this in https://github.com/arduino/ArduinoCore-samd/issues/158

sandeepmistry avatar Oct 15 '16 14:10 sandeepmistry

@sandeepmistry Let's wait. Do you know if someone working on to define something?

d00616 avatar Oct 15 '16 17:10 d00616

@d00616 not that I'm aware of, if you have any suggestions please comment on the SAMD issue I linked to.

sandeepmistry avatar Oct 16 '16 15:10 sandeepmistry

It looks like there is no way to find a solution which is compatible to SAMD and NRF without limiting capabilities of NRF GPIO.

d00616 avatar Oct 20 '16 15:10 d00616

@d00616 ok, we should really think if we need to expose all the options.

Advanced users can always access the nRF5x specific mode directly via registers or through a new nRF51 specific library.

sandeepmistry avatar Oct 23 '16 20:10 sandeepmistry

@sandeepmistry I work on a board.txt generator. My idea is to generate a board configuration by providing YAML files. This simplifies the management of boards, reduce the number of menu items and allows to manage boards like https://github.com/sandeepmistry/arduino-nRF5/issues/165 outside of this repository.

When I can configure a board in YAML, I can define pin mode overrides to support all nRF5 output modes, when a pin is configured as OUTPUT pin. What do you think about it?

The board generator can manage depending libraries to access board specific hardware.

d00616 avatar Jun 05 '17 16:06 d00616

This zip file contains diffs for wiring_digital.h wiring_digital_c and wiring_constants.h to add following extra pinModes to access highdrive and disconnect on the nRF52

(ZIP file removed for cyber security reasons)

  • For nRF52 extra modes are available.
  • Standard drive is typically 2mA (min 1mA) '0' sink (low) or '1' source (high). High drive (VDD > 2.7V) is typically 10mA low, 9mA high (min 6mA)
  • OUTPUT_S0S1 Standard '0', standard '1' same as OUTPUT
  • OUTPUT_H0S1 High drive '0', standard '1'
  • OUTPUT_S0H1 Standard '0', high drive '1'
  • OUTPUT_H0H1 High drive '0', high 'drive '1''
  • OUTPUT_D0S1 Disconnect '0' standard '1' (normally used for wired-or connections)
  • OUTPUT_D0H1 Disconnect '0', high drive '1' (normally used for wired-or connections)
  • OUTPUT_S0D1 Standard '0'. disconnect '1' (normally used for wired-and connections)
  • OUTPUT_H0D1 High drive '0', disconnect '1' (normally used for wired-and connections)
  • NOTE P0.27 should be only low (standard) drive, low frequency

drmpf avatar Mar 10 '19 05:03 drmpf

@drmpf I have deleted your ZIP files as it's in poor taste to attach a ZIP file with potentially malicious content. If you wish to share a modification to this project please to a PR or share just the raw code as text.

dlabun avatar Mar 11 '19 03:03 dlabun

no problem, I posted zip because github allows that type of file, but not diffs

--- \hardware\nRF5\0.6.0\cores\nRF5\wiring_digital.c	2018-08-11 05:24:03.000000000 +-1100
+++ \hardware\nRF5\0.6.0\cores\nRF5\wiring_digital.c	2019-03-10 15:43:27.000000000 +-1100
@@ -70,12 +70,21 @@
                                | ((uint32_t)GPIO_PIN_CNF_PULL_Disabled    << GPIO_PIN_CNF_PULL_Pos)
                                | ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1       << GPIO_PIN_CNF_DRIVE_Pos)
                                | ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled   << GPIO_PIN_CNF_SENSE_Pos);
     break ;
 
     default:
+    	if ((ulMode >= OUTPUT_S0S1) && (ulMode <= OUTPUT_H0D1)) {
+    		uint32_t drive = ulMode - OUTPUT_S0S1; 
+    		// Set pin to output mode with specified drive
+    		NRF_GPIO->PIN_CNF[ulPin] = ((uint32_t)GPIO_PIN_CNF_DIR_Output       << GPIO_PIN_CNF_DIR_Pos)
+                               | ((uint32_t)GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
+                               | ((uint32_t)GPIO_PIN_CNF_PULL_Disabled    << GPIO_PIN_CNF_PULL_Pos)
+                               | ((uint32_t)drive       << GPIO_PIN_CNF_DRIVE_Pos)
+                               | ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled   << GPIO_PIN_CNF_SENSE_Pos);
+        } // else
       // do nothing
     break ;
   }
 }
 
 void digitalWrite( uint32_t ulPin, uint32_t ulVal )
--- \hardware\nRF5\0.6.0\cores\nRF5\wiring_digital.h	2018-08-11 05:24:03.000000000 +-1100
+++ \hardware\nRF5\0.6.0\cores\nRF5\wiring_digital.h	2019-03-10 15:43:27.000000000 +-1100
@@ -24,15 +24,28 @@
 #endif
 
 // #include "WVariant.h"
 
 /**
  * \brief Configures the specified pin to behave either as an input or an output. See the description of digital pins for details.
+ * For nRF52 extra modes are available.  
+ * Standard drive is typically 2mA (min 1mA) '0' sink (low) or '1' source (high). High drive (VDD > 2.7V) is typically 10mA low, 9mA high (min 6mA)
  *
+ * OUTPUT_S0S1  Standard '0', standard '1'  same as OUTPUT
+ * OUTPUT_H0S1  High drive '0', standard '1'
+ * OUTPUT_S0H1  Standard '0', high drive '1'
+ * OUTPUT_H0H1  High drive '0', high 'drive '1''
+ * OUTPUT_D0S1  Disconnect '0' standard '1' (normally used for wired-or connections) 
+ * OUTPUT_D0H1  Disconnect '0', high drive '1' (normally used for wired-or connections) 
+ * OUTPUT_S0D1  Standard '0'. disconnect '1' (normally used for wired-and connections) 
+ * OUTPUT_H0D1  High drive '0', disconnect '1' (normally used for wired-and connections) 
+ * NOTE P0.27 should be only low (standard) drive, low frequency
+ *
  * \param ulPin The number of the pin whose mode you wish to set
  * \param ulMode Can be INPUT, OUTPUT, INPUT_PULLUP or INPUT_PULLDOWN
+ * or OUTPUT_S0S1, OUTPUT_H0S1, OUTPUT_S0H1, OUTPUT_H1H1, OUTPUT_D0S1, OUTPUT_D0H1, OUTPUT_S0D1, OUTPUT_H0D1
  */
 extern void pinMode( uint32_t dwPin, uint32_t dwMode ) ;
 
 /**
  * \brief Write a HIGH or a LOW value to a digital pin.
  *
--- \hardware\nRF5\0.6.0\cores\nRF5\wiring_constants.h	2018-08-11 05:24:03.000000000 +-1100
+++ \hardware\nRF5\0.6.0\cores\nRF5\wiring_constants.h	2019-03-10 15:43:27.000000000 +-1100
@@ -28,12 +28,33 @@
 
 #define INPUT           (0x0)
 #define OUTPUT          (0x1)
 #define INPUT_PULLUP    (0x2)
 #define INPUT_PULLDOWN  (0x3)
 
+/*** from nrf52_bitfields.h
+#define GPIO_PIN_CNF_DRIVE_S0S1 (0UL) //!< Standard '0', standard '1' 
+#define GPIO_PIN_CNF_DRIVE_H0S1 (1UL) //!< High drive '0', standard '1' 
+#define GPIO_PIN_CNF_DRIVE_S0H1 (2UL) //!< Standard '0', high drive '1' 
+#define GPIO_PIN_CNF_DRIVE_H0H1 (3UL) //!< High drive '0', high 'drive '1'' 
+#define GPIO_PIN_CNF_DRIVE_D0S1 (4UL) //!< Disconnect '0' standard '1' (normally used for wired-or connections) 
+#define GPIO_PIN_CNF_DRIVE_D0H1 (5UL) //!< Disconnect '0', high drive '1' (normally used for wired-or connections) 
+#define GPIO_PIN_CNF_DRIVE_S0D1 (6UL) //!< Standard '0'. disconnect '1' (normally used for wired-and connections) 
+#define GPIO_PIN_CNF_DRIVE_H0D1 (7UL) //!< High drive '0', disconnect '1' (normally used for wired-and connections) 
+*********************/
+
+// The default OUTPUT is SOS1
+#define OUTPUT_S0S1     (0x10+0x0)
+#define OUTPUT_H0S1     (0x10+0x1)
+#define OUTPUT_S0H1     (0x10+0x2)
+#define OUTPUT_H0H1     (0x10+0x3)
+#define OUTPUT_D0S1     (0x10+0x4)
+#define OUTPUT_D0H1     (0x10+0x5)
+#define OUTPUT_S0D1     (0x10+0x6)
+#define OUTPUT_H0D1     (0x10+0x7)
+
 #define PI 3.1415926535897932384626433832795
 #define HALF_PI 1.5707963267948966192313216916398
 #define TWO_PI 6.283185307179586476925286766559
 #define DEG_TO_RAD 0.017453292519943295769236907684886
 #define RAD_TO_DEG 57.295779513082320876798154814105
 #define EULER 2.718281828459045235360287471352

drmpf avatar Mar 11 '19 03:03 drmpf