Jump to content
!Qwert

TM4C123G Arduino Library Problem

Recommended Posts

I have an issue when using the Capacitive Sensing Library from Arduino. I used the ver. 5 that allows non-AVR boards to use the library. My problem is when I complied it in Energia, I get these errors:

 

/Users/apple/Documents/Energia/libraries/CapacitiveSensor/CapacitiveSensor.h:94:2: error: 'IO_REG_TYPE' does not name a type
/Users/apple/Documents/Energia/libraries/CapacitiveSensor/CapacitiveSensor.h:95:11: error: 'IO_REG_TYPE' does not name a type
/Users/apple/Documents/Energia/libraries/CapacitiveSensor/CapacitiveSensor.h:96:2: error: 'IO_REG_TYPE' does not name a type
/Users/apple/Documents/Energia/libraries/CapacitiveSensor/CapacitiveSensor.h:97:11: error: 'IO_REG_TYPE' does not name a type
 
I am not that strong in coding and I would like some assistance into how to solve this problem. Thanks.
 
here is the h file where the error is coming from:
#ifndef CapacitiveSensor_h
#define CapacitiveSensor_h

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"

#endif

// Direct I/O through registers and bitmask (from OneWire library)

#if defined(__AVR__)
#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint8_t
#define DIRECT_READ(base, mask)         (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)   ((*((base)+1)) &= ~(mask), (*((base)+2)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask)  ((*((base)+1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask)    ((*((base)+2)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask)   ((*((base)+2)) |= (mask))

#elif defined(__MK20DX128__) || defined(__MK20DX256__)
#define PIN_TO_BASEREG(pin)             (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin)             (1)
#define IO_REG_TYPE uint8_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask)         (*((base)+512))
#define DIRECT_MODE_INPUT(base, mask)   (*((base)+640) = 0)
#define DIRECT_MODE_OUTPUT(base, mask)  (*((base)+640) = 1)
#define DIRECT_WRITE_LOW(base, mask)    (*((base)+256) = 1)
#define DIRECT_WRITE_HIGH(base, mask)   (*((base)+128) = 1)

#elif defined(__SAM3X8E__)
#define PIN_TO_BASEREG(pin)             (&(digitalPinToPort(pin)->PIO_PER))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask)         (((*((base)+15)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)   ((*((base)+5)) = (mask))
#define DIRECT_MODE_OUTPUT(base, mask)  ((*((base)+4)) = (mask))
#define DIRECT_WRITE_LOW(base, mask)    ((*((base)+13)) = (mask))
#define DIRECT_WRITE_HIGH(base, mask)   ((*((base)+12)) = (mask))

#elif defined(__PIC32MX__)
#define PIN_TO_BASEREG(pin)             (portModeRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask)         (((*(base+4)) & (mask)) ? 1 : 0)  //PORTX + 0x10
#define DIRECT_MODE_INPUT(base, mask)   ((*(base+2)) = (mask))            //TRISXSET + 0x08
#define DIRECT_MODE_OUTPUT(base, mask)  ((*(base+1)) = (mask))            //TRISXCLR + 0x04
#define DIRECT_WRITE_LOW(base, mask)    ((*(base+8+1)) = (mask))          //LATXCLR  + 0x24
#define DIRECT_WRITE_HIGH(base, mask)   ((*(base+8+2)) = (mask))          //LATXSET + 0x28

#endif

// some 3.3V chips with 5V tolerant pins need this workaround
//
#if defined(__MK20DX256__)
#define FIVE_VOLT_TOLERANCE_WORKAROUND
#endif

// library interface description
class CapacitiveSensor
{
  // user-accessible "public" interface
  public:
  // methods
	CapacitiveSensor(uint8_t sendPin, uint8_t receivePin);
	long capacitiveSensorRaw(uint8_t samples);
	long capacitiveSensor(uint8_t samples);
	void set_CS_Timeout_Millis(unsigned long timeout_millis);
	void reset_CS_AutoCal();
	void set_CS_AutocaL_Millis(unsigned long autoCal_millis);
  // library-accessible "private" interface
  private:
  // variables
	int error;
	unsigned long  leastTotal;
	unsigned int   loopTimingFactor;
	unsigned long  CS_Timeout_Millis;
	unsigned long  CS_AutocaL_Millis;
	unsigned long  lastCal;
	unsigned long  total;
	IO_REG_TYPE sBit;   // send pin's ports and bitmask
	volatile IO_REG_TYPE *sReg;
	IO_REG_TYPE rBit;    // receive pin's ports and bitmask
	volatile IO_REG_TYPE *rReg;
  // methods
	int SenseOneCycle(void);
};

#endif

Share this post


Link to post
Share on other sites

This thread gives some suggestions/help on porting libraries

http://forum.stellarisiti.com/topic/1983-howto-porting-libraries-some-help-needed/

 

The immediate cause of the error messages is that you need to have a segment which will provide definitions relevant to the Tiva launchpads.

(up in the list of macros based on cpu types).

 

#define IO_REG_TYPE uint8_t

(Which says that ports are 8 bits wide).

 

Of course you will need to figure out what the appropriate values are for all the other macros in that section.

 

Here is a start on it, (this is just from examples/memory, I haven't tested this - so may be syntax errors, and may have too many & on the BASEREG item.)

Direct read and mode input/output still need to be filled in.  (Looking at the code for driverlib should give you the HWREG versions for those functions).

Energia.h is another good source. 

#elif defined(__TM4C129XNCZAD__) || defined(__TM4C1294NCPDT__) || defined(__LM4F120H5QR__) || defined(__TM4C123GH6PM__)

#define portMaskedOutputRegister(base, mask) \
  ((volatile uint8_t *) (base + (GPIO_O_DATA + (((uint32_t)mask) << 2))))

#define PIN_TO_BASEREG(pin)             (&((uint32_t)portBASERegister(digitalPinToPort(pin))))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint8_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask)
#define DIRECT_MODE_INPUT(base, mask)
#define DIRECT_MODE_OUTPUT(base, mask)
#define DIRECT_WRITE_LOW(base, mask)  (portMaskedOutputRegister(base, mask) = 0)
#define DIRECT_WRITE_HIGH(base, mask) (portMaskedOutputRegister(base, mask) = 0xFF)

Might be helpful if you posted a link to the library in question (so those offering assistance could see what the library code looks like).  One can infer what several of these macros are supposed to do from the name, but some are a bit obscure.

Share this post


Link to post
Share on other sites

Okay, I will try out the link you posted and the example code once I get the chance. Here is the cpp file along with the header file:

/*
 CapacitiveSense.h v.04 - Capacitive Sensing Library for 'duino / Wiring
 https://github.com/PaulStoffregen/CapacitiveSensor
 http://www.pjrc.com/teensy/td_libs_CapacitiveSensor.html
 http://playground.arduino.cc/Main/CapacitiveSensor
 Copyright (c) 2009 Paul Bagder  All right reserved.
 Version 05 by Paul Stoffregen - Support non-AVR board: Teensy 3.x, Arduino Due
 Version 04 by Paul Stoffregen - Arduino 1.0 compatibility, issue 146 fix
 vim: set ts=4:
 */

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#include "pins_arduino.h"
#include "WConstants.h"
#endif

#include "CapacitiveSensor.h"

// Constructor /////////////////////////////////////////////////////////////////
// Function that handles the creation and setup of instances

CapacitiveSensor::CapacitiveSensor(uint8_t sendPin, uint8_t receivePin)
{
	// initialize this instance's variables
	// Serial.begin(9600);		// for debugging
	error = 1;
	loopTimingFactor = 310;		// determined empirically -  a hack

	CS_Timeout_Millis = (2000 * (float)loopTimingFactor * (float)F_CPU) / 16000000;
	CS_AutocaL_Millis = 20000;

	// Serial.print("timwOut =  ");
	// Serial.println(CS_Timeout_Millis);

	// get pin mapping and port for send Pin - from PinMode function in core

#ifdef NUM_DIGITAL_PINS
	if (sendPin >= NUM_DIGITAL_PINS) error = -1;
	if (receivePin >= NUM_DIGITAL_PINS) error = -1;
#endif

	pinMode(sendPin, OUTPUT);						// sendpin to OUTPUT
	pinMode(receivePin, INPUT);						// receivePin to INPUT
	digitalWrite(sendPin, LOW);

	sBit =  digitalPinToBitMask(sendPin);			// get send pin's ports and bitmask
	sReg = PIN_TO_BASEREG(sendPin);					// get pointer to output register

	rBit = digitalPinToBitMask(receivePin);			// get receive pin's ports and bitmask
	rReg = PIN_TO_BASEREG(receivePin);

	// get pin mapping and port for receive Pin - from digital pin functions in Wiring.c
	leastTotal = 0x0FFFFFFFL;   // input large value for autocalibrate begin
	lastCal = millis();         // set millis for start
}

// Public Methods //////////////////////////////////////////////////////////////
// Functions available in Wiring sketches, this library, and other libraries

long CapacitiveSensor::capacitiveSensor(uint8_t samples)
{
	total = 0;
	if (samples == 0) return 0;
	if (error < 0) return -1;            // bad pin


	for (uint8_t i = 0; i < samples; i++) {    // loop for samples parameter - simple lowpass filter
		if (SenseOneCycle() < 0)  return -2;   // variable over timeout
}

		// only calibrate if time is greater than CS_AutocaL_Millis and total is less than 10% of baseline
		// this is an attempt to keep from calibrating when the sensor is seeing a "touched" signal

		if ( (millis() - lastCal > CS_AutocaL_Millis) && abs(total  - leastTotal) < (int)(.10 * (float)leastTotal) ) {

			// Serial.println();               // debugging
			// Serial.println("auto-calibrate");
			// Serial.println();
			// delay(2000); */

			leastTotal = 0x0FFFFFFFL;          // reset for "autocalibrate"
			lastCal = millis();
		}
		/*else{                                // debugging
			Serial.print("  total =  ");
			Serial.print(total);

			Serial.print("   leastTotal  =  ");
			Serial.println(leastTotal);

			Serial.print("total - leastTotal =  ");
			x = total - leastTotal ;
			Serial.print(x);
			Serial.print("     .1 * leastTotal = ");
			x = (int)(.1 * (float)leastTotal);
			Serial.println(x);
		} */

	// routine to subtract baseline (non-sensed capacitance) from sensor return
	if (total < leastTotal) leastTotal = total;                 // set floor value to subtract from sensed value
	return(total - leastTotal);

}

long CapacitiveSensor::capacitiveSensorRaw(uint8_t samples)
{
	total = 0;
	if (samples == 0) return 0;
	if (error < 0) return -1;                  // bad pin - this appears not to work

	for (uint8_t i = 0; i < samples; i++) {    // loop for samples parameter - simple lowpass filter
		if (SenseOneCycle() < 0)  return -2;   // variable over timeout
	}

	return total;
}


void CapacitiveSensor::reset_CS_AutoCal(void){
	leastTotal = 0x0FFFFFFFL;
}

void CapacitiveSensor::set_CS_AutocaL_Millis(unsigned long autoCal_millis){
	CS_AutocaL_Millis = autoCal_millis;
}

void CapacitiveSensor::set_CS_Timeout_Millis(unsigned long timeout_millis){
	CS_Timeout_Millis = (timeout_millis * (float)loopTimingFactor * (float)F_CPU) / 16000000;  // floats to deal with large numbers
}

// Private Methods /////////////////////////////////////////////////////////////
// Functions only available to other functions in this library

int CapacitiveSensor::SenseOneCycle(void)
{
    noInterrupts();
	DIRECT_WRITE_LOW(sReg, sBit);	// sendPin Register low
	DIRECT_MODE_INPUT(rReg, rBit);	// receivePin to input (pullups are off)
	DIRECT_MODE_OUTPUT(rReg, rBit); // receivePin to OUTPUT
	DIRECT_WRITE_LOW(rReg, rBit);	// pin is now LOW AND OUTPUT
	delayMicroseconds(10);
	DIRECT_MODE_INPUT(rReg, rBit);	// receivePin to input (pullups are off)
	DIRECT_WRITE_HIGH(sReg, sBit);	// sendPin High
    interrupts();

	while ( !DIRECT_READ(rReg, rBit) && (total < CS_Timeout_Millis) ) {  // while receive pin is LOW AND total is positive value
		total++;
	}
	//Serial.print("SenseOneCycle(1): ");
	//Serial.println(total);

	if (total > CS_Timeout_Millis) {
		return -2;         //  total variable over timeout
	}

	// set receive pin HIGH briefly to charge up fully - because the while loop above will exit when pin is ~ 2.5V
    noInterrupts();
	DIRECT_WRITE_HIGH(rReg, rBit);
	DIRECT_MODE_OUTPUT(rReg, rBit);  // receivePin to OUTPUT - pin is now HIGH AND OUTPUT
	DIRECT_WRITE_HIGH(rReg, rBit);
	DIRECT_MODE_INPUT(rReg, rBit);	// receivePin to INPUT (pullup is off)
	DIRECT_WRITE_LOW(sReg, sBit);	// sendPin LOW
    interrupts();

#ifdef FIVE_VOLT_TOLERANCE_WORKAROUND
	DIRECT_MODE_OUTPUT(rReg, rBit);
	DIRECT_WRITE_LOW(rReg, rBit);
	delayMicroseconds(10);
	DIRECT_MODE_INPUT(rReg, rBit);	// receivePin to INPUT (pullup is off)
#else
	while ( DIRECT_READ(rReg, rBit) && (total < CS_Timeout_Millis) ) {  // while receive pin is HIGH  AND total is less than timeout
		total++;
	}
#endif
	//Serial.print("SenseOneCycle(2): ");
	//Serial.println(total);

	if (total >= CS_Timeout_Millis) {
		return -2;     // total variable over timeout
	} else {
		return 1;
	}
}

Thanks for your reply. I appreciate it.

Share this post


Link to post
Share on other sites

Okay, I took the example and insert it to the header file. Of course, I saw the errors when I compiled it to see what would happen. Now I do have a new issue, you mentioned that I had to fill the Direct read and mode input/output with certain mask and base values. You also mentioned that the driverlib should give me the HWREG versions for those functions or looking at the Eneriga.h is another source to look at. Sorry that I am asking much but I am a beginner in learning how to properly port libraries. Why I need to insert something to the Direct read and mode input/output (is it the pin mapping?) and what should I look at the HWREG to type it up?

Here is the link where I found the HWREG reference:

https://github.com/energia/Energia/blob/master/hardware/lm4f/cores/lm4f/main.cpp

Share this post


Link to post
Share on other sites

The macros in question are doing what pinMode( ) and digitalRead( ) do.

The library is using lower level calls probably either to increase speed, or to do things which the regular Wiring calls do not do.

 

So the file to look at is where those functions are defined.

https://github.com/energia/Energia/blob/master/hardware/lm4f/cores/lm4f/wiring_digital.c

int digitalRead(uint8_t pin)
{
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    uint32_t portBase = (uint32_t) portBASERegister(port);
    if (port == NOT_A_PORT) return LOW;
    if(ROM_GPIOPinRead(portBase, bit)){
     return HIGH;
    }
    return LOW;
}

This tells us how to get the base and the mask from a pin (first 3 lines).

Then we skip the error checking (we are after performance, not safety, good coding or defensive programming).

 

So to read a pin given the base and mask 

#define DIRECT_READ(base, mask)         ((ROM_GPIOPinRead(base, mask)) ? 1 : 0)

Which should work, but we can go even deeper to make it even faster (avoiding the procedure call).

 

To translate that into even lower level we search the source for GPIOPinRead(

https://github.com/energia/Energia/blob/master/hardware/lm4f/cores/lm4f/driverlib/gpio.c

 

(Technically I skipped a step there - if one didn't know that we can just drop the ROM_ part of the name (it is part of a mapping scheme to allow use of ROM or user compiled versions of the library), one could search for ROM_GPIOPinRead and find the header file where it gets translated/etc. and find that it is associated with GPIOPinRead.)

 

Again taking off the error checking we wind up with:

#define DIRECT_READ(base, mask)  (HWREG(base+ (GPIO_O_DATA + (mask<< 2))))

Since HWREG is just a macro which expands to reading a particular memory address we can't get much lower.

 

Following similar steps should handle pinMode.

 

Of course normally a library should use the regular digitalRead/Write/etc. calls if it can.  Hopefully the designers of this library had good reason for going to lower levels.  (i.e. When writing a library only use this approach if benchmarking has shown that the regular calls are a bottleneck in your library.)

Share this post


Link to post
Share on other sites

Ok, correct me if I get something wrong. So the HWREG is just allowing an extension reading of the total pins available according to the memory address.

For adding the rest on

#define DIRECT_MODE_INPUT(base, mask)    
#define DIRECT_MODE_OUTPUT(base, mask)

I should look further on the GPIO.c at:

for DIRECT_MODE_INPUT:

//*****************************************************************************
void
GPIOPinTypeGPIOInput(uint32_t ui32Port, uint8_t ui8Pins)
{
    //
    // Check the arguments.
    //
    ASSERT(_GPIOBaseValid(ui32Port));

    //
    // Make the pin(s) be inputs.
    //
    GPIODirModeSet(ui32Port, ui8Pins, GPIO_DIR_MODE_IN);

    //
    // Set the pad(s) for standard push-pull operation.
    //
    GPIOPadConfigSet(ui32Port, ui8Pins, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
}

//*****************************************************************************

and 

 

for DIRECT_MODE_OUTPUT:

//*****************************************************************************
//
//! Configures pin(s) for use as GPIO outputs.
//!
//! \param ui32Port is the base address of the GPIO port.
//! \param ui8Pins is the bit-packed representation of the pin(s).
//!
//! The GPIO pins must be properly configured in order to function correctly as
//! GPIO outputs.  This function provides the proper configuration for those
//! pin(s).
//!
//! The pin(s) are specified using a bit-packed byte, where each bit that is
//! set identifies the pin to be accessed, and where bit 0 of the byte
//! represents GPIO port pin 0, bit 1 represents GPIO port pin 1, and so on.
//!
//! \return None.
//
//*****************************************************************************
void
GPIOPinTypeGPIOOutput(uint32_t ui32Port, uint8_t ui8Pins)
{
    //
    // Check the arguments.
    //
    ASSERT(_GPIOBaseValid(ui32Port));

    //
    // Set the pad(s) for standard push-pull operation.
    //
    GPIOPadConfigSet(ui32Port, ui8Pins, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);

    //
    // Make the pin(s) be outputs.
    //
    GPIODirModeSet(ui32Port, ui8Pins, GPIO_DIR_MODE_OUT);
}

 I have to figure out what to write up the required base and mask values from the memory address for each one?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...