/** * @file simpletools.h * * @author Andy Lindsay * * @copyright * Copyright (C) Parallax, Inc. 2013-2017. All Rights MIT Licensed. * * @brief This library provides convenient functions * for a variety of microcontroller I/O, timing, conversion, and * communication tasks. This library also includes (and you can * call functions from) * simpletext * and * serial. * * @details This library provides a set of introductory functions that simplify: * * @li I/O control - convenient I/O pin monitoring and control functions * @li Timing - Delays, timeouts * @li Timed I/O - pulse generation/measurement, square waves, transition * counting, RC decay, etc. * @li Analog - D/A conversion, PWM, and more. * @n For A/D conversion see ...Learn/Simple Libraries/Convert * for A/D conversion libraries * @li Serial Communication - SPI, I2C * @n For half and full duplex asynchronous serial communication, see * ...Learn/Simple Libraries/Text Devices * @li Memory - EEPROM, SD storage * * Applications include: monitoring, control and * communication with simple peripherals, like lights, buttons, * dials, motors, peripheral integrated circuits and prototyping with * simple systems that use pulse, or serial communication. (A few * examples from the very large list of devices includes: servos, * ultrasonic distance sensors, accelerometers, serial liquid crystal, * display, etc.) * * Intended use: Accompanies introductory electronics, robotics and * programming lessons and projects on learn.parallax.com. After * these lessons, bridge lessons will be added to familiarize the * programmer with standard practices used by the community for * adding libraries to support and endless variety of peripherals * and applications. * * @par Core Usage * Any of these functions, if called, will launch a process into another cog * and leave it launched for set it/forget it processes: * * @li cog_run (1 cog per call) * @li squareWave (1 cog) * @li pwm (1 cog) * @li dac (1 cog) * * @par Memory Models * Use with CMM or LMM. * * @version * 1.1.7 Update pause function for up to 2,147,483,647 ms. * @par * 0.98.2 Add term_cmd function for SimpleIDE Terminal cursor, screen, and audio * control. * @par * 0.98 fpucog floating point coprocessor no longer self-starts by default. * All floating point functionality is still supported, processing just happens in * the same cog. i2c_out and i2c_in char regAddr parameter changed to int memAddr. * itoa removed, use sprint(charArray, "%d", intVal) to make int to ASCII * conversions. st_msTicks and st_usTicks global variables are pre-initialized to the * number of system clock ticks in a millisecond and microsecond for convenience in * library development. Variables named us and ms are initialized to the same values * for user applications. Function endianSwap added to simplify communication with * devices that send/receive byte data in big endian format. * @par * 0.97 Add cog_run and cog_end for simplified running of functioncode in other cogs. * @par * 0.96.1 Add documentation for start_fpu_cog and stop_fpu_cog. * @par * 0.96 ee_putStr updated to support 128 byte page writes. More corrections to ee_put * for contiguous data crossing address/128 boundary. * @par * 0.95 square_wave bug that prevented output frequency changes * (fixed). * @par * 0.94 Fixed bug in ee_put* that prevented contiguous data from crossing the EEPROM's * address/128 buffer boundaries. Updated stack array to static in mstimer.c. * @par * 0.93 i2c_newbus now uses @n * .../Learn/Simple Libraries/Protocol/simplei2c/@n * Added:@n * i2c_out, i2c_in to cover most common I2C applications * EEPROM ee_get_* and ee_put_* changed to ee_get* and ee_put* where * the * term is camel-case. * @par * 0.92 Simpletext functionality incorporated for use of * character and string I/O with both terminal and peripheral devices. * Simple Text folder replaces PropGCC serial driver support for simple * and full duplex serial peripherals. * @par * 0.91 shift_in function pre-clock mode bug fixed. @n @n * * @par Help Improve this Library * Please submit bug reports, suggestions, and improvements to this code to * editor@parallax.com. */ #ifndef SIMPLETOOLS_H #define SIMPLETOOLS_H #if defined(__cplusplus) extern "C" { #endif #include #include "simpletext.h" #include #include #include #include #include #include #include #include #include #include #include #include "simplei2c.h" /** * @brief Propeller system clock ticks in 1 millisecond (ms). */ extern int ms; /** * @brief Propeller system clock ticks in 1 millisecond (us). */ extern int us; /** * @name Private (used by simpletools library) * @{ */ /** * @brief Propeller system clock ticks in 1 millisecond. Changing this value is * not recommended because it can affect library performance. */ extern int st_msTicks; /** * @brief Propeller system clock ticks in 1 microsecond. Changing this value is * not recommended because it can affect library performance. */ extern int st_usTicks; /** * @brief Clock ticks in a time increment used by pulse_in, pulse_out, and rc_time. * Default value is the number of system clock ticks in a microsecond = CLKFREQ/1000000. */ extern int st_iodt; /** * @brief Clock ticks in a time increment used by pulse_in, pulse_out, and rc_time. * Default value is the number of system clock ticks in 1/4 s = CLKFREQ/4. */ extern int st_timeout; /** * @brief Clock ticks in a time increment used by pause function. Default value is the * number of system clock ticks in 1/1000 s = CLKFREQ/1000. */ extern int st_pauseTicks; /** * @brief Variable shared by mark and time_out functions. */ extern int st_mark; /** * @brief Variable used by i2c_newbus. */ extern unsigned int st_buscnt; /** * @brief The busID for the Propeller Activity Board's EEPROM bus. */ extern i2c *st_eeprom; /** * @brief Initialization flag used by ee_ functions. */ extern int st_eeInitFlag; /** * @} */ #ifndef PI /** * @brief 3.141592653589793 */ #define PI 3.141592653589793 #endif /** * @name SimpleIDE Terminal Constants * @{ */ /* Values for use with SimpleIDE Terminal */ #ifndef HOME /** * @brief HOME character (1) sends SimpleIDE Terminal's cursor to top-left "home" position. */ #define HOME (1) #endif #ifndef CRSRXY /** * @brief CRSRXY character (2) sends cursor to a certain number of spaces over (X) * and returns (Y) down from SimpleIDE Terminal's top-left HOME position. This * character has to be followed immediately by the X and Y values when transmitted * to the SimpleIDE Terminal. */ #define CRSRXY (2) #endif #ifndef CRSRLF /** * @brief CRSRLF character (3) sends the SimpleIDE Terminal's cursor one column * (space) to the left of its current position. */ #define CRSRLF (3) #endif #ifndef CRSRRT /** * @brief CRSRRT character (4) sends the SimpleIDE Terminal's cursor one column * (space) to the right of its current position. */ #define CRSRRT (4) #endif #ifndef CRSRUP /** * @brief CRSRUP character (5) sends the SimpleIDE Terminal's cursor one row * (carriage return) upward from its current position. */ #define CRSRUP (5) #endif #ifndef CRSRDN /** * @brief CRSRDN character (6) sends the SimpleIDE Terminal's cursor one row * (carriage return) downward from its current position. */ #define CRSRDN (6) #endif #ifndef BEEP /** * @brief BEEP character (7) makes the system speaker in some computers beep * when received by SimpleIDE Terminal. */ #define BEEP (7) #endif #ifndef BKSP /** * @brief BKSP character (8) sends the SimpleIDE Terminal's cursor one column * (space) to the left of its current position and erases whatever character * was there. */ #define BKSP (8) #endif #ifndef TAB /** * @brief TAB character (9) advances the cursor to the right by a tab's worth * of spaces. */ #define TAB (9) #endif #ifndef NL /** * @brief NL character (10) sends the SimpleIDE Terminal's cursor to the leftmost * character in the next line down. */ #define NL (10) #endif #ifndef LF /** * @brief LF is same as NL. */ #define LF (10) #endif #ifndef CLREOL /** * @brief CLREOL character (11) erases all SimpleIDE Terminal characters to the * right of the cursor. */ #define CLREOL (11) #endif #ifndef CLRDN /** * @brief CLRDN character (12) erases all SimpleIDE Terminal characters below the * cursor. */ #define CLRDN (12) #endif #ifndef CR /** * @brief CR character (13) sends SimpleIDE Terminal's cursor one row * downward. */ #define CR (13) #endif #ifndef CRSRX /** * @brief CRSRX character (14) positions SimpleIDE Terminal's cursor X characters * from the its left edge. */ #define CRSRX (14) #endif #ifndef CRSRY /** * @brief CRSRY character (15) sends SimpleIDE Terminal's cursor Y rows to the * from its top edge. */ #define CRSRY (15) #endif #ifndef CLS /** * @brief CLS character (16) clears SimpleIDE's screen, erasing all characters and * placing the cursor in the top-left corner. */ #define CLS (16) #endif /** * @} * * @name SPI Constants for shift_in & shift_out * @{ */ #ifndef MSBPRE /** * @brief For use with shift_in. Stands for most significant bit first, pre-clock. */ #define MSBPRE 0 #endif #ifndef LSBPRE /** * @brief For use with shift_in. Stands for least significant bit first, pre-clock. */ #define LSBPRE 1 #endif #ifndef MSBPOST /** * @brief For use with shift_in. Stands for most significant bit first, post-clock. */ #define MSBPOST 2 #endif #ifndef LSBPOST /** * @brief For use with shift_in. Stands for least significant bit first, post-clock. */ #define LSBPOST 3 #endif // Values for use with shift_out #ifndef LSBFIRST /** * @brief For use with shift_out. Stands for least significant bit first. */ #define LSBFIRST 0 #endif #ifndef MSBFIRST /** * @brief For use with shift_out. Stands for most significant bit first. */ #define MSBFIRST 1 #endif /** * @} * * @name Counter Module Constants * @{ */ #ifndef NCO_PWM_1 /** * @brief Building block for configuring a cog's counter module to PWM mode. * Used by pwm functions. PWM stands for pulse width modulation. */ #define NCO_PWM_1 (0b00100 << 26) #endif #ifndef CTR_NCO /** * @brief Building block for configuring a cog's counter module to NCO mode. * Used by square_wave function. NCO stands for numerically controlled oscillator. */ #define CTR_NCO (0b100 << 26) #endif #ifndef CTR_PLL /** * @brief Building block for configuring a cog's counter module to PLL mode. * Used by square_wave function. PLL stands for phase locked loop. */ #define CTR_PLL (0b10 << 26) #endif #ifndef DUTY_SE /** * @brief Building block for configuring a cog's counter module to DUTY_SE mode. * Used by dac functions. DUTY_SE stands for duty single ended. */ #define DUTY_SE (0b110 << 26) #endif /** * @} * * @name Reverse Compatibility Functions * @{ */ /** * @brief ee_put_byte renamed ee_putByte. */ #define ee_put_byte ee_putByte /** * @brief ee_get_byte renamed ee_getByte. */ #define ee_get_byte ee_getByte /** * @brief ee_put_int renamed ee_putInt. */ #define ee_put_int ee_putInt /** * @brief ee_get_int renamed ee_getInt. */ #define ee_get_int ee_getInt /** * @brief ee_put_str renamed ee_putStr. */ #define ee_put_str ee_putStr /** * @brief ee_get_str renamed ee_getStr. */ #define ee_get_str ee_getStr /** * @brief ee_put_float32 renamed ee_putFloat32. */ #define ee_put_float32 ee_putFloat32 /** * @brief (Deprecated) Use waitcnt(CLKFREQ + CNT) for a delay that lasts 1 second, * and use fractions of CLKFREQ for smaller numbers of system clock ticks. */ #define pause_ticks(pticks) __builtin_propeller_waitcnt(pticks+CNT, 0) /** * @} * * @name Propeller EEPROM Address * @{ */ #ifndef EEPROM_ADDR /** * @brief Propeller EEPROM I2C bus address */ #define EEPROM_ADDR 0x50 #endif /** * @} */ /** * @brief Set an I/O pin to output-high * * @details This function set makes the Propeller * P8X32A connect the I/O pin to its positive 3.3 V * supply voltage enabling it to source up to * 40 mA of current (max 1 W dissipation per chip). * * @param pin Number of the I/O pin to set high. */ void high(int pin); /** * @brief Set an I/O pin to output-low * * @details This function makes the Propeller * P8X32A connect the I/O pin to its ground 0 V * supply voltage enabling it to sink up to * 40 mA of current (max 1 W dissipation per chip). * * @param pin Number of the I/O pin to set low. */ void low(int pin); /** * @brief Set an I/O pin to input and return 1 if pin * detects a high signal, or 0 if it detects low. * * @details This function makes the Propeller * connect the I/O pin to its input buffer * so that it can return the binary value of the * voltage applied by an external circuit. * * @param pin Number of the I/O pin to set to input. * * @returns 1 to indicate high (above 1.65 V) received * or 0 to indicate low (below 1.65 V) received. */ int input(int pin); /** * * @name More Individual I/O * @{ */ /** * @brief Toggle the output state of the I/O pin. * * @details Change I/O pin's output state from low to high * or high to low. This function assumes that some other * function has already set the I/O pin to output. * * @param pin I/O pin number. * * @returns The new pin state. */ unsigned int toggle(int pin); /** * @brief Reverse the direction of an I/O pin. * * @details If an I/O pin's direction is set to input, this * function changes it to output. If it's set to output, * this function changes it to input. * * @param pin I/O pin number. * * @returns The new pin direction. */ unsigned int reverse(int pin); /** * @brief Check the state of an I/O pin without * setting it to input. * * @details Use this function instead of input if the * Propeller needs to maintain an output. For example, * you can use this to monitor another cog's or counter's * output signal activity on a pin. (Note: if the pin * is already set to input, it will return the state the * external circuit is applying, just like input.) * * @param pin Number of the I/O pin * * @returns The pin's state. If the pin is an output, * 1 = 3.3 V and 0 = 0 V. If the pin is an input, * 1 means V > 1.65 V, 0 means it's less. */ unsigned int get_state(int pin); /** * @brief Check the direction of the I/O pin. * * @details This function will tell you the direction of the * I/O pin as seen by the cog executing it. Keep in mind that * that your program might make other cogs use the I/O pin as * an output, and a cog that treats a pin as an output wins over * one that treats it as an input. * * @param pin I/O pin number * * @returns I/O pin direction as seen by the cog that runs the * function. */ unsigned int get_direction(int pin); /** * @brief Get I/O pin output state. * * @details Keep in mind that this function reports the value in the output * register for the cog running the function. That doesn't tell you if the * I/O pin is set to input, or whether another cog is sending a different * output state. * * @param pin I/O pin number. * * @returns In a register bit for I/O pin, either 1 or 0. */ unsigned int get_output(int pin); /** * @brief Set an I/O pin to a given direction. * * @details This function sets an I/O pin to either output or input. * * @param pin I/O pin number. * @param direction I/O pin direction. */ void set_direction(int pin, int direction); /** * @brief Set I/O pin output register bit to either 1 or 0. * * @details This function focuses on the I/O pin's output register. If you * intend to use it to send high or low signals, consider using high or low * functions. This function can also be used in conjunction with set_direction * to send high or low signals. * * @param pin I/O pin to set high or low. * @param state 1 for high, 0 for low (when pin is actually set to output, * which can be done with setDirection. */ void set_output(int pin, int state); /** * @} * * @name Group I/O * @{ */ /** * @brief Get states of a contiguous group of I/O pins * * @details This works the same as getState, but for a group of pins. It * tells you the actual state of each pin, regardless of whether it's a * voltage applied to input or transmitted by an output. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * * @returns States value containing the binary bit pattern. The value for * startPin should be in bit-0, next in bit-1, etc. */ unsigned int get_states(int endPin, int startPin); /** * @brief Get directions for a contiguous group of I/O pins. * * @details Get direction register states from a contiguous group of bits * in the cog's output register. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * * @returns States value containing a binary bit pattern. The value for * startPin should be in bit-0, next in bit-1, etc. */ unsigned int get_directions(int endPin, int startPin); /** * @brief Get output settings for a contiguous group of I/O pins. * * @details Get output register settings for a contiguous group of bits * in the cog's output register. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * * @returns Pattern value containing a binary bit pattern. The value * for startPin should be in bit-0, next in bit-1, etc. */ unsigned int get_outputs(int endPin, int startPin); /** * @brief Set directions for a contiguous group of I/O pins. * * @details Set directions values in a contiguous group of bits in the * cog's output register. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * @param pattern Value containing the binary bit pattern. The value for * startPin should be in bit-0, next in bit-1, etc. */ void set_directions(int endPin, int startPin, unsigned int pattern); /** * @brief Set output states for a contiguous group of I/O pins. * * @details Set output states of a contiguous group of bits in the cog's * output register. * * @param endPin The highest numbered pin. * @param startPin The lowest numbered pin. * @param pattern Value containing the binary bit pattern. The value for * startPin should be in bit-0, next in bit-1, etc. */ void set_outputs(int endPin, int startPin, unsigned int pattern); /** * @} * * @name Timing * @{ */ /** * @brief Delay cog from moving on to the next statement for a certain length * of time. * * @details The default time increment is 1 ms, so pause(100) would delay for * 100 ms = 1/10th of a second. This time increment can be changed with a call * to the set_pause_dt function. * * @param time The number of time increments to delay. */ void pause(int time); /** * @brief Set time increment for pause function * * @details Default time increment for pause function is 1 ms. This function * allows you to change that delay to custom values. For example, * set_pause_dt(CLKFREQ/2000) would set it to 1/2 ms increments. To return to * default 1 ms increments, use set_pause_dt(CLKFREQ/1000). * * @param clockticks the number of clock ticks that pause(1) will delay. */ void set_pause_dt(int clockticks); /** * @} * * @name Timed I/O * @{ */ /** * @brief Count number of low to high transitions an external input applies to * an I/O pin over a certain period of time. * * @param pin I/O pin number * @param duration Amount of time the measurement counts transitions * * @returns The number of low to high transitions */ long count(int pin, long duration); /** * @brief Set D/A voltage * * @details Launches process into another cog for up to two channels of D/A conversion * on any I/O pin. Other libraries may be available that provide D/A for more channels. * Check SimpleIDE/Learn/Simple Libraries/Convert for options. For more options, check * obex.parallax.com. * * This library uses another cog's counter modules (2 per cog) to perform duty modulation, * which is useful for D/A conversion. The digital signal it generates will affect LED * brightness. The signal can be passed through a low pass RC filter for digital to * analog voltage conversion. Add an op amp buffer if it needs to drive a load. * * Default resolution is 8 bits for output voltages ranging from 0 V to (255/256) of * 3.3 V. * * General equation is dacVal * (3.3 V/2^bits) * * Default is 8 bits, which results in dacVal * (3.3 V/ 256), so dacVal * specifies the number of 256ths of 3.3 V. You can change the resolution with * the dac_ctr_res function. * * @param pin I/O pin number. * @param channel Use 0 or 1 to select the cog's CTRA or CTRB counter modules, which * are used for D/A conversion. * @param dacVal Number of 256ths of 3.3 V by default. Use a value from 0 (0 V) * to 255 . */ void dac_ctr(int pin, int channel, int dacVal); /** * @brief Set D/A voltage resolution * * @details Default resolution is 8-bits for output voltages ranging from 0 V to (255/256) of * 3.3 V. * * General equation is dacVal * (3.3 V/2^bits) * * Default is 8 bits, which results in dacVal * (3.3 V/ 256), so dacVal * specifies the number of 256ths of 3.3 V. * * @param bits The D/A converter's resolution in bits. */ void dac_ctr_res(int bits); /** * @brief Stop the cog that's transmitting the DAC signal(s). * * @details Stops any signals, lets go of any I/O pins, and reclaims the cog for * other uses. * */ void dac_ctr_stop(void); /** * @brief Use same cog to send square wave of a certain * frequency for a certain amount of time. For set and forget * with another cog, try square_wave function instead. * * @param pin I/O pin that sends the frequency * @param msTime Time in ms that the signal lasts * @param frequency Frequency of the signal in Hz. Accepts * values from 1 Hz to 128000000 Hz (128 MHz). */ void freqout(int pin, int msTime, int frequency); /** * @brief Start pulse width modulation (PWM) process in another cog. * * @details Great for DC motors, can also be used for servos, but the * servo library is probably a better choice for that. * * A PWM signal sends repeated high signals with a fixed cycle time. * Your code will typically control the amount of time a PWM signal is * high during each cycle. For example, pwm_start(1000) will establish * a 1000 us PWM cycle. You can then use the pwm_set function to send * high signals that last anywhere from 0 to 1000 us. * * @param cycleMicroseconds Number of microseconds the PWM cycle lasts. */ int pwm_start(unsigned int cycleMicroseconds); /** * @brief Set a PWM signal's high time. * * @details After a single call to pwm_start, this function allows you * to set a PWM signal's high time. For example, if your pwm_start call * sets up 1000 us (1 ms) you could use this function to make the signal * high for 3/4 of its cycle with pwm_set(pin, channel, 750). If the * signal goes to a DC motor through an H bridge or other driver circuit, * the motor will behave as though it's only getting 3/4 of the supply * and turn at roughly 3/4 of full speed. * * @param pin I/O pin to send the PWM signal. You can change this * value on the fly, which is useful for speed control of a DC motor in * two different directions. When the PWM signal changes to a new pin, * the cog sets the previous pin to input. If you want it to stay low * when the PWM cog lets go, just set the pin low in your code before * calling pwm_start. * * @param channel You have options of 0 or 1 for up to two simultaneous * PWM signals. If you have an application in mind that requires more * PWM signals, check the SimpleIDE/Learn/Simple Libraries/Motor * directory, and also online at obex.parallax.com. * * @param tHigh The high time for each PWM cycle repetition. */ void pwm_set(int pin, int channel, int tHigh); /** * @brief Shut down PWM process and reclaim cog and I/O pins for other * uses. * * @details Shut down PWM process and reclaim cog and I/O pins for other uses * */ void pwm_stop(void); /** * @brief Measure the duration of a pulse applied to an I/O pin * * @details Default time increments are specified in 1 microsecond units. Unit size * can be changed with a call to set_io_dt function. * * @param pin I/O pin number * @param state State of the pulse (1 for positive or high pulses, 0 for negative or * low pulses. * * @returns Number of time units the pulse lasted. */ long pulse_in(int pin, int state); /** * @brief Transmit a pulse with an I/O pin * * @details 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. The pulse will be negative * if it transmits a high signal before the call. When the pulse is done, the pin * returns to whatever state it was in before the pulse. If the pin was an input, it * will be changed to output and use whatever value was in the output register bit * for the pin. This defaults to low on start-up, but you can pre-set it while leaving * the pin set to input with the set_output function (or check it with get_output). * * @param pin I/O pin number. * @param time Amount of time the pulse lasts. */ void pulse_out(int pin, int time); /** * @brief Set I/O pin to input and measure the time it takes a signal to transition from * a start state to the opposite state. * * @details 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 pin I/O pin number. * @param state Starting pin state. * * @returns Time from starting pin. */ long rc_time(int pin, int state); /** * @brief Make I/O pin transmit a repeated high/low signal at a certain frequency. * High and low times are the same. Frequency can range from 1 Hz to 128 MHz. * * @details Uses one additional cog with up to two active channels, each with a selectable * frequency. You can change transmit pins on the fly by calling this function on the * same channel, but with a different pin. The previous pin will be set to input in that * cog. If your code is set to output, it will not affect that setting, only the setting * for the cog that is transmitting the square wave. Code in your cog, or some other cog * can modulate the signal. A low signal allows the square wave to transmit, and a high * signal prevents it. * * @param pin I/O pin that transmits square wave frequency. To stop sending the signal. * and change the pin back to input, pass the pin as a negative number. * @param channel 0 or 1 selects the counter module to transmit the frequency. * @param freq Square wave frequency. * */ void square_wave(int pin, int channel, int freq); /** * @brief Stop the cog that's transmitting a square wave. * * @details Stops any signals, lets go of any I/O pins, and reclaims the cog for * other uses. * */ void square_wave_stop(void); /** * @brief Sets the timeout value for the following timed I/O functions: pulse_in, rc_time * * @details Time increment is set in clock ticks. For example, the default of 0.25 * seconds is set with set_io_timeout(CLKFREQ/4). To set the timeout to 20 ms, you could * use set_io_timeout(CLKFREQ/50). * * @param clockTicks Number of clock ticks for timed I/O */ void set_io_timeout(long clockTicks); /** * @brief Sets the time increment for the following timed I/O functions: count, pulse_in, * pulse_out, rc_time. * * @details Time increment is set in clock ticks. For example, the default of 1 us * units is specified with set_io_dt(CLKFREQ/1000000). For 2 microsecond units, use * set_io_dt(CLKFREQ/500000). * * @param clockticks Number of clock ticks that represents one I/O time increment. */ void set_io_dt(long clockticks); /** * @} * * @name SPI * @{ */ /** * @brief Receive data from a synchronous serial device * * @param pinDat Data pin. * @param pinClk Clock pin. * @param mode Order and orientation to clock pulse options: * MSBPRE, LSBPRE, MSBPOST,LSBPOST. * @param bits Number of binary values to transfer. * * @returns Value received from the synchronous serial device. */ int shift_in(int pinDat, int pinClk, int mode, int bits); /** * @brief Send data to a synchronous serial device * * @param pinDat Data pin * @param pinClk Clock pin * @param mode Order that bits are transmitted, either LSBFIRST or MSBFIRST. * @param bits Number of binary values to transfer. * @param value to transmit. */ void shift_out(int pinDat, int pinClk, int mode, int bits, int value); /** * @} * * @name I2C * @{ */ /** * @brief Set up a simple serial driver with transmit & receive pins. * * @param sclPin the I2C bus' serial clock pin. * * @param sdaPin the I2C bus' serial data pin. * * @param sclDrive sets I/O pin connected to SCL line to send high signals by * either (sclDrive = 0) allowing the pull-up resistor on the bus to pull the * line high, or (sclDrive = 1) by setting the I/O pin to output and driving the * line high. sclDrive = 0 is by far the most common arrangement. sclDrive = 1 * is used with some Propeller boards that do not have a pull-up resistor on the * EEPROM's SCL line. * * @returns busID - a pointer to the I2C bus info in memory. The busID value gets * passed to i2c_out, i2c_in, and i2c_busy's busID parameter to select which I2C * bus to use. */ i2c *i2c_newbus(int sclPin, int sdaPin, int sclDrive); /** * @brief Send data to device using I2C protocol. * * @details This function uses Simple Libraries/Protocol/libsimplei2c for * clock and data line signaling. You can also use this library to create * custom I2C functions. Other I2C signaling options are included in * Propeller GCC. Search for i2C in the propgcc folder for more info. * * @param *busID I2C bus identifier. i2c_newbus returns this pointer. * * @param i2cAddr 7 bit I2C device address. * * @param memAddr Value for setting memory address pointer inside the I2C * device. * * @param memAddrCount Number of bytes to use for memAddr. This value can * be zero for no register or memory address data, in which case memAddr * can be set to NULL. * * @param *data Pointer to bytes to send to the I2C device. * * @param dataCount Number of bytes in data to send. Use a positive value to transmit * least significant byte first, or a negative value to transmit most significant * byte first. * * @returns total number of bytes written. Should be 1 + memAddrCount + dataCount. */ HUBTEXT int i2c_out(i2c *busID, int i2cAddr, int memAddr, int memAddrCount, const unsigned char *data, int dataCount); /** * @brief Receive data from device using I2C protocol. * * @details This function uses Simple Libraries/Protocol/libsimplei2c for * clock and data line signaling. You can also use this library to create * custom I2C functions. Other I2C signaling options are included in * Propeller GCC. Search for i2C in the propgcc folder for more info. * * @param *busID I2C bus identifier. i2c_newbus returns this pointer. * * @param i2cAddr 7 bit I2C device address. * * @param memAddr Value for setting memory address pointer inside the I2C * device. * * @param memAddrCount Number of bytes to use for memAddr. This value can * be zero for no register or memory address data, in which case memAddr * can be set to NULL. * * @param *data Pointer to bytes set aside for receiving data from the I2C device. * * @param dataCount Number of bytes in data to send. Use a positive value to load data * into result variable(s) least significant byte first, or a negative value for most * significant byte first. * * @returns total number of bytes written. Should be 1 + memAddrCount + dataCount. */ HUBTEXT int i2c_in(i2c *busID, int i2cAddr, int memAddr, int memAddrCount, unsigned char *data, int dataCount); /** * @brief Check if I2C device is busy or responding. * * @param *busID I2C bus identifier. i2c_newbus returns this pointer. * * @param i2cAddr 7 bit I2C device address. * * @returns 1 if busy, 0 if ready. */ HUBTEXT int i2c_busy(i2c *busID, int i2cAddr); /** * @} * * @name Propeller EEPROM * @{ */ /** * @brief Store a byte value at a certain address in the Propeller Chip's * dedicated EEPROM. * * @param value The byte value to store in EEPROM. * * @param addr The EEPROM address where the value is to be stored. * */ void ee_putByte(unsigned char value, int addr); /** * @brief Get a byte value from a certain address in the Propeller Chip's * dedicated EEPROM. * * @param addr The EEPROM address that with the byte value that should be fetched. * * @returns value The byte value stored by the EEPROM at the address specified * by the addr parameter. */ char ee_getByte(int addr); /** * @brief Store an int value at a certain address in the Propeller Chip's * dedicated EEPROM. An int value occupies four bytes, so the next value * should be stored at an address value that's four bytes higher. * * @param value The int value to store in EEPROM. * * @param addr The EEPROM address where the value is to be stored. */ void ee_putInt(int value, int addr); /** * @brief Get an int value from a certain address in the Propeller Chip's * dedicated EEPROM. If you are fetching several int values, make sure to * add 4 to the addr value with each successive call. * * @param addr The EEPROM address with the int value that should be fetched. * * @returns value The int value stored by the EEPROM at the specified address. */ int ee_getInt(int addr); /** * @brief Store a string of byte values starting at a certain address in * the Propeller Chip's dedicated EEPROM. * * @param s Address of a char array containing the string of bytes. * * @param n The number of bytes to copy from the array. * * @param addr The EEPROM address of the first byte in the string. */ void ee_putStr(unsigned char *s, int n, int addr); /** * @brief Fetch a string of byte values starting at a certain address in * Propeller Chip's dedicated EEPROM. * * @param s Address of a char array to receive the string of bytes fetched * from EEPROM. * * @param n The number of bytes to copy from EEPROM to the array. * * @param addr The EEPROM address of the first byte in the string. * * @returns The address of the array that stores the characters that * were fetched. */ unsigned char* ee_getStr(unsigned char* s, int n, int addr); /** * @brief Store a 32-bit precision floating point value at a certain address * in the Propeller Chip's dedicated EEPROM. A 32-bit value occupies four bytes * so if you are storing values in a sequence, make sure to add 4 to each addr * parameter value. * * Make sure that the Math box is checked in the Project Manager. In Simple View, * click the Show Project Manager button in SimpleIDE's bottom-left corner. Then * click the Linker tab, and check the Math Lib box. * * @param value The 32-bit floating point float value to store in EEPROM. * * @param addr The EEPROM address where the value is to be stored. */ void ee_putFloat32(float value, int addr); /** * @brief Fetch a 32-bit precision floating point value from a certain address * in the Propeller Chip's dedicated EEPROM. A 32-bit value occupies four bytes * so if you are fetching values in a sequence, make sure to add 4 to each addr * parameter value. * * Make sure that the Math box is checked in the Project Manager. In Simple View, * click the Show Project Manager button in SimpleIDE's bottom-left corner. Then * click the Linker tab, and check the Math Lib box. * * @param addr The EEPROM address with the 32-bit floating point float value * that should be fetched. * * @returns value The float value stored by the EEPROM at the specified address. */ float ee_getFloat32(int addr); /** * @brief Optional function for setting a custom EEPROM configuration. Other * ee_ functions automatically check if the EEPROM has been initialized, and * if not, they use default settings equivalent to ee_config(28, 29, 0). This * function can be called before any other ee_ functions to replace those * defaults with custom settings. * * @warning: If you're going to call this function, make sure to do it before * calling any other ee_ functions. If one ee_ function gets called before this, * it'll set up defaults, and this function cannot override them after they have * been set. * * @param sclPin Propeller I/O pin connected to the EEPROM's SCL (serial * clock) pin. * * @param sdaPin Propeller I/O pin connected to the EEPROM's SDA (serial * data) pin. * * @param sclDrive Use 0 for standard design where the SCL pin has a pull-up * resistor, or 1 if it does not have a pull-up and needs to be driven. */ void ee_config(int sclPin, int sdaPin, int sclDrive); /** * @} * * @name SD Card * @{ */ /** * @brief Mount an SD card with the minimal 4-pin interface. For Parallax Learn Site * examples, see: SD Card Data and Play WAV Files. * * @param doPin The SD card's data out pin. * * @param clkPin The SD card's clock pin. * * @param diPin The SD card's data in pin. * * @param csPin The SD card's chip select pin. * * @returns status 0 if successful, or an error code. */ int sd_mount(int doPin, int clkPin, int diPin, int csPin); /** * @} * * @name Multicore * @{ */ /** * @brief Run a function's code in the next available cog (processor). * * @details cog_run is designed to make launching application level * functions (typically from the main file) quick and easy. All you have * to do is pass a pointer to a function with no return value or parameters * along with the number for extra memory to reserve. The value returned * can be used to shut down the process and free up memory and a cog later * by passing it to cog_end. * * @param *function pointer to a function with no parameters * or return value. Example, if your function is void myFunction(), then * pass &myFunction. * * @param stacksize Number of extra int variables for local variable declarations * and call/return stack. This also needs to cover any local variable declarations * in functions that your function calls, including library functions. Be liberal * with extra stack space for prototyping, and if in doubt, 40 to whatever value * you calculate. * * @returns *coginfo Address of memory set aside for the cog. Make sure to save this value * in a variable if you intend to stop the process later with cog_end or check which cog * the process was launched into with cog_num. */ int *cog_run(void (*function)(void *par), int stacksize); /** * @brief Get the cog ID. * * @param *coginfo the address returned by cog_run. * * @returns The cog ID number. */ int cog_num(int *coginfo); /** * @brief End function code running in another cog that was launched with cog_run. * * @details This function uses the value returned by cog_run to stop a function * running in another cog and free the stack space cog_run allocated with its * stacksize parameter. * * @param *coginfo the address returned by cog_run. */ void cog_end(int *coginfo); /** * @} * * @name Terminal Control * @{ */ /** @brief Send a command to SimpleIDE Terminal. Examples of commands include HOME, CLS, BKSP, CRSRXY, and others. All sixteen are listed in the SimpleIDE Terminal Constants section above. Click the term_cmd link to go to the details section and see parameter descriptions and code examples. @code // Examples term_cmd(HOME); // Cursor -> home (0, 0) position term_cmd(CLS); // Clear screen and send cursor HOME term_cmd(BKSP); // Backspace one character // Position cursor 4 spaces from left and 2 rows down from top. term_cmd(CRSRXY, 4, 2); // Position cursor 4 spaces from left, but do not change row. term_cmd(CRSRX, 4); // Position cursor 2 rows from top, but do not change spaces // from left. term_cmd(CRSRY, 2); @endcode @param termConst One of the sixteen terminal control constants listed in the SimpleIDE Terminal Constants part of the Macros section above. @param ... No additional parameters are required for CLS, HOME, and most of the others. Only CRSRXY requires two additional parameters, and CRSRX and CRSRY require a single additional parameter. If CRSRXY is used, arguments for x (spaces from left) and y (linefeeds from top) are required. If CRSRX is used, only the x value is required, and if CRSRY is used, only the y value is required. */ void term_cmd(int termConst, ...); /** * @} * * @name Miscellaneous * @{ */ /** * @brief Take bytes in one variable at varAddr, swap their order, and store them * in another variable at resultAddr. This is useful for communication with peripherals * that transmit/receive bytes in multi-byte values in reverse order from how the * Propeller stores it in RAM. * * @param *resultAddr Address of variable to store result. Make sure it's the * same type as the varAddr parameter. * * @param *varAddr Address of source variable. Accepts any variable type. * * @param *byteCount Number of bytes in the variable. */ void endianSwap(void *resultAddr, void *varAddr, int byteCount); /** * @} * * @name Deprecated * @{ */ /** * @brief Mark the current time (deprecated). * * @details The timeout function uses the marked time to determine if a timeout * has occurred. * * @note This function has been deprecated because it doesn't support use in * more than one cog. Use this code instead: * * @code * // CNT stores current number of system clock ticks elapsed. * int t = CNT; // Mark current time by storing in variable * @endcode */ void mark(void); /** * @brief Compares the time against the time elapsed since mark (deprecated). * * @details The default time increment is 1 us, so timeout(2000) will return 1 * if 2 ms or more has elapsed since mark, or 0 if it has not. * * @note This function has been deprecated because it doesn't support use in * more than one cog. Use this code instead: * * @code * // CLKFREQ stores number of system clock ticks in 1 second. * // CNT stores current number of system clock ticks elapsed. * int dt = CLKFREQ/2; // Pick a timeout, 1/2 a second in this case * int t = CNT; // Mark current time by storing in variable * while(CNT - t < dt) // Repeat until timeout * { * // Add code repeated until time elapsed is larger than dt here. * } * @endcode * * @param time Number of time increments. */ int timeout(int time); /** * @brief Waits a certain number of time increments from the last call to * mark or wait functions (deprecated). * * @details The default time increment is 1 us, so wait(2000) will return wait * until 2 us after the last call to mark or wait. This function automatically * updates the marked time; you can call it repeatedly without having to call mark. * * @note This function has been deprecated because it doesn't support use in * more than one cog. Use this code instead: * * @code * // CLKFREQ stores number of system clock ticks in 1 second. * // CNT stores current number of system clock ticks elapsed. * int t = CNT; // Mark current time by storing in variable * int dt = CLKFREQ/10; // Pick time increment, 1/10 second in this case * while(1) // Repeat indefinitely * { * // Variable timed code here. Must last less than dt. * waitcnt(t += dt); * // Code that must start at precise intervals here. * } * @endcode * * @param time Number of time increments. */ void wait(int time); /** * @} */ #if defined(__cplusplus) } #endif /* __cplusplus */ #endif /* SIMPLETOOLS_H */ /** * TERMS OF USE: MIT License * * 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. */