From a0549b4a15a7093f990fffa4bc1d2d52ec1c16e2 Mon Sep 17 00:00:00 2001 From: Hanna Mendes Levitin Date: Wed, 1 Dec 2010 03:37:07 -0600 Subject: docs, now with style --- docs/source/lang/cpp/arithmetic.rst | 127 +++++++++++++++ docs/source/lang/cpp/array.rst | 123 +++++++++++++++ docs/source/lang/cpp/assignment.rst | 70 +++++++++ docs/source/lang/cpp/bitshift.rst | 144 +++++++++++++++++ docs/source/lang/cpp/bitwisemath.rst | 186 ++++++++++++++++++++++ docs/source/lang/cpp/boolean.rst | 91 +++++++++++ docs/source/lang/cpp/booleanvariables.rst | 54 +++++++ docs/source/lang/cpp/break.rst | 35 +++++ docs/source/lang/cpp/byte.rst | 34 ++++ docs/source/lang/cpp/bytecast.rst | 50 ++++++ docs/source/lang/cpp/cc-attribution.txt | 9 ++ docs/source/lang/cpp/char.rst | 50 ++++++ docs/source/lang/cpp/charcast.rst | 36 +++++ docs/source/lang/cpp/comments.rst | 67 ++++++++ docs/source/lang/cpp/comparison.rst | 87 +++++++++++ docs/source/lang/cpp/compoundarithmetic.rst | 44 ++++++ docs/source/lang/cpp/compoundbitwise.rst | 231 ++++++++++++++++++++++++++++ docs/source/lang/cpp/const.rst | 52 +++++++ docs/source/lang/cpp/continue.rst | 32 ++++ docs/source/lang/cpp/curly-braces.rst | 109 +++++++++++++ docs/source/lang/cpp/define.rst | 56 +++++++ docs/source/lang/cpp/double.rst | 48 ++++++ docs/source/lang/cpp/doublecast.rst | 27 ++++ docs/source/lang/cpp/dowhile.rst | 27 ++++ docs/source/lang/cpp/enum.rst | 53 +++++++ docs/source/lang/cpp/float.rst | 50 ++++++ docs/source/lang/cpp/floatcast.rst | 28 ++++ docs/source/lang/cpp/for.rst | 142 +++++++++++++++++ docs/source/lang/cpp/goto.rst | 130 ++++++++++++++++ docs/source/lang/cpp/if.rst | 121 +++++++++++++++ docs/source/lang/cpp/include.rst | 72 +++++++++ docs/source/lang/cpp/increment.rst | 37 +++++ docs/source/lang/cpp/int.rst | 64 ++++++++ docs/source/lang/cpp/intcast.rst | 29 ++++ docs/source/lang/cpp/keywords.rst | 205 ++++++++++++++++++++++++ docs/source/lang/cpp/long.rst | 52 +++++++ docs/source/lang/cpp/longcast.rst | 27 ++++ docs/source/lang/cpp/modulo.rst | 70 +++++++++ docs/source/lang/cpp/numeric-types.rst | 79 ++++++++++ docs/source/lang/cpp/pointer.rst | 31 ++++ docs/source/lang/cpp/return.rst | 61 ++++++++ docs/source/lang/cpp/scope.rst | 120 +++++++++++++++ docs/source/lang/cpp/semicolon.rst | 25 +++ docs/source/lang/cpp/sizeof.rst | 64 ++++++++ docs/source/lang/cpp/sqrt.rst | 25 +++ docs/source/lang/cpp/static.rst | 57 +++++++ docs/source/lang/cpp/string.rst | 128 +++++++++++++++ docs/source/lang/cpp/switchcase.rst | 118 ++++++++++++++ docs/source/lang/cpp/unsignedchar.rst | 33 ++++ docs/source/lang/cpp/unsignedint.rst | 55 +++++++ docs/source/lang/cpp/unsignedlong.rst | 41 +++++ docs/source/lang/cpp/variables.rst | 170 ++++++++++++++++++++ docs/source/lang/cpp/void.rst | 31 ++++ docs/source/lang/cpp/while.rst | 38 +++++ 54 files changed, 3945 insertions(+) create mode 100644 docs/source/lang/cpp/arithmetic.rst create mode 100644 docs/source/lang/cpp/array.rst create mode 100644 docs/source/lang/cpp/assignment.rst create mode 100644 docs/source/lang/cpp/bitshift.rst create mode 100644 docs/source/lang/cpp/bitwisemath.rst create mode 100644 docs/source/lang/cpp/boolean.rst create mode 100644 docs/source/lang/cpp/booleanvariables.rst create mode 100644 docs/source/lang/cpp/break.rst create mode 100644 docs/source/lang/cpp/byte.rst create mode 100644 docs/source/lang/cpp/bytecast.rst create mode 100644 docs/source/lang/cpp/cc-attribution.txt create mode 100644 docs/source/lang/cpp/char.rst create mode 100644 docs/source/lang/cpp/charcast.rst create mode 100644 docs/source/lang/cpp/comments.rst create mode 100644 docs/source/lang/cpp/comparison.rst create mode 100644 docs/source/lang/cpp/compoundarithmetic.rst create mode 100644 docs/source/lang/cpp/compoundbitwise.rst create mode 100644 docs/source/lang/cpp/const.rst create mode 100644 docs/source/lang/cpp/continue.rst create mode 100644 docs/source/lang/cpp/curly-braces.rst create mode 100644 docs/source/lang/cpp/define.rst create mode 100644 docs/source/lang/cpp/double.rst create mode 100644 docs/source/lang/cpp/doublecast.rst create mode 100644 docs/source/lang/cpp/dowhile.rst create mode 100644 docs/source/lang/cpp/enum.rst create mode 100644 docs/source/lang/cpp/float.rst create mode 100644 docs/source/lang/cpp/floatcast.rst create mode 100644 docs/source/lang/cpp/for.rst create mode 100644 docs/source/lang/cpp/goto.rst create mode 100644 docs/source/lang/cpp/if.rst create mode 100644 docs/source/lang/cpp/include.rst create mode 100644 docs/source/lang/cpp/increment.rst create mode 100644 docs/source/lang/cpp/int.rst create mode 100644 docs/source/lang/cpp/intcast.rst create mode 100644 docs/source/lang/cpp/keywords.rst create mode 100644 docs/source/lang/cpp/long.rst create mode 100644 docs/source/lang/cpp/longcast.rst create mode 100644 docs/source/lang/cpp/modulo.rst create mode 100644 docs/source/lang/cpp/numeric-types.rst create mode 100644 docs/source/lang/cpp/pointer.rst create mode 100644 docs/source/lang/cpp/return.rst create mode 100644 docs/source/lang/cpp/scope.rst create mode 100644 docs/source/lang/cpp/semicolon.rst create mode 100644 docs/source/lang/cpp/sizeof.rst create mode 100644 docs/source/lang/cpp/sqrt.rst create mode 100644 docs/source/lang/cpp/static.rst create mode 100644 docs/source/lang/cpp/string.rst create mode 100644 docs/source/lang/cpp/switchcase.rst create mode 100644 docs/source/lang/cpp/unsignedchar.rst create mode 100644 docs/source/lang/cpp/unsignedint.rst create mode 100644 docs/source/lang/cpp/unsignedlong.rst create mode 100644 docs/source/lang/cpp/variables.rst create mode 100644 docs/source/lang/cpp/void.rst create mode 100644 docs/source/lang/cpp/while.rst (limited to 'docs/source/lang/cpp') diff --git a/docs/source/lang/cpp/arithmetic.rst b/docs/source/lang/cpp/arithmetic.rst new file mode 100644 index 0000000..91fe22e --- /dev/null +++ b/docs/source/lang/cpp/arithmetic.rst @@ -0,0 +1,127 @@ +.. highlight:: cpp + +.. _lang-arithmetic: + +Arithmetic Operators (``+``, ``-``, ``*``, ``/``) +================================================= + +The operators ``+``, ``-``, ``*``, and ``/`` respectively evaluate to +the sum, difference, product, or quotient (respectively) of the two +operands. The operation is conducted using the data type of the +operands, so, for example, ``9 / 4`` gives ``2`` since 9 and 4 are +:ref:`int variables `. + +This also means that the operation can overflow if the result is +larger than that which can be stored in the data type (e.g. adding 1 +to an :ref:`lang-int` with the value 2,147,483,647 gives +-2,147,483,648). + +.. _lang-arithmetic-typeconversion: + +If the operands are of different types, the "larger" type is used for +the calculation. If one of the numbers (operands) are of the type +**float** or of type **double**, floating point math will be used for +the calculation. + +.. note:: The specifics of these rules are beyond the scope of this + documentation; for more information, see `The C++ Programming + Language `_\ , by Bjarne + Stroustroup, Appendix C, especially §§C.4-C.6, or `this WikiBooks + entry on C++ type conversion + `_. + +.. note:: For more information on how computers represent integers, + see the Wikipedia page on `two's complement + `_. + +.. contents:: Contents + :local: + +Examples +-------- + + :: + + y = y + 3; + x = x - 7; + i = j * 6; + r = r / 5; + + +Syntax +------ + + :: + + result = value1 + value2; + result = value1 - value2; + result = value1 * value2; + result = value1 / value2; + + +Parameters +---------- + +**value1**: any numeric variable or constant + +**value2**: any numeric variable or constant + +Programming Tips +---------------- + +- Know that :ref:`integer constants ` + default to :ref:`int `, so some constant calculations + may overflow (e.g., 200000 * 5000000 will yield a negative result). + +- Choose variable sizes that are large enough to hold the largest + results from your calculations. + +- Know at what point your variable will "roll over" and also what + happens in the other direction e.g. (0 - 1) for unsigned arithmetic, + or (0 - -2,147,483,648) for signed arithmetic. + +- For math that requires fractions, float variables may be used, but + be aware of their drawbacks: large size and slow computation speeds + (the STM32 has no floating point hardware, so all floating point + calculations have to be done in software). + +- Use cast operator, e.g. ``(int)myFloat`` to convert one variable type + to another on the fly. + +Arduino Compatibility +--------------------- + +Since the STM32 processor on the Maple is a 32-bit machine, the int +type overflows at a much higher value on Maple than on Arduino. In +particular, on Maple, ints do not overflow (become negative) until +they reach 2,147,483,648; on the Arduino, they overflow at 32,767. +Because of this, programs running on Maple are much less likely to run +into overflow issues. The following table summarizes the sizes and +ranges of integer datatypes on the Maple (the ranges of long long +types are approximate): + +.. _lang-arithmetic-int-sizes: + +.. csv-table:: + :header: Datatype, Unsigned range, Signed range, Size (bytes) + :widths: 8, 12, 17, 8 + + ``char``, 0 --- 255, -128 --- 127, 1 + ``short``, "0 --- 65,535", "-32,768 --- 32,767", 2 + ``int``, "0 --- 4,294,967,295", "-2,147,483,648 --- 2,147,483,647", 4 + ``long``, "0 --- 4,294,967,295", "-2,147,483,648 --- 2,147,483,647", 4 + ``long long``, "0 --- 1.8*10\ :sup:`19`\ " (approx.), "-9.2*10\ :sup:`18` --- 9.2*10\ :sup:`18` (approx.)", 8 + + +See Also +-------- + +- The individual sizes (in bits) of various available types are + defined in `libmaple_types.h + `_\ + . + +- :ref:`sizeof `\ () + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/array.rst b/docs/source/lang/cpp/array.rst new file mode 100644 index 0000000..30a818f --- /dev/null +++ b/docs/source/lang/cpp/array.rst @@ -0,0 +1,123 @@ +.. highlight:: cpp + +.. _lang-array: + +Arrays +====== + +An array is a collection of variables that are accessed with an index +number. Arrays in the C++ programming language, in which the Maple is +programmed, can be complicated, but using simple arrays is relatively +straightforward. + +.. contents:: Contents + :local: + +Creating (Declaring) an Array +----------------------------- + +All of the methods below are valid ways to create (declare) an +array. :: + + int myInts[6]; + int myPins[] = {2, 4, 8, 3, 6}; + int mySensVals[6] = {2, 4, -8, 3, 2}; + char message[6] = "hello"; + +You can declare an array without initializing it, as with myInts. In +the line referring to myPins, we declare an array without explicitly +choosing a size. The compiler counts the elements and creates an +array of the appropriate size. + +Finally, you can both initialize and size your array, as in +mySensVals. Note that when declaring an array with elements of type +char, one more element than your initialization is required, to hold +the required `null character `_. + + +Accessing an Array +------------------ + + +.. compound:: + + Arrays are **zero indexed**; that is, referring to the array + initialization above, the first element of the array is at index 0, + hence :: + + mySensVals[0] == 2; + mySensVals[1] == 4 + + and so forth. + +It also means that in an array with ten elements, index nine is the +last element. Hence:: + + int myArray[10]={9,3,2,4,3,2,7,8,9,11}; + // myArray[9] contains 11 + // myArray[10] is invalid and contains random information (other memory address) + +For this reason, you should be careful in accessing arrays. Accessing +past the end of an array (using an index number greater than your +declared array size - 1) is reading from memory that is in use for +other purposes. Reading from these locations is probably not going to +do much except yield invalid data. Writing to random memory locations +is definitely a bad idea, and can often lead to unhappy results such +as crashes or program malfunction. This can also be a difficult bug to +track down. + +Unlike Basic or Java, the C compiler does no checking to see if array +access is within legal bounds of the array size that you have +declared. + + +To assign a value to an array +----------------------------- + :: + + mySensVals[0] = 10; + + +To retrieve a value from an array +--------------------------------- + + :: + + x = mySensVals[4]; + + +Arrays and ``for`` Loops +------------------------ + +Arrays are often manipulated inside :ref:`for loops `, where +the loop counter is used as the index for each array element. For +example, to print the elements of an array over the serial port, you +could do something like this:: + + int i; + for (i = 0; i < 5; i = i + 1) { + SerialUSB.println(myPins[i]); + } + + +Example +------- + +For a complete program that demonstrates the use of arrays, see the +Arduino `Knight Rider example +`_\ (which will run +unmodified on the Maple). + +Arduino Compatibility +--------------------- + +Arrays on Maple are identical those on Arduino. + +See also +-------- + +- :ref:`Storing arrays in FLASH memory ` + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/assignment.rst b/docs/source/lang/cpp/assignment.rst new file mode 100644 index 0000000..b6ad4d5 --- /dev/null +++ b/docs/source/lang/cpp/assignment.rst @@ -0,0 +1,70 @@ +.. highlight:: cpp + +.. _lang-assignment: + +Assignment Operator (``=``) +=========================== + +Stores the value to the right of the equal sign in the variable to +the left of the equal sign. + +The single equal sign in the C++ programming language is called the +assignment operator. It has a different meaning than in algebra +class, where it indicated an equation or equality. The assignment +operator tells the microcontroller to evaluate whatever value or +expression is on the right side of the equal sign, and store it in +the variable to the left of the equal sign [#fgross]_. + + + +Example +------- + +:: + + int sensVal; // declare an integer variable named sensVal + senVal = analogRead(0); // store the (digitized) input voltage at analog pin 0 in SensVal + + + +Programming Tips +---------------- + +The variable on the left side of the assignment operator ( = sign ) +needs to be able to hold the value stored in it. If it is not large +enough to hold a value, the value stored in the variable will be +incorrect. + +Don't confuse the assignment operator [ = ] (single equal sign) +with the comparison operator [ == ] (double equal signs), which +evaluates whether two expressions are equal. + + +Arduino Compatibility +--------------------- + +Assignments on the Maple are identical to those on Arduino. + + + +See Also +-------- + + +- `if (comparison operators) `_ +- `char `_ +- `int `_ +- `long `_ + + +.. rubric:: Footnotes + +.. [#fgross] Experienced C++ programmers know this to be an + oversimplification of what happens when the variable on the left + hand side is an object. See Richard Gillam's wonderful and scary + `The Anatomy of the Assignment Operator + `_ + for more information. + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/bitshift.rst b/docs/source/lang/cpp/bitshift.rst new file mode 100644 index 0000000..e1c8de0 --- /dev/null +++ b/docs/source/lang/cpp/bitshift.rst @@ -0,0 +1,144 @@ +.. highlight:: cpp + +.. _lang-bitshift: + +Bit Shift Operators (``<<``, ``>>``) +==================================== + +(Adapted from `The Bit Math Tutorial +`_ in `The Arduino +Playground `_\ ) + +There are two bit shift operators in C++: the left shift operator +``<<`` and the right shift operator ``>>``. These operators cause the +bits in the left operand to be shifted left or right by the number of +positions specified by the right operand. + +More information on bitwise math can be obtained in the Wikipedia +article on `bitwise operations +`_\ , especially the +section on shifts in `C, C++, and Java +`_\ . + + +Syntax +------ + +``some_int << number_of_bits`` + +``some_int >> number_of_bits`` + + +Parameters +---------- + +* **some_int** An integer value or variable. + +* **number_of_bits** integer whose value is at most ``8 * + sizeof(variable)`` (so ``number_of_bits`` can be at most 32 for + ``int`` values, at most ``8`` for ``char`` values, etc.; the various + integer sizes are summarized :ref:`in this table + `\ ). + + + +Example: +-------- + +Here are some examples of bit shifting, with the binary representation of the number in comments:: + + int a = 5; // binary: 101 + int b = a << 3; // binary: 101000, or 40 in decimal + int c = b >> 3; // binary: 101, or back to 5 like we started with + + +When you left shift a value x by y bits (x << y), the leftmost y bits +in x are lost, literally shifted out of existence. We'll do this +example with ``char`` values (which are integers in the range 0-255, +and take up 8 bits of memory):: + + char a = 5; // binary (all 8 bits): 00000101 + char b = a << 7; // binary: 10000000 - the first 1 in 101 was discarded + + +If you are certain that none of the ones in a value are being shifted +into oblivion, a simple way to think of the left-shift operator is +that it multiplies the left operand by 2 raised to the right operand +power (in math notation, ``x << y`` equals x * 2\ :sup:`y`\ , as long +as none of the bits of x get shifted out). For example, to generate +powers of 2, the following expressions can be employed:: + + 1 << 0 == 1 + 1 << 1 == 2 + 1 << 2 == 4 + 1 << 3 == 8 + ... + 1 << 8 == 256 + 1 << 9 == 512 + 1 << 10 == 1024 + ... + +.. _lang-bitshift-signbit-gotcha: + +When you shift x right by y bits (``x >> y``), and the highest bit in +x is a 1, the behavior depends on the exact data type of x. If x is of +type ``int``, the highest bit is special, and determines whether x is +negative or not; the details are too complicated to explain here, but +they are thoroughly explained in the Wikipedia article on `two's +complement arithmetic +`_\ , which the +system most computers use to store integers. In that case, the sign +bit is copied into lower bits, for esoteric historical reasons:: + + int x = -16; // binary (all 32 bits): 11111111111111111111111111110000 + int y = x >> 3; // binary: 11111111111111111111111111111110 + + + +This behavior, called "sign extension", is often not what you +want. You probably wish zeros to be shifted in from the left. It +turns out that the right shift rules are different for ``unsigned +int`` values, so you can use a type cast to suppress ones being copied +from the left:: + + int x = -16; // binary: 11111111111111111111111111110000 + int y = (unsigned int)x >> 3; // binary: 00011111111111111111111111111110 + + + +If you are careful to avoid sign extension, you can use the +right-shift operator, ``>>``, as a way to divide by powers of 2. For +example:: + + int x = 1000; + int y = x >> 3; // integer division of 1000 by 8, causing y = 125. + + +Arduino Compatibility +--------------------- + +Since it's part of the C++ language, bit shifting on the Maple is +compatible with the Arduino; however, you should keep in mind that the +Maple has bigger integer types (as in, more bits) than the Arduino. + +Since the STM32 is a 32-bit processor, the ``int`` type takes up 32 +bits instead of 16, like on Arduino's 16-bit microcontroller. This +means that you can shift left, like ``x << y``, with bigger values of +``y`` on the Maple before ones in ``x`` start to get shifted out. + +To calculate the number of bits of an integer type on the Maple, +multiply its size in bytes (see :ref:`this table +` for these) by 8, since there are 8 +bits in 1 byte. For example, a ``short`` takes up 2 bytes of memory, +or 2 * 8 = 16 bits. + +See Also +-------- + +- :ref:`lang-bit` +- :ref:`lang-bitread` +- :ref:`lang-bitwrite` +- :ref:`lang-bitclear` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/bitwisemath.rst b/docs/source/lang/cpp/bitwisemath.rst new file mode 100644 index 0000000..28fe6bf --- /dev/null +++ b/docs/source/lang/cpp/bitwisemath.rst @@ -0,0 +1,186 @@ +.. highlight:: cpp + +.. _lang-bitwisemath: + +Bitwise Operators (``&``, ``|``, ``^``, ``~``) +============================================== + +The bitwise operators perform their calculations at the bit level of +variables. They help solve a wide range of common programming +problems. + +Much of the material here is adapted for Maple from an (Arduino) +`tutorial on bitwise math +`_\ . Another great +resource is the Wikipedia article on `bitwise operations +`_\ . + +Below are descriptions and syntax for all of the operators. + +.. contents:: Contents + :local: + +.. _lang-bitwisemath-and: + +Bitwise AND (``&``) +------------------- + +The bitwise AND operator in C++ is a single ampersand, ``&``, used +between two other integer expressions. Bitwise AND operates on each +bit position of the surrounding expressions independently, according +to this rule: if both input bits are 1, the resulting output is 1, +otherwise the output is 0. Another way of expressing this is:: + + 0 0 1 1 operand1 + 0 1 0 1 operand2 + ---------- + 0 0 0 1 (operand1 & operand2) = result + + +On the Maple, the type ``int`` is a 32-bit value, so using ``&`` +between two ``int`` expressions causes 32 simultaneous AND operations +to occur. In a code fragment like:: + + int a = 92; // in binary: 00000000000000000000000001011100 + int b = 101; // in binary: 00000000000000000000000001100101 + int c = a & b; // result: 00000000000000000000000001000100, + // (or 68 in decimal). + + +Each of the 32 bits in ``a`` and ``b`` are processed using bitwise +AND, and all 32 resulting bits are stored in ``c``, resulting in the +value 1000100 in binary, which is 68 in decimal. + + +.. _lang-bitwisemath-or: + +Bitwise OR (``|``) +------------------ + +The bitwise OR operator in C++ is the vertical bar symbol, ``|``. Like +the ``&`` operator, ``|`` operates independently on each bit in its +two surrounding integer expressions, but what it does is +different. The bitwise OR of two bits is 1 if either or both of the +input bits is 1, otherwise it is 0. For example:: + + 0 0 1 1 operand1 + 0 1 0 1 operand2 + ---------- + 0 1 1 1 (operand1 | operand2) = result + +Here is an example of bitwise OR used in a snippet of C++ code (using +``char``, which takes up 8 bits of memory, instead of ``int``, which +uses 32):: + + char a = 92; // in binary: 01011100 + char b = 101; // in binary: 01100101 + char c = a | b; // result: 01111101, or 125 in decimal. + +.. _lang-bitwisemath-xor: + +Bitwise XOR (``^``) +------------------- + +There is a somewhat unusual operator in C++ called bitwise EXCLUSIVE +OR, also known as bitwise XOR. (In English, this is usually pronounced +"zor" or "ex-or"). The bitwise XOR operator is written using the caret +symbol, ``^``. This operator is very similar to the bitwise OR +operator ``|``, except it evaluates to 0 for a given bit position when +both of the input bits for that position are 1:: + + 0 0 1 1 operand1 + 0 1 0 1 operand2 + ---------- + 0 1 1 0 (operand1 ^ operand2) = result + + +Another way to look at bitwise XOR is that each bit in the result +is a 1 if the input bits are different, or 0 if they are the same. + +Here is a simple example:: + + int x = 12; // binary (ignoring extra bits): 1100 + int y = 10; // binary: 1010 + int z = x ^ y; // binary: 0110, or decimal 6 + + + +The ^ operator is often used to toggle (i.e. change from 0 to 1, or 1 +to 0) some of the bits in an integer expression. In a bitwise OR +operation if there is a 1 in the mask bit, that bit is inverted; if +there is a 0, the bit is not inverted and stays the same. Below is a +program to blink digital pin 13 (the LED pin on Maple):: + + // Blink Maple LED pin + + int led_pin = 13; + int toggle = 0; + + // demo for Exclusive OR + void setup(){ + pinMode(led_pin, OUTPUT); + } + + void loop(){ + toggle = toggle ^ 1; + digitalWrite(led_pin, toggle); + delay(100); + } + +.. _lang-bitwisemath-not: + +Bitwise NOT (``~``) +------------------- + +The bitwise NOT operator in C++ is the tilde character ``~``. Unlike +``&`` and ``|``, the bitwise NOT operator is applied to a single +operand to its right. Bitwise NOT changes each bit to its opposite: 0 +becomes 1, and 1 becomes 0. For example:: + + 0 1 operand1 + ---- + 1 0 ~operand1 = result + +Another example:: + + char a = 103; // binary: 01100111 + char b = ~a; // binary: 10011000 = -104 + +You might be surprised to see a negative number like -104 as the +result of this operation. This is because the highest bit in an int +variable is the so-called "sign bit". If the highest bit is 1, the +number is interpreted as negative. This encoding of positive and +negative numbers is referred to as *two's complement*. For more +information, see the Wikipedia article on `two's +complement. `_ + +As an aside, it is interesting to note that (under two's complement +arithmetic) for any integer ``x``, ``~x`` is the same as ``-x-1``. + +At times, the sign bit in a signed integer expression can cause +some unwanted surprises. + + +Uses +---- + +One of the most common uses of bitwise operations is to select or +manipulate a particular bit (or bits) from an integer value, often +called `bit masking +`_\ . See the +linked Wikipedia article for more information and examples. + +If you really want to see bit-twiddling techniques in their full +glory, you could do much worse than to get yourself a copy of +`Hacker's Delight `_\ . + + +See Also +-------- + +- :ref:`Boolean operations ` (``&&``, ``||``) +- :ref:`Compound bitwise operations ` (``&=``, + ``|=``, ``^=``). + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/boolean.rst b/docs/source/lang/cpp/boolean.rst new file mode 100644 index 0000000..8d6aa5c --- /dev/null +++ b/docs/source/lang/cpp/boolean.rst @@ -0,0 +1,91 @@ +.. highlight:: cpp + +.. _lang-boolean: + +Boolean Operators +================= + +These can be used inside the condition of an :ref:`if ` +statement. Evaluate to :ref:`true ` or +:ref:`false `. + +.. contents:: Contents + :local: + +.. _lang-boolean-and: + +&& (logical and) +---------------- + +True only if both operands are true. For example:: + + if (digitalRead(2) == HIGH && digitalRead(3) == HIGH) { // read two switches + // ... + } + +is true only if both inputs are high. Another example:: + + if (a >= 10 && a <= 20){} // true if a is between 10 and 20 + +**Be careful** not to say ``10 <= a <= 20``! This won't work the way +you want. You have to separately test whether ``a`` is at least 10 +using ``a >= 10``, then test whether ``a`` is at most 20 using ``a <= +20``, then combine the results using ``&&``. + + +.. _lang-boolean-or: + +\|\| (logical or) +----------------- + +True if either operand is true. For example:: + + if (x > 0 || y > 0) { + // ... + } + +is true if either ``x`` or ``y`` is greater than 0. + +.. _lang-boolean-not: + +! (logical not) +--------------- + +True if the operand is false. For example:: + + if (!x) { + // ... + } + +is true if ``x`` is false (i.e. if ``x`` is zero). + +Some Advice +----------- + +.. warning:: + + Make sure you don't mistake the boolean AND operator ``&&`` + (double ampersand) for the :ref:`bitwise AND operator + ` ``&`` (single ampersand). They are + entirely different beasts. + + Similarly, do not confuse the boolean OR operator ``||`` (double + pipe) with the :ref:`bitwise OR operator ` + ``|`` (single pipe). + + The :ref:`bitwise NOT operator ` ``~`` + (tilde) looks much different than the boolean not operator ``!`` + (exclamation point, or "bang", as some programmers say), but you + still have to be sure which one you want. + + +See Also +-------- + +- :ref:`Bitwise operators ` (``&``, ``|``, ``^``, ``~``) +- :ref:`Compound bitwise operators ` (``&=``, + ``|=``, ``^=``). +- :ref:`if statement ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/booleanvariables.rst b/docs/source/lang/cpp/booleanvariables.rst new file mode 100644 index 0000000..6051b8c --- /dev/null +++ b/docs/source/lang/cpp/booleanvariables.rst @@ -0,0 +1,54 @@ +.. highlight:: cpp + +.. _lang-booleanvariables: + +Booleans +======== + +A **boolean** holds one of two values, :ref:`true +` or :ref:`false `. On a +Maple, each boolean variable has type ``bool``. + +.. warning:: + + On an Arduino, the type ``boolean`` is also provided. While the + Maple also has this type for compatibility, **its use is strongly + discouraged**. The ``bool`` type is a standard part of C++, while + ``boolean`` is a non-standard extension that serves no purpose. + +Example +------- + +:: + + int ledPin = 13; // LED on pin 13 + int switchPin = 12; // momentary switch on 12, other side connected to ground + + // running is a boolean variable: + bool running = false; + + void setup() { + pinMode(ledPin, OUTPUT); + pinMode(switchPin, INPUT); + digitalWrite(switchPin, HIGH); // turn on pullup resistor + } + + void loop() { + if (digitalRead(switchPin) == LOW) { + // switch is pressed - pullup keeps pin high normally + delay(100); // delay to debounce switch + running = !running; // toggle running variable + digitalWrite(ledPin, running) // indicate via LED + } + } + +See also +-------- + + +- :ref:`Boolean constants ` +- :ref:`Boolean operators ` +- :ref:`Variables ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/break.rst b/docs/source/lang/cpp/break.rst new file mode 100644 index 0000000..ce8ac17 --- /dev/null +++ b/docs/source/lang/cpp/break.rst @@ -0,0 +1,35 @@ +.. highlight:: cpp + +.. _lang-break: + +``break`` +========= + +``break`` is used to exit from a :ref:`while `\ , +:ref:`for `\ , or :ref:`do/while ` loop, +bypassing the normal loop condition. It is also used to exit from a +:ref:`switch ` statement. + + +Example +------- + +:: + + for (x = 0; x < 255; x ++) + { + digitalWrite(PWMpin, x); + sens = analogRead(sensorPin); + if (sens > threshold){ // bail out on sensor detect + x = 0; + // this line of code means that we'll immediately exit + // from the "for" loop: + break; + } + delay(50); + } + + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/byte.rst b/docs/source/lang/cpp/byte.rst new file mode 100644 index 0000000..45c9d5f --- /dev/null +++ b/docs/source/lang/cpp/byte.rst @@ -0,0 +1,34 @@ +.. highlight:: cpp + +.. _lang-byte: + +byte +==== + +The ``byte`` type stores a 1-byte (8-bit) unsigned integer number, +from 0 to 255. + +.. warning:: + + The ``byte`` type is provided for compatibility with Arduino. + However, it is a non-standard extension. The standard C++ type for + storing an 8-bit unsigned integer is ``unsigned char``; we + recommend using that instead. (Your code will still work on an + Arduino). + + +Example +------- + +:: + + byte b = 134; + +See Also +-------- + +- :ref:`byte() ` (casting a value to a byte) +- :ref:`Variables ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/bytecast.rst b/docs/source/lang/cpp/bytecast.rst new file mode 100644 index 0000000..b3f0de2 --- /dev/null +++ b/docs/source/lang/cpp/bytecast.rst @@ -0,0 +1,50 @@ +.. highlight:: cpp + +.. _lang-bytecast: + +byte() (cast) +============= + +Converts a value to the :ref:`byte ` data type. + +.. note:: + + Casting to the byte type is provided for compatibility with + Arduino. However, the recommended Maple type for storing an 8-bit + unsigned integer is ``uint8``. (C and C++ programmers: ``stdint.h`` + is also available). + + In order to cast a variable ``x`` to a ``uint8``, the + following syntax can be used:: + + uint8(x); + +Syntax +------ + +``byte(x)`` + + +Parameters +---------- + +**x**: a value of any integer type + + +Returns +------- + +The value, converted to a ``byte``. Note, however, that if the value +is larger than the maximum value you can store in a byte (255), then +the results might be strange and unexpected. + + +See Also +-------- + +- :ref:`lang-byte` + + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/cc-attribution.txt b/docs/source/lang/cpp/cc-attribution.txt new file mode 100644 index 0000000..e100140 --- /dev/null +++ b/docs/source/lang/cpp/cc-attribution.txt @@ -0,0 +1,9 @@ +.. Included in all this directory's files in order to satisfy the +.. Arduino CC Attribution-ShareAlike 3.0 License + +.. admonition:: License and Attribution + + This documentation page was adapted from the `Arduino Reference + Documentation `_\ , which + is released under a `Creative Commons Attribution-ShareAlike 3.0 + License `_. diff --git a/docs/source/lang/cpp/char.rst b/docs/source/lang/cpp/char.rst new file mode 100644 index 0000000..b8747f3 --- /dev/null +++ b/docs/source/lang/cpp/char.rst @@ -0,0 +1,50 @@ +.. highlight:: cpp + +.. _lang-char: + +``char`` +======== + +The ``char`` type stores a 1-byte character value (or integer with +value from -128 to 127). Character literals are written in single +quotes, like this: ``'A'`` (for multiple characters - strings - use +double quotes: ``"ABC"``). + + +Just like everything else on a computer, characters are stored as +numbers. You can see the specific encoding in the `ASCII chart +`_\ +. This means that it is possible to do arithmetic on characters, in +which the ASCII value of the character is used (e.g. ``'A' + 1`` has the +decimal value 66, since the ASCII value of the capital letter A in +decimal is 65). See the :ref:`Serial.println() +` documentation for more information about how +characters are converted into numbers. + +The ``char`` datatype is a signed type, meaning that it encodes +numbers from -128 to 127. For an unsigned type, which stores values +from 0 to 255, just use the type ``unsigned char`` (two words). + + +Example +------- + +:: + + // the following two lines are equivalent, using the ASCII + // character encoding: + char c = 'A'; + char c = 65; + + +See also +-------- + + +- :ref:`lang-int` +- :ref:`lang-array` (a string is just an array of ``char``\ s) +- :ref:`Serial.println() ` + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/charcast.rst b/docs/source/lang/cpp/charcast.rst new file mode 100644 index 0000000..a480dec --- /dev/null +++ b/docs/source/lang/cpp/charcast.rst @@ -0,0 +1,36 @@ +.. highlight:: cpp + +.. _lang-charcast: + +``char()`` (cast) +================= + +Converts a value to the :ref:`char ` data type. + +Syntax +------ + +``char(x)`` + + +Parameters +---------- + +**x**: a value of any type + + +Returns +------- + +The value, converted to a ``char``. Note, however, that if the value +is outside the range of a ``char`` (-128 to 127), then the results +might be strange and unexpected. + + +See Also +-------- + +- :ref:`char ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/comments.rst b/docs/source/lang/cpp/comments.rst new file mode 100644 index 0000000..c5f118a --- /dev/null +++ b/docs/source/lang/cpp/comments.rst @@ -0,0 +1,67 @@ +.. highlight:: cpp + +.. _lang-comments: + +Comments +======== + +Comments are lines in the program that are used to inform yourself or +others about the way the program works. They are ignored by the +compiler, and not exported to the processor, so they don't take up any +space in RAM or Flash. + +One use for comments is to help you understand (or remember) how your +program works, or to inform others how your program works. There are +two different ways of making comments. + +.. _lang-comments-singleline: + +**Single line comment**: Anything following two slashes, ``//``, until +the end of the line, is a comment:: + + x = 5; // the rest of this line is a comment + +.. _lang-comments-multiline: + +**Multi-line comment**: Anything in between a pair of ``/*`` and ``*/`` +is a comment:: + + /* <-- a slash-star begins a multi-line comment + + all of this in the multi-line comment - you can use it to comment + out whole blocks of code + + if (gwb == 0){ // single line comment is OK inside a multi-line comment + x = 3; + } + + // don't forget the "closing" star-slash - they have to be balanced: + */ + +Note that it's okay to use single-line comments within a multi-line +comment, but you can't use multi-line comments within a multi-line +comment. Here's an example:: + + /* ok, i started a multi-line comment + + x = 3; /* this next star-slash ENDS the multi-line comment: */ + + x = 4; // this line is outside of the multi-line comment + + // next line is also outside of the comment, and causes a compile error: + */ + +Programming Tip +--------------- + +When experimenting with code, "commenting out" parts of your program +is a convenient way to remove lines that may be buggy. This leaves +the lines in the code, but turns them into comments, so the compiler +just ignores them. This can be especially useful when trying to locate +a problem, or when a program refuses to compile and the compiler error +is cryptic or unhelpful. + + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/comparison.rst b/docs/source/lang/cpp/comparison.rst new file mode 100644 index 0000000..b24355f --- /dev/null +++ b/docs/source/lang/cpp/comparison.rst @@ -0,0 +1,87 @@ +.. highlight:: cpp + +.. _lang-comparison: + +Comparison Operators (``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=``) +=================================================================== + +The comparison operators ``==``, ``!=``, ``<``, ``>``, ``<=``, and +``>=`` are used to compare two numbers. They are :ref:`true +` when the comparison is true, and :ref:`false +` otherwise. They are based on the symbols +=, ≠, <, >, ≤, and ≥ from mathematics. + +Here are some examples, with their meaning in comments:: + + // "eq" is true when x is equal to y + bool eq = (x == y); + + // "neq" is true when x is different than y + bool neq = (x != y); + + // "lt" is true when x is less than, but NOT equal to, y + bool lt = (x < y); + + // "gt" is true when x is greater than, but NOT equal to, y + bool gt = (x > y); + + // "lte" is true when x is less than or equal to y + bool lte = (x <= y); + + // "gte" is true when x is greater than or equal to y + bool gte = (x >= y); + +The parentheses are optional; they are present only for clarity. For +example, the following two lines are the same:: + + bool eq = x == y; + + bool eq = (x == y); + +Uses +---- + +Comparison operators, along with :ref:`boolean operators +`, are useful inside the conditionals of :ref:`if +` statements. Here's one example:: + + if (x < 50) { + // only execute these lines if x is less than 50 + SerialUSB.println("delaying:"); + SerialUSB.println(x); + delay(x); + } + +.. warning:: + Beware of accidentally using the single equal sign (``=``) when you + meant to test if two numbers are equal (``==``). This is a common + mistake inside of ``if`` statement conditionals, e.g.:: + + // DON'T MAKE THIS MISTAKE + if (x = 10) { + // body + } + + The single equal sign is the assignment operator, and sets x to 10 + (puts the value 10 into the variable x). Instead use the double equal + sign (e.g. ``if (x == 10)``), which is the comparison operator, and + tests *whether* x is equal to 10 or not. The latter statement is only + true if x equals 10, but the former statement will always be true. + + This is because C evaluates the statement ``if (x=10)`` as follows: 10 + is assigned to x (remember that the single equal sign is the + :ref:`assignment operator `), so x now + contains 10. Then the 'if' conditional evaluates 10, which evaluates + to :ref:`true `, since any non-zero number + evaluates to ``true``. + + Consequently, the conditional of an ``if`` statement like ``if (x = + 10) {...}`` will always evaluate to ``true``, and the variable x + will be set to 10, which is probably not what you meant. + + (This sometimes has uses, though, so just because an assignment + appears within a conditional doesn't mean it's automatically wrong. + Be careful to know what you mean.) + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/compoundarithmetic.rst b/docs/source/lang/cpp/compoundarithmetic.rst new file mode 100644 index 0000000..420f1db --- /dev/null +++ b/docs/source/lang/cpp/compoundarithmetic.rst @@ -0,0 +1,44 @@ +.. highlight:: cpp + +.. _lang-compoundarithmetic: + +Compound Arithmetic Operators (``+=`` , ``-=``, ``*=``, ``/=``) +=============================================================== + +These oparators perform a mathematical operation on a variable with +another constant or variable. These operators are just a convenient +shorthand:: + + x += y; // equivalent to the expression x = x + y; + x -= y; // equivalent to the expression x = x - y; + x *= y; // equivalent to the expression x = x * y; + x /= y; // equivalent to the expression x = x / y; + +Here is an example:: + + int x = 2; + int y = 10; + + x += 4; // x now contains 6 + x -= 3; // x now contains 3 + x *= y; // x now contains 30 + x /= 2; // x now contains 15 + x += max(20, 6); // x now contains 35 + x -= sq(5); // x now contains 15 + +Parameters +---------- + +**x**: a numeric variable + +**y**: a numeric variable, number constant, or any other expression +that evaluates to a number (e.g. call to a function that returns a +number). + +See Also +-------- + +- :ref:`Arithmetic operators ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/compoundbitwise.rst b/docs/source/lang/cpp/compoundbitwise.rst new file mode 100644 index 0000000..a4bbb24 --- /dev/null +++ b/docs/source/lang/cpp/compoundbitwise.rst @@ -0,0 +1,231 @@ +.. highlight:: cpp + +.. _lang-compoundbitwise: + +Compound Bitwise Operators (``&=``, ``|=``, ``^=``) +=================================================== + +The compound bitwise operators perform their calculations at the +bit level of variables. They are often used to clear and set +specific bits of a variable. + +See the :ref:`bitwise math tutorial ` for more +information on bitwise operators. + +.. contents:: Contents + :local: + +.. _lang-compoundbitwise-and: + +Compound bitwise AND (``&=``) +----------------------------- + +The compound bitwise AND operator ``&=`` is often used with a variable +and a constant to force particular bits in a variable to be zero. This +is often referred to in programming guides as "clearing" or +"resetting" bits. In a program, writing the line ``x &= y;`` is +equivalent to writing ``x = x & y;``. That is, the value of ``x`` +after the line will be equal to its old value bitwise ANDed with the +value of ``y``:: + + x &= y; // equivalent to x = x & y; + +You can use any integer variable for ``x`` (i.e., any variable of type +``int``, ``long``, ``char``, ``byte``, etc.). You can use either an +integer variable or any :ref:`integer value +` (like ``3`` or ``0x20``) for ``y``. + +Before doing an example of ``&=``, let's first review the Bitwise AND +(``&``) operator:: + + 0 0 1 1 operand1 + 0 1 0 1 operand2 + ---------- + 0 0 0 1 (operand1 & operand2) = result + +As shown above, bits that are "bitwise ANDed" with 0 become 0, while +bits that are "bitwise ANDed" with 1 are left unchanged. So, if ``b`` +is a ``byte`` variable, then ``b & B00000000`` equals zero, and ``b & +B11111111`` equals ``b``. + +.. _lang-compoundbitwise-binconst: + +.. note:: The above uses :ref:`binary constants + `\ . The numbers are still the same + value in other representations, they just might not be as easy to + understand. + + Normally, in C and C++ code, :ref:`hexadecimal + ` or :ref:`octal + ` are used when we're interested in + an integer's bits, rather than its value as a number. + + While hexadecimal and octal literals might be harder to understand + at first, you should really take the time to learn them. They're + part of C, C++, and many other programming languages, while binary + constants are available only for compatibility with Arduino. + + Also, ``B00000000`` is shown for clarity, but zero in any number + format is zero. + +So, to clear (set to zero) bits 0 and 1 of a one-byte variable, while +leaving the rest of the variable's bits unchanged, use the compound +bitwise AND operator ``&=`` with the constant ``B11111100`` +(hexadecimal ``0xFC``\ ):: + + 1 0 1 0 1 0 1 0 variable + 1 1 1 1 1 1 0 0 mask + ---------------------- + 1 0 1 0 1 0 0 0 + ^^^^^^^^^^^^^^^^ ^^^^ + unchanged cleared + + +Here is the same representation with the variable's bits replaced +with the symbol ``x``\ :: + + x x x x x x x x variable + 1 1 1 1 1 1 0 0 mask + ---------------------- + x x x x x x 0 0 + ^^^^^^^^^^^^^^^^ ^^^^ + unchanged cleared + + +So, using a byte variable ``b``\ , if we say:: + + b = B10101010; // B10101010 == 0xAA + b &= B11111100; // B11111100 == 0xFC + +then we will have :: + + b == B10101000; // B10101000 == 0xA8 + +.. _lang-compoundbitwise-or: + +Compound bitwise OR (``|=``) +---------------------------- + +The compound bitwise OR operator ``|=`` is often used with a variable +and a constant to "set" (set to 1) particular bits in a variable. In +a program, writing the line ``x |= y;`` is equivalent to writing ``x = +x | y;``. That is, the value of ``x`` after the line will be equal to +its old value bitwise ORed with the value of ``y``:: + + x |= y; // equivalent to x = x | y; + +You can use any integer variable for ``x`` (i.e., any variable of type +``int``, ``long``, ``char``, ``byte``, etc.). You can use either an +integer variable or any integer value (like ``3`` or ``0x20``) for +``y``. (This works the same way as :ref:`compound bitwise AND +`\ , ``&=``). + +Before doing an example of ``|=``, let's first review the Bitwise OR +(``|``) operator:: + + 0 0 1 1 operand1 + 0 1 0 1 operand2 + ---------- + 0 1 1 1 (operand1 | operand2) = result + +Bits that are "bitwise ORed" with 0 are unchanged, while bits that are +"bitwise ORed" with 1 are set to 1. So if ``b`` is a ``byte`` +variable, then ``b | B00000000`` equals ``b``, and ``b & B11111111`` +equals ``B11111111`` (here we've used binary constants; see the +:ref:`note ` above). + +So, to set bits 0 and 1 of a one-byte variable, while leaving the rest +of the variable unchanged, use the compound bitwise OR operator +(``|=``) with the constant ``B00000011`` (hexadecimal ``0x3``):: + + 1 0 1 0 1 0 1 0 variable + 0 0 0 0 0 0 1 1 mask + ---------------------- + 1 0 1 0 1 0 1 1 + ^^^^^^^^^^^^^^^^ ^^^^ + unchanged set + +Here is the same representation with the variable's bits replaced with +the symbol ``x``:: + + x x x x x x x x variable + 0 0 0 0 0 0 1 1 mask + ---------------------- + x x x x x x 1 1 + ^^^^^^^^^^^^^^^^ ^^^^ + unchanged set + +So, using a byte variable ``b``, if we say:: + + b = B10101010; // B10101010 == 0xAA + b |= B00000011; // B00000011 == 0x3 + +then we will have :: + + b == B10101011; // B10101011 == 0xAB + +.. _lang-compoundbitwise-xor: + +Compound bitwise XOR (``^=``) +----------------------------- + +The compound bitwise XOR operator ``^=`` is used with a variable and a +constant to "toggle" (change 0 to 1, and 1 to 0) particular bits in a +variable. In a program, writing the line ``x ^= y;`` is equivalent to +writing ``x = x ^ y;``. That is, the value of ``x`` after the line +will be equal to its old value bitwise XORed with the value of ``y``:: + + x ^= y; // equivalent to x = x ^ y; + +You can use any integer variable for ``x`` (i.e., any variable of type +``int``, ``long``, ``char``, ``byte``, etc.). You can use either an +integer variable or any integer value (like ``3`` or ``0x20``) for +``y``. (This works the same way as :ref:`&= +` and :ref:`\|= +`; in fact, these three operators all +work the same in this way). + +Before doing an example of ``^=``, let's first review the Bitwise +XOR operator, ``^``:: + + 0 0 1 1 operand1 + 0 1 0 1 operand2 + ---------- + 0 1 1 0 (operand1 ^ operand2) = result + +One way to look at bitwise XOR is that each bit in the result is a 1 +if the input bits are different, or 0 if they are the same. Another +way to think about it is that the result bit will be 1 when *exactly* +one (no more, no less) of the input bits is 1; otherwise, it will be +zero. This means that if you XOR a bit with 1, it will change (or +toggle) its value, while if you XOR a bit with 0, it stays the same. + +So, to toggle bits 0 and 1 of a one-byte variable, while leaving the +rest of the variable unchanged, use the compound bitwise XOR operator +``^=`` with the constant ``B00000011`` (hexadecimal ``0x3``\ ; see +:ref:`note ` above):: + + 1 0 1 0 1 0 1 0 variable + 0 0 0 0 0 0 1 1 mask + ---------------------- + 1 0 1 0 1 0 1 1 + ^^^^^^^^^^^^^^^^ ^^^^ + unchanged toggled + +So, using a byte variable ``b``, if we say:: + + b = B10101010; // B10101010 == 0xAA + b ^= B00000011; // B00000011 == 0x3 + +then we will have :: + + b == B10101001; // B10101001 == 0xA9 + +See Also +-------- + +- :ref:`Boolean operations ` (``&&``, ``||``) +- :ref:`Bitwise operators ` (``&``, ``|``, ``^``, ``~``) + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/const.rst b/docs/source/lang/cpp/const.rst new file mode 100644 index 0000000..52de85f --- /dev/null +++ b/docs/source/lang/cpp/const.rst @@ -0,0 +1,52 @@ +.. highlight:: cpp + +.. _lang-const: + +``const`` +========= + +The ``const`` keyword stands for "constant". It is a variable +*qualifier* that modifies the behavior of the variable, making a +variable "*read-only*". This means that the variable can be used just +as any other variable of its type, but its value cannot be +changed. You will get a compiler error if you try to assign a value to +a ``const`` variable. + +Constants defined with the ``const`` keyword obey the same rules of +:ref:`variable scoping ` that govern other +variables. This, and the pitfalls of using :ref:`#define +`, often makes using the ``const`` keyword a superior +method for defining constants than ``#define``. + +Example +------- + +:: + + // this defines a variable called "pi", which cannot be changed: + const float pi = 3.14; + float x; + + // .... + + x = pi * 2; // it's fine to find the value of a const variable + + pi = 7; // illegal - you can't write to (modify) a constant + + +**#define** or **const** +------------------------ + +You can use either ``const`` or ``#define`` for creating numeric or +string constants. For :ref:`arrays `\ , you will need +to use ``const``. In general, ``const`` is preferred over ``#define`` +for defining constants. + +See Also +-------- + +- :ref:`#define ` +- :ref:`volatile ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/continue.rst b/docs/source/lang/cpp/continue.rst new file mode 100644 index 0000000..13d1815 --- /dev/null +++ b/docs/source/lang/cpp/continue.rst @@ -0,0 +1,32 @@ +.. highlight:: cpp + +.. _lang-continue: + +``continue`` +============ + +The ``continue`` keyword skips the rest of the current iteration of a +:ref:`while `\ , :ref:`for `\ , or +:ref:`do/while ` loop. It continues by checking the +conditional expression of the loop, and proceeding with any subsequent +iterations. + +Example +------- + +:: + + + for (x = 0; x < 255; x ++) { + if (x > 40 && x < 120) { // create jump in values + continue; // skips the next two lines and goes to the + // beginning of the loop, with the next value of x + } + + digitalWrite(PWMpin, x); + delay(50); + } + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/curly-braces.rst b/docs/source/lang/cpp/curly-braces.rst new file mode 100644 index 0000000..a4bd3dc --- /dev/null +++ b/docs/source/lang/cpp/curly-braces.rst @@ -0,0 +1,109 @@ +.. highlight:: cpp + +.. _lang-curly-braces: + +Curly Braces (``{``, ``}``) +=========================== + +.. contents:: Contents + :local: + +Introduction +------------ + +Curly braces (also referred to as just "braces" or as "curly +brackets") are a major part of the C and C++ programming +languages. They are used in several different constructs, outlined +below, and this can sometimes be confusing for beginners. + +An opening curly brace, ``{`` must always be followed by a closing +curly brace ``}``. This is a condition that is often referred to as +the braces being *balanced*. The Maple IDE (integrated development +environment) includes a convenient feature to check the balance of +curly braces. Just select a brace, or even click the insertion point +immediately following a brace, and its companion will be highlighted\ +[#fbug]_\ . + +Beginning programmers, and programmers coming to C++ from languages +without braces, often find using them confusing or daunting. + +Because the use of the curly brace is so varied, it is good +programming practice to type the closing brace immediately after +typing the opening brace when inserting a construct which requires +curly braces. Then insert some blank lines between your braces and +begin inserting statements. Your braces, and your attitude, will never +become unbalanced. + +Unbalanced braces can often lead to cryptic, impenetrable compiler +errors that can sometimes be hard to track down in a large program. +Because of their varied usages, braces are also incredibly important +to the syntax of a program and moving a brace one or two lines will +usually dramatically affect the meaning of a program. + +The main uses of curly braces +----------------------------- + +**Functions**:: + + // a function body needs braces around it + void myFunction(datatype argument) { + // ... function body goes in here ... + } + +**Loops** (see the :ref:`while `\ , :ref:`for +`\ , and :ref:`do/while ` loop reference +pages for more information):: + + // you should put braces around the body of a loop: + + while (boolean expression) { + // code inside the loop goes here + } + + for (initialisation; termination condition; incrementing expr) { + // code inside the loop goes here + } + + do { + // code inside the loop goes here + } while (boolean expression); + + +**Conditional statements** (see the :ref:`if statement ` +reference page for more information):: + + // you should put braces around the body of an "if", "else if", + // or "else": + + if (boolean expression) { + // code inside the "if" + } + else if (boolean expression) { + // code inside the "else if" + } + else { + // code inside the "else" + } + +**Switch statements** (see the :ref:`switch statement +` reference page for more information):: + + switch (var) { + case 1: + doThing1(); + break; + case 2: + doThing2(); + break; + } + +.. rubric:: Footnotes + +.. TODO remove this once IDE 0.1.0 released + +.. [#fbug] At present this feature is slightly buggy as the IDE will + often find (incorrectly) a brace in text that has been commented + out. + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/define.rst b/docs/source/lang/cpp/define.rst new file mode 100644 index 0000000..677390d --- /dev/null +++ b/docs/source/lang/cpp/define.rst @@ -0,0 +1,56 @@ +.. highlight:: cpp + +.. _lang-define: + +``#define`` +=========== + +``#define`` is a useful C and C++ feature that allows the programmer +to give a name to a constant value before the program is compiled. +The compiler will replace references to these constants with the +defined value at compile time. + +This can have some unwanted side effects. In general, the :ref:`const +` keyword is preferred for defining constants. + + +Syntax +------ + +The following line would define the name ``MY_CONSTANT`` to have value +``value``:: + + #define MY_CONSTANT value + +Note that the ``#`` is necessary. It is usually good style for the +name to be capitalized, although this is not required. + +There is no semicolon after the #define statement. If you include one, +the compiler will likely throw cryptic errors in unrelated places. +That is, **don't do this**:: + + // DON'T DO THIS! THE SEMICOLON SHOULDN'T BE THERE! + #define NAME value; + +Similarly, including an equal sign after the ``#define`` line will +also generate a cryptic compiler error further down the page. That +is, **don't do this, either**:: + + // DON'T DO THIS, EITHER! THE EQUALS SIGN SHOULDN'T BE THERE! + #define NAME = value + +Example +------- + +:: + + #define LED_PIN 13 + // The compiler will replace any mention of LED_PIN with + // the value 3 at compile time. + +See Also +-------- +- :ref:`const ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/double.rst b/docs/source/lang/cpp/double.rst new file mode 100644 index 0000000..1527778 --- /dev/null +++ b/docs/source/lang/cpp/double.rst @@ -0,0 +1,48 @@ +.. _lang-double: + +``double`` +========== + +Double precision floating point type. Occupies 8 bytes. On Maple, the +``double`` type has a range of approximately -1.79769×10^308 to +1.79769×10^308; the ``double`` type subject to the same :ref:`overflow +issues ` as any numeric data type. + +Floating point numbers are not exact, and may yield strange results +when compared. For example ``6.0 / 3.0`` may not equal ``2.0``. You +should instead check that the absolute value of the difference between +the numbers is less than some small number. + +Floating point math is also much slower than integer math in +performing calculations, so should be avoided if, for example, a loop +has to run at top speed for a critical timing function. Programmers +often go to some lengths to convert floating point calculations to +integer math to increase speed. + +For more information, see the `Wikipedia article on floating point +math `_\ . + +Floating-point numbers represent numbers with "decimal point", unlike +integral types, which always represent whole numbers. Floating-point +numbers are often used to approximate analog and continuous values +because they have greater resolution than integers. + +The double implementation on the Maple uses twice the number of bytes +as a :ref:`float `, with the corresponding gains in +precision. + +Tip +--- + +Users who borrow code from other sources that includes ``double`` +variables may wish to examine the code to see if the implied range and +precision are different from that actually achieved on the Maple. + +See Also +-------- + +- :ref:`float ` + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/doublecast.rst b/docs/source/lang/cpp/doublecast.rst new file mode 100644 index 0000000..511fe24 --- /dev/null +++ b/docs/source/lang/cpp/doublecast.rst @@ -0,0 +1,27 @@ +.. highlight:: cpp + +.. _lang-doublecast: + +``double()`` (cast) +=================== + +Converts a value to the :ref:`double ` floating point +data type. Here is an example:: + + int x = 2; + double d = double(x); // d now holds 2.0, a double value + +The value ``x`` can be of any type. However, if ``x`` is not a number +(like an ``int`` or ``long``), you will get strange results. + +See the :ref:`double ` reference for details about the +precision and limitations of ``double`` values on the Maple. + +See Also +-------- + +- :ref:`double ` +- :ref:`float ` +- :ref:`float() ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/dowhile.rst b/docs/source/lang/cpp/dowhile.rst new file mode 100644 index 0000000..fe92226 --- /dev/null +++ b/docs/source/lang/cpp/dowhile.rst @@ -0,0 +1,27 @@ +.. highlight:: cpp + +.. _lang-dowhile: + +``do``/``while`` +================ + +A ``do`` loop works in the same manner as a :ref:`while +` loop, with the exception that the condition is tested +at the end of the loop, so the ``do`` loop will *always* run at least +once. + +This is the basic syntax:: + + do { + // statement block + } while (test condition); + +Example:: + + do { + delay(50); // wait for sensors to stabilize + x = readSensors(); // check the sensors + } while (x < 100); + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/enum.rst b/docs/source/lang/cpp/enum.rst new file mode 100644 index 0000000..ba82383 --- /dev/null +++ b/docs/source/lang/cpp/enum.rst @@ -0,0 +1,53 @@ +.. highlight:: cpp + +.. _lang-enum: + +``enum`` +======== + +The ``enum`` keyword is used to specify an enumeration type. An +enumeration type is a type whose values are taken from a specified, +fixed list of constant values. + +Example +------- + +Here's an example defining an enumeration type called ``weather``, +which has values ``HOT``, ``COMFY``, and ``COLD``:: + + enum weather {HOT, COMFY, COLD}; + +Once you've defined this type, you can create variables of type +``weather``, in the same way you would with an :ref:`int ` +or a :ref:`long `:: + + // create a weather variable named theWeather, with value COMFY: + weather theWeather = COMFY; + +Enumeration types are useful within :ref:`switch statements +`. If you know that an argument is of an enumeration +type, you can make ``case`` statements for all of that type's possible +values, so you know you won't miss anything:: + + void describeWeather(weather currentWeather) { + switch(currentWeather) { + case HOT: + SerialUSB.println("it's hot out"); + break; + case COMFY: + SerialUSB.println("it's nice today"); + break; + case COLD: + SerialUSB.println("it's freezing!"); + break; + } + } + +Such a ``switch`` statement would need no :ref:`default +`, since we know that ``currentWeather`` must +be either ``HOT``, ``COMFY``, or ``COLD``. + +See Also +-------- + +- :ref:`lang-switchcase` diff --git a/docs/source/lang/cpp/float.rst b/docs/source/lang/cpp/float.rst new file mode 100644 index 0000000..6937c8c --- /dev/null +++ b/docs/source/lang/cpp/float.rst @@ -0,0 +1,50 @@ +.. highlight:: cpp + +.. _lang-float: + +``float`` +========= + +Single-precision floating point number. Occupies 4 bytes. On Maple, +the ``float`` type has a range of approximately -3.40282×10^38 to +3.40282×10^38; the ``float`` type is subject to the same +:ref:`overflow issues ` as any numeric data +type. + +``float``\ s have only 6-7 decimal digits of precision. That means the +total number of digits, not the number to the right of the decimal +point. You can get more precision by using a :ref:`double +` (which has a precision of about 16 decimal digits). + +The following example declares a ``float`` value named ``myfloat``:: + + float myfloat; + +This example declares a ``float`` value named ``sensorCalibrate``, +with value 1.117:: + + float sensorCalibrate = 1.117; + +The general syntax for declaring a float named ``var`` with value +``val`` is:: + + float var = val; + +Here is a more extended example involving a :ref:`float cast +`:: + + int x; + int y; + float z; + + x = 1; + y = x / 2; // y now contains 0, ints can't hold fractions + z = float(x) / 2; // z now contains .5 + +See Also +-------- + +- :ref:`double ` +- :ref:`Variables ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/floatcast.rst b/docs/source/lang/cpp/floatcast.rst new file mode 100644 index 0000000..4766478 --- /dev/null +++ b/docs/source/lang/cpp/floatcast.rst @@ -0,0 +1,28 @@ +.. highlight:: cpp + +.. _lang-floatcast: + +``float()`` (cast) +================== + +Converts a value to the :ref:`float ` data type. Here is +an example (see the :ref:`constants reference ` for +an explanation of the "2.0f"):: + + int x = 2; + float f = float(x); // f now holds 2.0f, a float value + +The value ``x`` can be of any type. However, if ``x`` is not a number +(like an ``int``), you will get strange results. + +See the :ref:`float ` reference for details about the +precision and limitations of ``float`` values on the Maple. + +See Also +-------- + +- :ref:`float ` +- :ref:`double ` +- :ref:`double() ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/for.rst b/docs/source/lang/cpp/for.rst new file mode 100644 index 0000000..71c5aca --- /dev/null +++ b/docs/source/lang/cpp/for.rst @@ -0,0 +1,142 @@ +.. highlight:: cpp + +.. _lang-for: + +``for`` +======= + +A ``for`` loop is used to repeat a block of statements enclosed in +curly braces. ``for`` loops are useful for performing repetitive +operations, and are often used in combination with :ref:`arrays +` to operate on collections of data or multiple +:ref:`pins `. A ``for`` loop is composed of two parts: first, a +*header*, which sets up the for loop, and then a *body*, which is made +up of lines of code enclosed in curly braces. + +.. contents:: Contents + :local: + +Syntax +------ + +There are three parts to the ``for`` loop header: an *initialization* +expression, *loop condition* expression, and a *post-loop* +expression. The general syntax looks like this:: + + for (initialization; condition; post-loop) { + // all of these lines inside the curly braces are part + // of the loop body. + statement 1; + statement 2; + ... + } + +(Note that there is no semicolon after the post-loop). The +initialization happens first and exactly once, before the loop begins. +Each time through the loop, the condition is tested. The condition is +a :ref:`boolean ` expression. If it is true, then the +list of statements inside the curly braces are executed. Next, the +post-loop is executed. The loop then begins again by evaluating the +condition again, entering the loop body if it is true. This proceeds +until the condition becomes false. + +Examples +-------- + +Here's an example:: + + // Dim an LED using a PWM pin + int pwmPin = 9; // LED in series with 470 ohm resistor on pin 9 + + void setup() { + pinMode(pwmPin, PWM); + } + + void loop() { + for (int i=0; i <= 65535; i++) { + pwmWrite(pwmPin, i); + delay(1); + } + } + +There is a ``for`` loop In the :ref:`loop() ` function of +the above example. This loop starts by declaring an ``int`` variable +named ``i``, whose value starts out at zero. The loop proceeds by +checking if ``i`` is less than or equal to 65535. Since ``i`` is +zero, this is true, and so the calls to :ref:`pwmWrite() +` and :ref:`delay() ` happen next. At this +point, the post-loop expression ``i++`` is evaluated, which +:ref:`increments ` ``i``, so that ``i`` becomes one. +That concludes the first time through the loop. Each "time through +the loop" is referred to as an *iteration*. + +The loop then jumps back to the beginning, checking the condition as +the beginning of its second iteration (initialization is skipped, +since this only happens once, before the first iteration). One is +less than 65535, so the loop statements are executed again. This +proceeds over and over until the iteration when ``i`` finally +reaches 65536. At that point, the condition is no longer true, so the +loop stops executing, and the ``loop()`` function returns. + +Here's another example, using a ``for`` loop to brighten and fade an +LED (see the :ref:`pwmWrite() ` reference for more +information):: + + int pwmPin = 9; // hook up the LED to pin 9 + void loop() { + int x = 1; + for (int i = 0; i >= 0; i += x) { + analogWrite(pwmPin, i); // controls the brightness of the LED + if (i == 65535) { + x = -1; // switch direction, so i starts decreasing + } + delay(1); + } + } + +Coding Tips +----------- + +The C ``for`` loop is more flexible than ``for`` loops found in some +other computer languages, including BASIC. Any or all of the three +header elements may be left blank, although the semicolons are +required. Also the statements for initialization, condition, and +post-loop can be any valid C statements, and use any C datatypes, +including :ref:`floating point numbers `. These types +of unusual ``for`` loops sometimes provide solutions to less-common +programming problems. + +For example, using a multiplication in the post-loop line will +generate a `geometric progression +`_:: + + for(int x = 1; x <= 100; x = x * 2) { + SerialUSB.println(x); + } + + +This loop prints out the numbers 1, 2, 4, 8, ..., 64. Check +your understanding of ``for`` loops by answering the following two +questions (answers are in footnote [#fanswers]_\ ): + +1. How many iterations occur before the loop finishes? + +2. Why does it stop at 64? + +See also +-------- + +- :ref:`while ` loops +- :ref:`do ` loops + +.. rubric:: Footnotes + +.. [#fanswers] + 1. Seven. + + 2. After the seventh iteration, the post-loop causes ``x`` to + equal 128. This is larger than 100, so the loop condition is + false, and the loop stops. + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/goto.rst b/docs/source/lang/cpp/goto.rst new file mode 100644 index 0000000..ff2f248 --- /dev/null +++ b/docs/source/lang/cpp/goto.rst @@ -0,0 +1,130 @@ +.. highlight:: cpp + +.. _lang-goto: + +Labels and ``goto`` +=================== + +A *label* gives a name to a line of code within a function. You can +label a line by writing a name for it, then a colon (``:``), before +the line starts. The ``goto`` keyword allows program flow to transfer +to a labeled line from anywhere within the same function. + +.. warning:: The use of ``goto`` is discouraged in C and C++ + programming. It is *never necessary* to use ``goto`` to write a + program. + + Unless you know what you're doing, using ``goto`` tends to + encourage code which is harder to debug and understand than + programs without ``goto`` that do the same thing. That said, + however, it's sometimes useful; :ref:`see below ` + for a concrete example. + +Using Labels and goto +--------------------- + +Labels and ``goto`` are probably best explained through example. +Let's start with an example of how to label lines. The first line +(``int x = analogRead(some_pin);``) in the :ref:`loop ` +function below has label ``readpin``. The third line (``delay(x);``) +has label ``startdelay``. The second line (``SerialUSB.println(x);``) +does not have a label:: + + void loop() { + readpin: + int x = analogRead(some_pin); + SerialUSB.println(x); // for debugging + startdelay: + delay(x); + // ... more code ... + } + +Anything which can be a :ref:`variable ` name can +be a label. + +Let's say that we wanted to print ``x`` only if it was very large, say +at least 2000. We might want to do this just so anybody watching on a +:ref:`serial monitor ` would know they were in for +a longer wait than usual. We can accomplish this through the use of a +``goto`` statement that skips the printing if ``x`` is less than +2000:: + + void loop() { + readpin: + int x = analogRead(some_pin); + if (x < 2000) { + goto startdelay; + } + SerialUSB.println(x); // for debugging + startdelay: + delay(x); + // ... more code ... + } + +In this modified program, whenever ``x`` is less than 2000, the body +of the :ref:`if ` statement in the second line is +executed. The ``goto`` statement inside the ``if`` body skips +straight to the line labeled ``startdelay``, passing over the line +doing the printing. + +A ``goto`` does not have to "move forwards"; it can go "backwards", +too. For example, the following program prints "5" forever (why?):: + + void loop() { + printfive: + SerialUSB.println(5); + goto printfive; + SerialUSB.println(6); + } + +.. _goto-when-to-use: + +When to Use goto +---------------- + +As mentioned above, use of ``goto`` is `generally discouraged +`_. However, +when used with care, ``goto`` can simplify certain programs. One +important use case for ``goto`` is breaking out of deeply nested +:ref:`for ` loops or :ref:`if ` logic blocks. +Here's an example:: + + for(int r = 0; r < 255; r++) { + for(int g = 255; g > -1; g--) { + for(int b = 0; b < 255; b++) { + if (analogRead(0) > 250) { + goto bailout; + } + // more statements ... + } + // innermost loop ends here + } + } + bailout: + // more code here + +In the above example, whenever the :ref:`analog reading +` on pin 0 was greater than 250, the program would +jump to the line labeled ``bailout``, exiting all three loops at once. + +While there is already a :ref:`break ` keyword for +breaking out of a loop, it will only break out of the *innermost* +loop. So, if instead of saying "``goto bailout;``", there was a +"``break;``" instead, the program would only exit from the loop with +header "``for(int b = 0; b < 255; b++)``". The program would continue +at the line which reads "``// innermost loop ends here``", which is +clearly undesirable if you wanted to leave all three loops at once. + +More examples of when ``goto`` is a good choice are given in Donald +Knuth's paper, "Structured Programming with go to Statements"; see +below for a link. + +See Also +-------- + +- Dijkstra, Edsger W. `Go To Statement Considered Harmful `_ (PDF) + +- Knuth, Donald. `Structured Programming with go to Statements `_ (PDF) + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/if.rst b/docs/source/lang/cpp/if.rst new file mode 100644 index 0000000..bef89e2 --- /dev/null +++ b/docs/source/lang/cpp/if.rst @@ -0,0 +1,121 @@ +.. highlight:: cpp + +.. _lang-if: + +``if``/``else`` +=============== + +An ``if`` statement is used to execute code when certain conditions +are met. The general syntax for an ``if`` statement is:: + + if (condition) { + body + } + +An ``if`` statement first tests whether its *condition* is true (such +as an input being above a certain number). If the condition is true, +the ``if`` statement executes its *body*, which is made up of lines of +code inside :ref:`curly braces `. If the condition +is false, the body is not executed. Here's a more concrete example:: + + if (someVariable > 50) { + // do something here + } + +The program tests to see if ``someVariable`` is greater than 50. If it +is, the program executes every line in the curly braces (which in the +above example does nothing, since the body is just the :ref:`comment +` line "``// do something here``"). + +Put another way, if the statement in parentheses is true, the +statements inside the braces are run. If not, the program skips over +the code. + +An ``if`` statement's condition (which is inside the parentheses after +``if``) often uses one or more :ref:`boolean ` or +:ref:`comparison ` operators. + +Writing the if Body +------------------- + +The brackets may be omitted after an ``if`` statement's +conditional. If this is done, the next line (which ends in a +semicolon) becomes the only line in the body. The following three +``if`` statements all do the same thing:: + + if (x > 120) digitalWrite(ledPin, HIGH); + + if (x > 120) + digitalWrite(ledPin, HIGH); + + if (x > 120) { + digitalWrite(ledPin, HIGH); + } + +However, the following two examples are different:: + + // example 1: two lines of code in the if body + if (x > 120) { + digitalWrite(ledPin1, HIGH); + digitalWrite(ledPin2, HIGH); + } + + // example 2: one line of code in the if body, and + // another line of code after the if statement + if (x > 120) + digitalWrite(ledPin1, HIGH); // this is in the if body + digitalWrite(ledPin2, HIGH); // this is NOT in the if body + +In the first example, since the body is enclosed in curly braces, both +lines are included. In the second example, since the curly braces are +missing, only the first line is in the ``if`` body. + +``else`` +-------- + +``if``/\ ``else`` allows greater control over the flow of code than +the basic :ref:`if ` statement, by allowing multiple tests to +be grouped together. For example, an :ref:`analog input +` could be tested, with one action taken if the input +was less than 500, and another action taken if the input was 500 or +greater. The code would look like this:: + + if (pinFiveInput < 500) { + // action A + } else { + // action B + } + +``else`` can precede another ``if`` test, so that multiple, mutually +exclusive tests can be run at the same time. + +Each test will proceed to the next one until a true test is +encountered. When a true test is found, its associated block of code +is run, and the program then skips to the line following the entire +if/else construction. If no test proves to be true, the default +``else`` block is executed, if one is present, and sets the default +behavior. + +Note that an ``else if`` block may be used with or without a +terminating ``else`` block, and vice-versa. An unlimited number of +such ``else if`` branches is allowed. Here is a code example:: + + if (pinFiveInput < 500) { + // do Thing A + } else if (pinFiveInput >= 1000) { + // do Thing B + } else { + // do Thing C + } + +Another way to express branching, mutually exclusive tests, is with a +:ref:`switch/case ` statement. + + +See Also +-------- + +- :ref:`boolean operators ` +- :ref:`comparison operators ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/include.rst b/docs/source/lang/cpp/include.rst new file mode 100644 index 0000000..74fe7af --- /dev/null +++ b/docs/source/lang/cpp/include.rst @@ -0,0 +1,72 @@ +.. highlight:: cpp + +.. _lang-include: + +``#include`` +============ + +``#include`` is used to include outside libraries in your sketch. +This gives the programmer access to a large group of standard C +libraries (groups of pre-made functions and data types), and also +libraries written especially for Maple. + +Example +------- + +This example (from the `Arduino LiquidCrystal Tutorial +`_) includes a library +that is used to control :ref:`LCD displays +`:: + + // include the library code: + #include + + // initialize the library with the numbers of the interface pins + LiquidCrystal lcd(12, 11, 5, 4, 3, 2); + + void setup() { + // set up the LCD's number of columns and rows: + lcd.begin(16, 2); + // Print a message to the LCD. + lcd.print("hello, world!"); + } + + void loop() { + // set the cursor to column 0, line 1 + // (note: line 1 is the second row, since counting begins with 0): + lcd.setCursor(0, 1); + // print the number of seconds since reset: + lcd.print(millis()/1000); + } + +Note that a ``#include`` line, like :ref:`#define `, +has **no semicolon**. The compiler will print strange error messages +if you add one. + +C Standard Library +------------------ + +The standard C library that comes with Maple is called `newlib +`_. Its main sources of documentation +are its `main reference `_ +page and its `math functions +`_ reference page. Here's an +example that imports the math.h library in order to take the `cube +root `_ of a number:: + + #include + + void setup() { + // no setup necessary + } + + void loop() { + // "cbrt" stands for "cube root" + double cubeRootOf3 = cbrt(3.0); + // prints a number that is approximately the cube root of 3: + SerialUSB.println(cubeRootOf3); + } + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/increment.rst b/docs/source/lang/cpp/increment.rst new file mode 100644 index 0000000..6dffa80 --- /dev/null +++ b/docs/source/lang/cpp/increment.rst @@ -0,0 +1,37 @@ +.. highlight:: cpp + +.. _lang-increment: + +Increment and Decrement Operators (``++``, ``--``) +================================================== + +These operators increment (add one to) or decrement (subtract one +from) a variable. If they come before the variable, they return its +new value; otherwise, they return its old value. + +Some quick examples:: + + x++; // adds one to x, and returns the old value of x + ++x; // adds one to x, and returns the new value of x + + x--; // decrement x by one and returns the old value of x + --x; // decrement x by one and returns the new value of x + +A more extended example:: + + x = 2; + y = ++x; // x now contains 3, y contains 3 + y = x--; // x contains 2 again, y still contains 3 + +.. warning:: Be careful! You cannot put a space in between the two + ``+`` or ``-`` signs. This example is broken:: + + // this line won't compile (notice the extra space): + int y = x+ +; + +See Also +-------- + +- :ref:`lang-compoundarithmetic` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/int.rst b/docs/source/lang/cpp/int.rst new file mode 100644 index 0000000..ca75f75 --- /dev/null +++ b/docs/source/lang/cpp/int.rst @@ -0,0 +1,64 @@ +.. highlight:: cpp + +.. _lang-int: + +``int`` +======= + +The ``int`` data type represents integers. Integers are your primary +data type for number storage, and store a 4 byte value. This yields a +range of -2,147,483,648 to 2,147,483,647 (minimum value of -2^31 and a +maximum value of (2^31) - 1; that's about negative 2 billion to +positive 2 billion). + +An ``int`` stores a negative number with a technique called `two's +complement math +`_\ . +The highest bit in an ``int``, sometimes refered to as the "sign" bit, +flags the number as a negative number. (See the linked article on +two's complement for more information). + +The Maple takes care of dealing with negative numbers for you, so that +arithmetic operations work mostly as you'd expect. There can be an +:ref:`unexpected complication ` in +dealing with the :ref:`bitshift right operator (>>) +`, however. + +Here is an example of declaring an ``int`` variable named ``ledPin``, +then giving it value 13:: + + int ledPin = 13; + +The general syntax for declaring an ``int`` variable named ``var``, +then giving it value ``val``, looks like:: + + int var = val; + +.. _lang-int-overflow: + +Integer Overflow +---------------- + +When ``int`` variables leave the range specified above, they +:ref:`roll over ` in the other direction. +Here are some examples:: + + int x; + x = -2,147,483,648; + x--; // x now contains 2,147,483,647; rolled over "left to right" + + x = 2,147,483,647; + x++; // x now contains -2,147,483,648; rolled over "right to left" + +See Also +-------- + +- :ref:`unsigned int ` +- :ref:`char ` +- :ref:`unsigned char ` +- :ref:`long ` +- :ref:`unsigned long ` +- :ref:`Integer Constants ` +- :ref:`Variables ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/intcast.rst b/docs/source/lang/cpp/intcast.rst new file mode 100644 index 0000000..386fe14 --- /dev/null +++ b/docs/source/lang/cpp/intcast.rst @@ -0,0 +1,29 @@ +.. highlight:: cpp + +.. _lang-intcast: + +``int()`` (cast) +================ + +Converts a value to the :ref:`int ` data type. Here is +an example:: + + double d = 2.5; + int i = int(d); // i holds "2", an int value + +The value inside of the parentheses (``int(...)``) can be of any type. +However, if it is not a numeric type (like ``double``, ``char``, +etc.), you will get strange results. + +See the :ref:`int ` reference for details about the +precision and limitations of ``int`` variables on the Maple. + +See Also +-------- + +- :ref:`int ` + + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/keywords.rst b/docs/source/lang/cpp/keywords.rst new file mode 100644 index 0000000..e4ebe99 --- /dev/null +++ b/docs/source/lang/cpp/keywords.rst @@ -0,0 +1,205 @@ +.. _lang-keywords: + +Keywords +======== + +This page lists all of the C++ keywords, and either links to a +reference page explaining their use, or provides a brief description. + +List of Keywords +---------------- + +The C++ keywords are: + +``and``, ``and_eq``, ``asm``, ``auto``, ``bitand``, ``bitor``, +``bool``, ``break``, ``case``, ``catch``, ``char``, ``class``, +``compl``, ``const``, ``const_cast``, ``continue``, ``default``, +``delete``, ``do``, ``double``, ``dynamic_cast``, ``else``, ``enum``, +``explicit``, ``export``, ``extern``, ``false``, ``float``, ``for``, +``friend``, ``goto``, ``if``, ``inline``, ``int``, ``long``, +``mutable``, ``namespace``, ``new``, ``not``, ``not_eq``, +``operator``, ``or``, ``or_eq``, ``private``, ``protected``, +``public``, ``register``, ``reinterpret_cast``, ``return``, ``short``, +``signed``, ``sizeof``, ``static``, ``static_cast``, ``struct``, +``switch``, ``template``, ``this``, ``throw``, ``true``, ``try``, +``typedef``, ``typeid``, ``typename``, ``union``, ``unsigned``, +``using``, ``virtual``, ``void``, ``volatile``, ``wchar_t``, +``while``, ``xor``, ``xor_eq`` + +Boolean Operator Synonyms +------------------------- + +- ``and`` is a synonym for :ref:`&& `. +- ``not`` is a synonym for :ref:`\! `. +- ``not_eq`` is a synonym for :ref:`\!= `. +- ``or`` is a synonym for :ref:`|| `. + +Bitwise Operator Synonyms +------------------------- + +- ``and_eq`` is a synonym for :ref:`&= `. +- ``bitand`` is a synonym for (bitwise) :ref:`& `. +- ``bitor`` is a synonym for :ref:`\| `. +- ``compl`` is a synonym for :ref:`~ `. +- ``or_eq`` is a synonym for :ref:`|= `. +- ``xor`` is a synonym for :ref:`^ `. +- ``xor_eq`` is a synonym for :ref:`^= `. + +Constants +--------- + +- ``true`` and ``false`` are the :ref:`boolean constants + `. + +Control Flow +------------ + +- ``break`` can exit out of a :ref:`switch statement + ` or a :ref:`for `, :ref:`do + `, or :ref:`while ` loop. + +- ``case`` defines alternatives in a :ref:`switch statement `. + +- ``continue`` will move control flow to the next iteration of the + enclosing :ref:`for `, :ref:`do `, or + :ref:`while ` loop. + +- ``default`` defines the default alternative in a :ref:`switch + statement `. + +- ``do`` introduces a :ref:`do ` loop. + +- ``else`` is used in :ref:`if statements `. + +- ``for`` introduces a :ref:`for ` loop. + +- ``goto`` :ref:`jumps ` to a label. + +- ``if`` introduces an :ref:`if statement `. + +- ``return`` :ref:`transfers flow to a function's caller `. + +- ``switch`` introduces a :ref:`switch statement `. + +- ``while`` introduces a :ref:`while ` loop. + +Types +----- + +The following keywords are used for built-in types. + +- :ref:`bool ` +- :ref:`lang-char` +- :ref:`lang-double` +- :ref:`lang-float` +- :ref:`lang-int` +- :ref:`lang-long` +- :ref:`short ` +- :ref:`void ` (not really a type, but used in the absence + of one) + +The following keywords are used to introduce new types. + +- :ref:`enum ` + +Qualifiers +---------- + +- :ref:`static ` can be used to declare persistent local + variables; it has other uses not documented here. + +- ``unsigned`` is used to specify an unsigned integral type. + Examples: :ref:`lang-unsignedint`, :ref:`lang-unsignedchar`, + :ref:`lang-unsignedlong`. + +- :ref:`volatile ` is useful when declaring variables + that may be modified by external interrupts. + +- :ref:`const ` is used to define constants. + +Other +----- + +These keywords are not described in the Maple documentation. For more +information, consult a C++ reference. + +- ``asm`` is used to insert literal assembly language. + +- ``auto`` is used to declare that a variable has automatic storage. + +- ``catch`` is used in exception handling. Note that the default + flags we pass to :ref:`GCC ` include ``-fno-exceptions``. + +- ``class`` is used to define classes. + +- ``const_cast`` is used in typecasting. + +- ``delete`` is used to free ``new``\ -allocated storage. Note that + dynamic memory allocation is not available by default on the Maple, + so you'll have to bring your own ``new`` and ``delete`` if you want + this. + +- ``dynamic_cast`` is used in typecasting. + +- ``explicit`` is used to declare constructors that can be called only + explicitly. + +- ``export`` declares a template definition accessible to other + compilation units. + +- ``extern`` can mark a declaration as a declaration and not a + definition, and also grant external linkage to a ``const`` or + ``typedef``. + +- ``friend`` is used to declare that certain functions have access to + a class's private variables. + +- ``inline`` is a compiler hint to inline a function. + +- ``mutable`` specifies that a member can be updated, even when a + member of a ``const`` object. + +- ``namespace`` declares a new namespace. + +- ``new`` dynamically allocates space for a value. Note that dynamic + memory allocation is not available by default on the Maple, so + you'll have to bring your own ``new`` and ``delete`` if you want + this. + +- ``operator`` is used to define type-specific operator overrides. + +- ``private`` declares a private class member. + +- ``protected`` declares a protected class member. + +- ``public`` declares a public class member. + +- ``register`` is a compiler hint to store a variable in a register. + +- ``reinterpret_cast`` is used in typecasting. + +- ``signed`` is the opposite of ``unsigned``. + +- ``static_cast`` is used in typecasting. + +- ``struct`` declares a new struct. + +- ``template`` introduces a template class, function, etc. + +- ``this`` is a pointer to the receiver object. + +- ``throw`` is used in exception handling. Note that the default + flags we pass to :ref:`GCC ` include ``-fno-exceptions``. + +- ``try`` is used in exception handling. Note that the default + flags we pass to :ref:`GCC ` include ``-fno-exceptions``. + +- ``typedef`` defines a type synonym. + +- ``union`` defines an untagged union. + +- ``using`` is a directive related to namespaces. + +- ``virtual`` declares a method which may be overridden. + +- ``wchar_t`` is the wide character type. diff --git a/docs/source/lang/cpp/long.rst b/docs/source/lang/cpp/long.rst new file mode 100644 index 0000000..d8498c0 --- /dev/null +++ b/docs/source/lang/cpp/long.rst @@ -0,0 +1,52 @@ +.. highlight:: cpp + +.. _lang-long: + +``long`` +======== + +The ``long`` data type stores extended size integer values. You can +use a ``long`` when your values are too large to fit into an :ref:`int +`. A ``long`` occupies 8 bytes of memory. This yields a +range of approximately -9.2×10^18 to 9.2×10^18 (that's 9.2 billion +billion, or about 92 million times the number of stars in the Milky +Way galaxy). The exact range of a ``long`` on the Maple is from +-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807, or -2^63 to +(2^63-1). A ``long`` it is subject to the same :ref:`overflow issues +` as any numeric data type. + +Here's an example of declaring a long (see :ref:`integer constants +` for an explanation of the "L" at the end of the +number):: + + // Speed of light in nanometers per second (approximate). + long c = 299792458000000000L; + +The general syntax for declaring an ``long`` variable named ``var``, +then giving it value ``val``, looks like:: + + long var = val; + +This is identical to the ``int`` syntax, with ``long`` replacing +``int``. + +Note that ``long`` values will still :ref:`overflow +`, just like ``int`` values, but their much +larger range makes this less likely to happen. + +The downside to using a ``long`` instead of an ``int`` (besides the +extra storage) is that :ref:`arithmetic ` operations +on ``long``\ s will take slightly longer than on ``int``\ s. + +See Also +-------- + +- :ref:`char ` +- :ref:`unsigned char ` +- :ref:`int ` +- :ref:`unsigned int ` +- :ref:`unsigned long ` +- :ref:`Integer Constants ` +- :ref:`Variables ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/longcast.rst b/docs/source/lang/cpp/longcast.rst new file mode 100644 index 0000000..2b92345 --- /dev/null +++ b/docs/source/lang/cpp/longcast.rst @@ -0,0 +1,27 @@ +.. highlight:: cpp + +.. _lang-longcast: + +``long()`` (cast) +================= + +Converts a value to the :ref:`long ` data type. Here is +an example:: + + double d = 2.5; + long i = long(d); // i holds "2L", an long value + +The value inside of the parentheses (``long(...)``) can be of any type. +However, if it is not a numeric type (like ``double``, ``char``, +etc.), you will get strange results. + +See the :ref:`long ` reference for details about the +precision and limitations of ``long`` variables on the Maple. + +See Also +-------- + +- :ref:`long ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/modulo.rst b/docs/source/lang/cpp/modulo.rst new file mode 100644 index 0000000..289fba0 --- /dev/null +++ b/docs/source/lang/cpp/modulo.rst @@ -0,0 +1,70 @@ +.. highlight:: cpp + +.. _lang-modulo: + +Modulo Operator (``%``) +======================= + +Calculates the `remainder `_ +when one integer is divided by another. It is useful for keeping a +variable within a particular range (e.g. the size of an array). + +Syntax +------ + +:: + + dividend % divisor + +Parameters +---------- + +**dividend**: the number to be divided + +**divisor**: the number to divide by + +Returns +------- + +The remainder of **dividend**\ /\ **divisor**\ . + +Examples +-------- + +:: + + int x; + x = 7 % 5; // x now contains 2 + x = 9 % 5; // x now contains 4 + x = 5 % 5; // x now contains 0 + x = 4 % 5; // x now contains 4 + +:: + + /* update one value in an array each time through a loop */ + + int values[10]; + int i = 0; + + void setup() { + // no setup necessary + } + + void loop() { + values[i] = analogRead(0); + i = (i + 1) % 10; // modulo operator makes sure i stays between 0 and 9 + } + +Tip +--- + +The modulo operator does not work on floats. For that, you can use +the C standard library function `fmod() +`_. + +See Also +-------- + +- :ref:`Arithmetic ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/numeric-types.rst b/docs/source/lang/cpp/numeric-types.rst new file mode 100644 index 0000000..9d2be48 --- /dev/null +++ b/docs/source/lang/cpp/numeric-types.rst @@ -0,0 +1,79 @@ +.. _lang-numeric-types: + +Numeric types +============= + +This document serves as a reference for all of the built-in numeric +types which are available when programming in the IDE. Programmers +using the :ref:`command-line tools ` will have access +to these types as long as they have imported ``wirish.h``; several are +defined in in `libmaple_types.h +`_. + +.. _lang-numeric-types-integral: + +Integral types +-------------- + +.. cpp:type:: char + + 8-bit integer value. + +.. cpp:type:: short + + 16-bit integer value. + +.. cpp:type:: int + + 32-bit integer value. + +.. cpp:type:: long + + 64-bit integer value. + +.. cpp:type:: long long + + 64-bit integer value. + +.. cpp:type:: int8 + + Synonym for ``char``. + +.. cpp:type:: uint8 + + Synonym for ``unsigned char``. + +.. cpp:type:: int16 + + Synonym for ``short``. + +.. cpp:type:: uint16 + + Synonym for ``unsigned short``. + +.. cpp:type:: int32 + + Synonym for ``int``. + +.. cpp:type:: uint32 + + Synonym for ``unsigned int`` + +.. cpp:type:: int64 + + Synonym for ``long long`` + +.. cpp:type:: uint64 + + Synonym for ``unsigned long long``. + +Floating-Point Types +-------------------- + +.. cpp:type:: float + + 32-bit, IEEE 754 single-precision floating-point type. + +.. cpp:type:: double + + 64-bit, IEEE 754 double-precision floating-point type. diff --git a/docs/source/lang/cpp/pointer.rst b/docs/source/lang/cpp/pointer.rst new file mode 100644 index 0000000..0a42270 --- /dev/null +++ b/docs/source/lang/cpp/pointer.rst @@ -0,0 +1,31 @@ +.. _lang-pointer: + +Pointer Operators (``&``, ``*``) +================================ + +The pointer operators ``&`` (reference) and ``*`` (dereference) are +different from the bitwise math operator :ref:`& +` and the arithmetic operator :ref:`* +`. + +Pointers are one of the more complicated subjects for beginners in +learning C, and it is possible to write many useful Arduino sketches +without ever encountering pointers. However, for manipulating certain +data structures, the use of pointers can simplify the code, improve +its efficiency, and generally provide many benefits that would be +difficult to achieve without the use of pointers. + +Introducing pointers is somewhat outside the scope of this +documentation. However, a good `pointer tutorial +`_ is available. +Also see the `Wikipedia article on pointers +`_, especially +the section on `pointers in C +`_. + +See Also +-------- + +- http://xkcd.com/138/ + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/return.rst b/docs/source/lang/cpp/return.rst new file mode 100644 index 0000000..7b5039e --- /dev/null +++ b/docs/source/lang/cpp/return.rst @@ -0,0 +1,61 @@ +.. highlight:: cpp + +.. _lang-return: + +``return`` +========== + +Terminates a function and return a value from a function to the +calling function, if the function has non-``void`` return type. + +Syntax: +------- + +:: + + // from within a "void" function: + return; + + // from within a non-"void" function: + return value; + +In the second case, ``value`` should have a type which is the same as +the return type of the function, or be convertible to it (like an +``int`` to a ``long``, etc.; see :ref:`this note +` for some references). + +Examples: +--------- + +A function to compare a sensor input to a threshold:: + + // converts analog readings between 0 and 400 to 0, and 400 up to 1. + int checkSensor() { + if (analogRead(0) > 400) { + return 1; + else { + return 0; + } + } + +An early ``return`` is also useful when testing a section of code +without having to "comment out" large sections of possibly buggy code, +like so:: + + void loop() { + + // brilliant code idea to test here + + return; + + // the rest of a dysfunctional sketch here + // this code will never be executed + } + +See Also +-------- + +- :ref:`comments ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/scope.rst b/docs/source/lang/cpp/scope.rst new file mode 100644 index 0000000..7b65bab --- /dev/null +++ b/docs/source/lang/cpp/scope.rst @@ -0,0 +1,120 @@ +.. highlight:: cpp + +.. _lang-scope: + +Scope +===== + +Variables in the C++ programming language, which Maple uses (all of +your sketches are C++ programs in disguise), have a property called +*scope*. Simply put, a variable's scope is made up of all of the +lines where the variable can be used. + +Scope in C++ is a fairly complex topic, so we won't try to describe it +in full here. Instead, we present a simplified view, describing two +different kinds of scopes, *global* and *local*. For more detailed +information, consult a C++ reference. + +Global and Local Variables +-------------------------- + +A global variable is one that can be "seen" by every function in a +program. In the :ref:`Maple IDE `, any variable declared outside +of a function (like :ref:`setup() ` and :ref:`loop() +`) is a global variable. + +A local variable can only be "seen" inside of a particular function. +You can declare a variable to be local to a function by declaring it +inside of the :ref:`curly braces ` which enclose +that function. + +When programs start to get larger and more complex, local variables +are a useful way to ensure that a function has exclusive access to its +own variables. This prevents programming errors when one function +mistakenly modifies variables used by another function. + +It is also sometimes useful to declare and initialize a variable +inside a :ref:`for ` loop. This creates a variable that +can only be accessed from inside the loop body. + +Example +------- + +Here is an example sketch (which you can copy into the Maple IDE and +run on your Maple) that illustrates the use of global and local +variables, as well as declaring variables inside of a ``for`` loop. +Be sure to open a :ref:`serial monitor ` after you +:ref:`verify ` and :ref:`upload ` the sketch:: + + int globalVar; // any function will see this variable + + void setup() { + // since "globalVar" is declared outside of any function, + // every function can "see" and use it: + globalVar = 50; + + // the variables "i" and "d" declared inside the "loop" function + // can't be seen here. see what happens when you uncomment the + // following lines, and try to Verify (compile) the sketch: + // + // i = 16; + // SerialUSB.print("i = "); + // SerialUSB.println(i); + // d = 26.5; + // SerialUSB.print("d = "); + // SerialUSB.println(d); + } + + void loop() { + // since "i" and "d" are declared inside of the "loop" function, + // they can only be seen and used from inside of it: + int i; + double d; + + for (int j = 0; j < 5; j++) { + // variable i can be used anywhere inside the "loop" function; + // variable j can only be accessed inside the for-loop brackets: + i = j * j; + SerialUSB.print("i = "); + SerialUSB.println(i); + } + + // globalVar can be accessed from anywhere. note how even + // though we set globalVar = 50 in the "setup" function, we can + // see that value here: + SerialUSB.print("globalVar = "); + SerialUSB.println(globalVar); + + // d can be accessed from anywhere inside the "loop" function: + d = 26.5; + SerialUSB.print("d = "); + SerialUSB.print(d); + SerialUSB.println(" (before separateFunction())"); + + separateFunction(); + + // notice how even though separateFunction() has a variable + // named "d", it didn't touch our (local) variable which has + // the same name: + SerialUSB.print("d = "); + SerialUSB.print(d); + SerialUSB.println(" (after separateFunction())"); + } + + void separateFunction() { + // variable "d" here has the same name as variable "d" inside of + // the "loop" function, but since they're both _local_ + // variables, they don't affect each other: + double d = 30.5; + SerialUSB.print("d = "); + SerialUSB.print(d); + SerialUSB.println(" (inside of separateFunction())"); + } + +See Also +-------- + +- `C++ programming Wikibook `_. +- Wikipedia article on `scope `_ + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/semicolon.rst b/docs/source/lang/cpp/semicolon.rst new file mode 100644 index 0000000..8164616 --- /dev/null +++ b/docs/source/lang/cpp/semicolon.rst @@ -0,0 +1,25 @@ +.. highlight:: cpp + +.. _lang-semicolon: + +Semicolon (``;``) +================= + +Used to end a line of code. Example:: + + int a = 13; + +Tip +--- + +Forgetting to end a line in a semicolon will result in a compiler +error. The error text may be obvious, and refer to a missing +semicolon, or it may not. If an impenetrable or seemingly illogical +compiler error comes up, one of the first things to check is a +missing semicolon, in the immediate vicinity, preceding the line at +which the compiler complained. + + + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/sizeof.rst b/docs/source/lang/cpp/sizeof.rst new file mode 100644 index 0000000..eae509c --- /dev/null +++ b/docs/source/lang/cpp/sizeof.rst @@ -0,0 +1,64 @@ +.. highlight:: cpp + +.. _lang-sizeof: + +``sizeof()`` +============ + +The ``sizeof`` operator on the Maple returns the number of bytes +needed to store a value of a given type\ [#fcharsize]_. This can be +an ordinary numeric type, like ``int``. It can be something more +complicated, like a ``struct`` or ``union``. If the argument to +``sizeof`` is an array, it returns the total number of bytes occupied +by the array. + +The general syntax looks like this:: + + sizeof(type) + sizeof(var) + +Example +------- + +The ``sizeof`` operator is useful for dealing with arrays (such as +strings) where it is convenient to be able to change the size of the +array without breaking other parts of the program. + +This program prints out a text string one character at a time. Try +changing the text phrase:: + + char myStr[] = "this is a test"; + int i; + + void setup() { + Serial.begin(9600); + } + + void loop() { + for (i = 0; i < sizeof(myStr) - 1; i++) { + Serial.print(i, DEC); + Serial.print(" = "); + Serial.println(myStr[i], BYTE); + } + } + + +Note that ``sizeof`` returns the total number of bytes. So for larger +variable types such as ``int``, the :ref:`for loop ` +would look something like this:: + + for (i = 0; i < (sizeof(myInts)/sizeof(int)) - 1; i++) { + // do something with myInts[i] + } + +.. rubric:: Footnotes + +.. [#fcharsize] Technically (and pedantically) speaking, ``sizeof`` + returns a multiple of the number of bits a ``char`` occupies in + memory. However, on the Maple (this goes for most C++ + implementations), a ``char`` occupies 8 bits = 1 byte. All the C++ + standard guarantees, however, is that a ``char`` occupies at + *least* 8 bits. + +.. include:: cc-attribution.txt + diff --git a/docs/source/lang/cpp/sqrt.rst b/docs/source/lang/cpp/sqrt.rst new file mode 100644 index 0000000..956a754 --- /dev/null +++ b/docs/source/lang/cpp/sqrt.rst @@ -0,0 +1,25 @@ +.. _lang-sqrt: + +sqrt() +====== + +Calculates the square root of a number. + +Library Documentation +--------------------- + +.. doxygenfunction:: sqrt + +Arduino Compatibility +--------------------- + +The Maple versino of ``sqrt()`` is compatible with Arduino. + +See Also +-------- + +- :ref:`pow ` +- :ref:`sq ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/static.rst b/docs/source/lang/cpp/static.rst new file mode 100644 index 0000000..5d1802e --- /dev/null +++ b/docs/source/lang/cpp/static.rst @@ -0,0 +1,57 @@ +.. highlight:: cpp + +.. _lang-static: + +``static`` +========== + +The ``static`` keyword can be used to create variables that are +visible to only one function. However, unlike local variables that get +created and destroyed every time a function is called, ``static`` +variables persist beyond the function call, preserving their data +between function calls. + +Variables declared as ``static`` will only be created and initialized +the first time a function is called. + +.. note:: This is only one use of the ``static`` keyword in C++. It + has some other important uses that are not documented here; consult + a reliable C++ reference for details. + +Example +------- + +One use case for ``static`` variables is implementing counters that +last longer than the functions which need them, but shouldn't be +shared to other functions. Here's an example:: + + void setup() { + SerialUSB.begin(); + } + + void loop() { + int reading; + if (timeToReadSensors()) { + reading = readSensors(); + } + // do something with reading + } + + int readSensors() { + static int numSensorReadings = 0; + numSensorReadings++; + if (numSensorReadings % 100 == 0) { + SerialUSB.print("just got to another 100 sensor readings"); + } + return analogRead(...); + } + +In this example, the static variable ``numSensorReadings`` is +initialized to zero the first time ``readSensors()`` is called, and +then incremented, so it starts out at one. Subsequent calls to +``readSensors()`` won't reset ``numSensorReadings`` to zero, because +it was declared ``static``. Thus, ``numSensorReadings`` is a count of +the number of times that ``readSensors()`` has been called. + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/string.rst b/docs/source/lang/cpp/string.rst new file mode 100644 index 0000000..0a270da --- /dev/null +++ b/docs/source/lang/cpp/string.rst @@ -0,0 +1,128 @@ +.. highlight:: cpp + +.. _lang-string: + +Strings +======= + +Text strings can be represented in two ways. You can + +1. Use the :ref:`String ` data type, which is +part of the core as of version 0.0.9, or + +2. You can make a string out of an array of type :ref:`char +` and null-terminate it. + +This page describes the second method. + +Examples +-------- + +All of the following are valid declarations for strings:: + + char str1[15]; + char str2[6] = {'m', 'a', 'p', 'l', 'e'}; + char str3[6] = {'m', 'a', 'p', 'l', 'e', '\0'}; + char str4[ ] = "maple"; + char str5[6] = "maple"; + char str6[15] = "maple"; + +As you can see, there are several methods available for declaring and +initializing strings: + +- Declare an array of ``char`` without initializing it, as with ``str1``. + +- Declare an array of ``char`` (with one extra ``char``) and the + compiler will add the required null character, as with ``str2``. + +- Explicitly add the null character (``'\0'``), as with ``str3``. + +- Initialize with a string constant in quotation marks (``"..."``); + the compiler will size the array to fit the string constant and a + terminating null character (``str4``). + +- Initialize the array with an explicit size and string constant, + (``str5``). + +- Initialize the array, leaving extra space for a larger string + (``str6``). + +Null Termination +---------------- + +Generally, strings are terminated with a null character (`ASCII +`_ code 0). This allows functions +(like ``SerialUSB.print()``) to tell where the end of a string is. +Otherwise, they would continue reading subsequent bytes of memory that +aren't actually part of the string. + +This means that your string needs to have space for one more character +than the text you want it to contain. That is why ``str2`` and +``str5`` need to be six characters, even though "maple" is only five +-- the last position is automatically filled with a NULL +character. ``str4`` will be automatically sized to six characters, one +for the extra null. In the case of ``str3``, we've explicitly included +the null character (written ``'\0'``) ourselves. + +Note that it's possible to have a string without a final null +character (e.g. if you had specified the length of ``str2`` as five +instead of six). This will break most functions that use strings, so +you shouldn't do it intentionally. If you notice something behaving +strangely (operating on characters not in the string), however, this +could be the problem. + +Single quotes or double quotes? +------------------------------- + +Strings are always defined inside double quotes (``"Abc"``) and +characters are always defined inside single quotes (``'A'``). + +Wrapping long strings +--------------------- + +You can wrap long strings like this:: + + char myString[] = "This is the first line" + " this is the second line" + " etcetera"; + +Arrays of Strings +----------------- + +It is often convenient, when working with large amounts of text, +such as a project with an LCD display, to setup an array of +strings. Because strings themselves are arrays, this is in actually +an example of a two-dimensional array. + +In the code below, the asterisk after the datatype char ``char *`` +indicates that this is an array of "pointers". All array names are +actually pointers, so this is required to make an array of arrays. +Pointers are one of the more esoteric parts of C for beginners to +understand, but it isn't necessary to understand pointers in detail to +use them effectively here:: + + char* myStrings[] = {"This is string 1", "This is string 2", + "This is string 3", "This is string 4", + "This is string 5", "This is string 6"}; + + void setup() { + SerialUSB.begin(); + } + + void loop() { + for (int i = 0; i < 6; i++) { + SerialUSB.println(myStrings[i]); + delay(500); + } + } + + +See Also +-------- + +- :ref:`array ` +- :ref:`__attribute__ ` +- :ref:`Variables ` + + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/switchcase.rst b/docs/source/lang/cpp/switchcase.rst new file mode 100644 index 0000000..b484bc5 --- /dev/null +++ b/docs/source/lang/cpp/switchcase.rst @@ -0,0 +1,118 @@ +.. highlight:: cpp + +.. _lang-switchcase: + +``switch``\ /\ ``case`` +======================= + +Like :ref:`if ` statements, A ``switch`` statement controls +program flow by allowing you to specify different code that should be +executed under various cases. + +The general syntax looks like this:: + + switch (var) { + case val1: + // statements + break; + case val2: + // statements + break; + ... + default: + // statements + } + +Where ``var`` is a variable whose value to investigate, and the +``val1``, ``val2`` after each ``case`` are constant values that +``var`` might be. + +Description +----------- + +A ``switch`` statement compares the value of a variable to the values +specified in ``case`` statements. When a ``case`` statement is found +whose value matches that of the variable, the code in that case +statement is run. + +Here's a more concrete example:: + + switch (var) { + case 1: + doThing1(); + break; + case 2: + doThing2(); + break; + } + afterTheSwitch(); + +In the above example, if ``var == 1``, then the code beginning on the +line after ``case 1`` gets executed. That is, if ``var`` is one, +``doThing1()`` gets called first, and then the ``break`` statement is +executed. + +The ``break`` keyword exits the ``switch`` statement, and is typically +used at the end of each ``case``. Since there is a ``break`` at the +end of ``case 1``, the ``switch`` statement exits, and the next line +to be run is the one which calls ``afterTheSwitch()``. + +Without a ``break``, the ``switch`` statement will continue executing +the following ``case`` expressions ("falling-through") until a +``break`` (or the end of the switch statement) is reached. Let's +pretend the ``switch`` looked like this instead:: + + switch (var) { + case 1: + doThing1(); + // no break statement anymore + case 2: + doThing2(); + break; + } + afterTheSwitch(); + +Now, if ``var`` is one, ``doThing1()`` gets executed like before. +However, without a ``break``, the code would continue to be executed +line-by-line, so ``doThing2()`` would be called next. At this point, +a ``break`` has been reached, so the program continues by calling +``afterTheSwitch()``. This is usually not what you want, which is why +each ``case`` usually has a ``break`` at the end. + +.. _lang-switchcase-default: + +Writing "``default:``" instead of a ``case`` statement allows you to +specify what to do if none of the ``case`` statements matches. Having +a ``default`` is optional (you can leave it out), but if you have one, +it must appear after all of the ``case`` statements. Let's add a +``default`` to the ``switch`` we've been discussing:: + + switch (var) { + case 1: + doThing1(); + break; + case 2: + doThing2(); + break; + default: + doSomethingElse(); + } + afterTheSwitch(); + +If ``var`` is one, then ``doThing1()`` gets called. If ``var`` is +two, ``doThing2()`` gets called. If ``var`` is anything else, +``doSomethingElse()`` gets called. As stated above, a ``default`` is +optional. If you're missing one and none of the ``case`` statements +match, the ``switch`` does nothing at all, as if it weren't there. + +``switch`` statements are often used with an :ref:`enum ` +value as the variable to compare. In this case, you can write down +all of the values the ``enum`` takes as ``case`` statements, and be +sure you've covered all the possibilities. + +See also: +--------- + +- :ref:`if/else ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/unsignedchar.rst b/docs/source/lang/cpp/unsignedchar.rst new file mode 100644 index 0000000..5b946ed --- /dev/null +++ b/docs/source/lang/cpp/unsignedchar.rst @@ -0,0 +1,33 @@ +.. highlight:: cpp + +.. _lang-unsignedchar: + +``unsigned char`` +================= + +An unsigned version of the :ref:`char ` data type. An +``unsigned char`` occupies 1 byte of memory; it stores an integer from +0 to 255. + +Like an :ref:`unsigned int `, an ``unsigned char`` +won't store negative numbers; it is also subject to the same +:ref:`overflow issues ` as any integral data type. + +Example +------- + +:: + + unsigned char c = 240; + +See Also +-------- + + +- :ref:`byte ` +- :ref:`int ` +- :ref:`array ` +- :ref:`SerialUSB.println() ` +- :ref:`Serial.println() ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/unsignedint.rst b/docs/source/lang/cpp/unsignedint.rst new file mode 100644 index 0000000..f6311da --- /dev/null +++ b/docs/source/lang/cpp/unsignedint.rst @@ -0,0 +1,55 @@ +.. highlight:: cpp + +.. _lang-unsignedint: + +``unsigned int`` +================ + +An ``unsigned int`` (unsigned integer) is the same as an :ref:`int +` in that it stores a 4 byte integer value. However, +Instead of storing both negative and positive numbers, an ``unsigned +int`` can only store nonnegative values, yielding a range of 0 to +4,294,967,295 (the positive value is 2^32 - 1). + +The difference between an ``unsigned int`` and a (signed) ``int`` lies +in the way the highest bit, sometimes referred to as the "sign" bit, +is interpreted. In the case of the Maple ``int`` type (which is +signed), if the high bit is a "1", the number is interpreted as a +negative number, using a technique known as `two's complement math +`_. The +bits in an an ``unsigned int`` are interpreted according to the usual +rules for converting `binary to decimal +`_. + +An ``unsigned int`` is subject to the same :ref:`overflow issues +` as a regular ``int``; the only difference is +that an ``unsigned int`` will "underflow" at 0, and "overflow" at +4,294,967,295. Here is some example code which illustrates this:: + + unsigned int x; + x = 0; + x--; // x now contains 4,294,967,295; rolled over "left to right" + x++; // x now contains 0; rolled over "right to left" + +Here is an example of declaring an ``unsigned int`` variable named +``ledPin``, then giving it value 13:: + + unsigned int ledPin = 13; + +The general syntax for declaring an ``unsigned int`` variable named +``var``, then giving it value ``val``, looks like:: + + unsigned int var = val; + +See Also +-------- + +- :ref:`int ` +- :ref:`char ` +- :ref:`unsigned char ` +- :ref:`long ` +- :ref:`unsigned long ` +- :ref:`Integer Constants ` +- :ref:`Variables ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/unsignedlong.rst b/docs/source/lang/cpp/unsignedlong.rst new file mode 100644 index 0000000..14a4fc3 --- /dev/null +++ b/docs/source/lang/cpp/unsignedlong.rst @@ -0,0 +1,41 @@ +.. highlight:: cpp + +.. _lang-unsignedlong: + +``unsigned long`` +================= + +An unsigned version of the :ref:`long ` data type. An +``unsigned long`` occupies 8 bytes of memory; it stores an integer +from 0 to 2^64-1, which is approximately 1.8×10^19 (18 quintillion, or +18 billion billion). + +Like an :ref:`unsigned int `, an ``unsigned long`` +won't store negative numbers; it is also subject to the same +:ref:`overflow issues ` as any integral data type. + +Here is an example of declaring an ``unsigned long`` variable named +``c``, then giving it value 299,792,458,000,000,000 (see :ref:`integer +constants ` for an explanation of the "L" +at the end of the number):: + + // Speed of light in nanometers per second (approximate). + unsigned long c = 299792458000000000L; + +The general syntax for declaring an ``unsigned long`` variable named +``var``, then giving it value ``val``, looks like:: + + unsigned long var = val; + +See Also +-------- + +- :ref:`long ` +- :ref:`int ` +- :ref:`unsigned ` +- :ref:`char ` +- :ref:`unsigned char ` +- :ref:`Integer Constants ` +- :ref:`Variables ` + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/variables.rst b/docs/source/lang/cpp/variables.rst new file mode 100644 index 0000000..9094cd5 --- /dev/null +++ b/docs/source/lang/cpp/variables.rst @@ -0,0 +1,170 @@ +.. highlight:: cpp + +.. _lang-variables: + +Variables +========= + +A variable is a way of naming and storing a value for later use by +the program, such as data from a sensor or an intermediate value +used in a calculation. + +.. contents:: Contents + :local: + +.. _lang-variables-declaring: + +Declaring Variables +------------------- + +Before they are used, all variables have to be *declared*. Declaring a +variable means defining its type, giving it a name, and (optionally) +giving it an initial value (this is often referred to as +*initializing* the variable). Variables do not have to be initialized +(given a value) when they are declared, but it is good style to give +them an initial value whenever possible. + +Here is an example of declaring a variable named ``inputVariable1`` +with type :ref:`int ` (the ``int`` type is used to store +integers, like -2, -1, 0, 1, etc.):: + + int inputVariable1; + +In the above declaration, we did not give the variable an initial +value. Here is another example, where we declare an ``int`` variable +named ``inputVariable2``, with an initial value of ``0``:: + + int inputVariable2 = 0; + +The Maple environment comes ready to use with many useful types of +variables. See the :ref:`built-in types ` page +for more information. + +Here are a few examples of declaring variables of different types:: + + int lightSensVal; + char currentLetter; + unsigned long speedOfLight = 186000UL; + char errorMessage = {"choose another option"}; // see string + +Naming Variables +---------------- + +The rules for naming a variable are simple. Names for variables can +contain letters, numbers, and underscores (the underscore is the +:kbd:`_` character), and cannot begin with a number. So +``temperature_reading``, ``tempReading``, ``tempReading1``, and +``tempReading2`` are all valid variable names, but ``4_temp_readings`` +is not, because it begins with a number. + +You cannot choose a name for a variable that is one of the C++ +:ref:`keywords `. + +Variable names are case-sensitive, so "tempreading" and "tempReading" +are different variables. However, it is very bad style to write code +that chooses variables which are the same up to case. + +You should give your variables descriptive names, so as to make your +code more readable. Variable names like ``tiltSensor`` or +``pushButton`` help you (and anyone else reading your code) understand +what the variable represents. Variable names like ``var`` or +``value``, on the other hand, do little to make your code readable. + +.. _lang-variables-scope: + +Variable Scope +-------------- + +An important choice that programmers face is where (in the program +text) to declare variables. The specific place that variables are +declared influences how various functions in a program will "see" the +variable. This is called variable *scope*. See the :ref:`scope +reference ` for more information. + +.. _lang-variables-initializing: + +Initializing Variables +---------------------- + +Variables may be *initialized* (assigned a starting value) when they +are declared or not. It is always good programming practice however to +double check that a variable has valid data in it before it is used. +Using a variable before you give it a value is a common source of +bugs. + +.. _lang-variables-rollover: + +Variable Rollover +----------------- + +Every (numeric) type has a valid *range*. The range of a type is the +smallest and largest value that a variable of that type can store. +For example, the :ref:`int ` type has a range of +-2,147,483,648 to 2,147,483,647 [#frange]_. + +When variables are made to exceed their range's maximum value, they +"roll over" back to their minimum value. Note that this happens in +both directions. It's like in the game *Pac-Man* -- when Pac-Man goes +past the right edge of the screen, he reappears on the left, and when +he goes past the left side of the screen, he reappears on the right:: + + int x; + x = -2,147,483,648; + x = x - 1; // x now contains -2,147,483,647; rolled over "left to right" + + x = 2,147,483,647; + x = x + 1; // x now contains -2,147,483,648; rolled over "right to left" + +Each numeric type's reference page includes its range. See the +:ref:`built-in types ` reference for links to each +type's reference page. + +Using Variables +--------------- + +Once variables have been declared, they are given values using the +:ref:`assignment operator `, which is a single equals +sign, ``=``. The assignment operator tells the program to store the +value on the right side of the equals sign into the variable on the +left side:: + + inputVariable1 = 7; // sets variable named inputVariable1 to 7 + inputVariable2 = analogRead(2); // sets variable named inputVariable2 to + // the (digitized) input voltage read from + // analog pin #2 + +Once a variable has been set (assigned a value), you can test its +value to see if it meets certain conditions, or you can use its value +directly. For instance, the following code tests whether the +inputVariable2 is less than 100, then sets a delay based on +inputVariable2 (which, at that point, is at least 100):: + + if (inputVariable2 < 100) { + inputVariable2 = 100; + } + + delay(inputVariable2); + +See Also +-------- + +- :ref:`lang-scope` +- :ref:`lang-numeric-types` + +.. rubric:: Footnotes + +.. [#frange] This range might seem a little weird at first. The + reasons for this range of values have to do with the fact that an + ``int`` occupies 32 bits of memory, and the facts :: + + 2^31 = -2,147,483,648 + 2^31 - 1 = 2,147,483,647 + + + Why 2^31 instead of 2^32? Well, that has to do with `how ints are + (usually) stored + `_ on computers. + + +.. include:: cc-attribution.txt + diff --git a/docs/source/lang/cpp/void.rst b/docs/source/lang/cpp/void.rst new file mode 100644 index 0000000..88bd448 --- /dev/null +++ b/docs/source/lang/cpp/void.rst @@ -0,0 +1,31 @@ +.. highlight:: cpp + +.. _lang-void: + +``void`` +======== + +The ``void`` keyword is used only in function declarations. It +indicates that the function is expected to return no information to +the function from which it was called, or that it expects no arguments +from its caller. + +Example +------- + +:: + + // actions are performed in the functions "setup" and "loop" + // but no information is reported to the larger program + + void setup() { + // ... + } + + void loop() { + // ... + } + +.. TODO doc page on function declaration? + +.. include:: cc-attribution.txt diff --git a/docs/source/lang/cpp/while.rst b/docs/source/lang/cpp/while.rst new file mode 100644 index 0000000..9047d05 --- /dev/null +++ b/docs/source/lang/cpp/while.rst @@ -0,0 +1,38 @@ +.. highlight:: cpp + +.. _lang-while: + +``while`` +========= + +Syntax +------ + +:: + + while (expression) { + // block of code + } + +Description +----------- + +``while`` loops will repeat the statements inside their associated +block of code until the expression inside the parentheses becomes +:ref:`false `. Something must change the tested +expressions' value, or the ``while`` loop will never exit. This could +be in your code, such as an incremented variable, or an external +condition, such as testing a sensor. + +Example +------- + +:: + + var = 0; + while(var < 200) { + // do something repetitive 200 times + var++; + } + +.. include:: cc-attribution.txt -- cgit v1.2.3 From d744fb826f4a6d6ce560f3b78f2e63a1f9666d9e Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Wed, 15 Dec 2010 01:50:56 -0500 Subject: Finalized 0.0.9 documentation. --- docs/Doxyfile | 11 +- docs/source/_static/img/jtag-wiring.png | Bin 40550 -> 33637 bytes docs/source/bootloader.rst | 710 ++++++++++++------------ docs/source/compatibility.rst | 22 +- docs/source/cpp.rst | 13 - docs/source/external-interrupts.rst | 1 - docs/source/gpio.rst | 16 +- docs/source/home.rst | 32 -- docs/source/i2c.rst | 1 - docs/source/index.rst | 20 +- docs/source/jtag.rst | 27 +- docs/source/lang/api/analogread.rst | 35 -- docs/source/lang/api/analogwrite.rst | 50 +- docs/source/lang/api/constants.rst | 23 + docs/source/lang/api/hardwarespi.rst | 152 +++++ docs/source/lang/api/hardwaretimer.rst | 368 ++++++++++++ docs/source/lang/api/interrupts.rst | 47 ++ docs/source/lang/api/isbuttonpressed.rst | 17 + docs/source/lang/api/nointerrupts.rst | 47 ++ docs/source/lang/api/pinmode.rst | 2 + docs/source/lang/api/pwmwrite.rst | 15 +- docs/source/lang/api/serialusb.rst | 11 +- docs/source/lang/api/toggleled.rst | 17 + docs/source/lang/api/togglepin.rst | 17 + docs/source/lang/api/waitforbuttonpress.rst | 17 + docs/source/lang/cpp/built-in-types.rst | 95 ++++ docs/source/lang/cpp/keywords.rst | 2 +- docs/source/lang/cpp/numeric-types.rst | 79 --- docs/source/lang/cpp/variables.rst | 6 +- docs/source/lang/cpp/void.rst | 10 +- docs/source/lang/unimplemented/interrupts.rst | 59 -- docs/source/lang/unimplemented/nointerrupts.rst | 59 -- docs/source/language-index.rst | 40 +- docs/source/language.rst | 233 ++++---- docs/source/libraries.rst | 67 ++- docs/source/libs/servo.rst | 108 ++++ docs/source/pwm.rst | 103 +--- docs/source/spi.rst | 55 +- docs/source/timers.rst | 231 ++------ docs/source/troubleshooting.rst | 27 +- docs/source/usart.rst | 1 - docs/source/usb.rst | 1 - libmaple/libmaple_types.h | 2 + libmaple/timers.h | 109 ++-- support/scripts/copy-to-ide | 16 +- wirish/HardwareTimer.cpp | 1 - wirish/HardwareTimer.h | 69 ++- wirish/comm/HardwareSPI.h | 23 +- wirish/ext_interrupts.h | 4 +- wirish/io.h | 2 +- wirish/wirish_math.h | 6 +- 51 files changed, 1784 insertions(+), 1295 deletions(-) delete mode 100644 docs/source/cpp.rst delete mode 100644 docs/source/home.rst create mode 100644 docs/source/lang/api/hardwarespi.rst create mode 100644 docs/source/lang/api/hardwaretimer.rst create mode 100644 docs/source/lang/api/interrupts.rst create mode 100644 docs/source/lang/api/isbuttonpressed.rst create mode 100644 docs/source/lang/api/nointerrupts.rst create mode 100644 docs/source/lang/api/toggleled.rst create mode 100644 docs/source/lang/api/togglepin.rst create mode 100644 docs/source/lang/api/waitforbuttonpress.rst create mode 100644 docs/source/lang/cpp/built-in-types.rst delete mode 100644 docs/source/lang/cpp/numeric-types.rst delete mode 100644 docs/source/lang/unimplemented/interrupts.rst delete mode 100644 docs/source/lang/unimplemented/nointerrupts.rst create mode 100644 docs/source/libs/servo.rst (limited to 'docs/source/lang/cpp') diff --git a/docs/Doxyfile b/docs/Doxyfile index 88b8764..3290843 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -318,7 +318,7 @@ EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. @@ -1335,13 +1335,13 @@ ENABLE_PREPROCESSING = YES # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. -EXPAND_ONLY_PREDEF = NO +EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. @@ -1369,7 +1369,8 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = __cplusplus +PREDEFINED = ALWAYS_INLINE= \ + __cplusplus # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. @@ -1462,7 +1463,7 @@ HIDE_UNDOC_RELATIONS = YES # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) -HAVE_DOT = YES +HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will diff --git a/docs/source/_static/img/jtag-wiring.png b/docs/source/_static/img/jtag-wiring.png index 9c63e82..8f31f99 100644 Binary files a/docs/source/_static/img/jtag-wiring.png and b/docs/source/_static/img/jtag-wiring.png differ diff --git a/docs/source/bootloader.rst b/docs/source/bootloader.rst index d42c050..57833ed 100644 --- a/docs/source/bootloader.rst +++ b/docs/source/bootloader.rst @@ -138,447 +138,447 @@ This time, however, no DFU transaction is initiated, and the bootloader gives way to user code, closing down the DFU pipe and bringing up the USB serial. -.. _bootloader-rev6: - -Maple Rev6 - The Serial Bootloader (Tentative) ----------------------------------------------- - -.. note:: This section documents an in-progress version of the Maple - bootloader. **No Maples yet sold use this bootloader protocol**. - It has not been yet been publicly released, and its interface is - not stable. - -The bootloader in Rev3/Rev5 works well on Linux, acceptably on Mac, -but was unsatisfactory on Windows. Unlike the other operating systems, -Windows needed to be manually pointed to both the driver to use for -programming (DFU, via `libusb `_) and the -driver to use for serial communication (usbser.sys, built in to -Windows). Since Maple operates in only one of these modes at a time, -driver installation was unnecessarily complicated. It was necessary to -bring Maple into the correct mode before installing each of the -drivers. Furthermore, because libusb is not bundled with Windows, and -its driver is not signed, Windows 7 users have been forced to -laboriously disable driver signing checks. Finally, Windows hates the -constant switching of the device between Serial and DFU modes (during -programming), and often prompts users to install drivers that are -already installed. We have therefore decided to abandon DFU. - -In our new bootloader scheme, Maple is simply a serial device. -Windows comes bundled with usbser.sys, so no driver signing is -required. The IDE installation process is greatly simplified, there -is no more switching back and forth between "modes", and we can build -in new functionality outside the DFU spec. - -The first incarnation of this serial-only bootloader leaves libmaple -and user code untouched. However, during programming, instead of -calling :command:`dfu-util` to upload code we will now call a newly -written utility script similar to `avr-dude -`_. The high level -operation of the bootloader will remain the same - come on at startup, -wait for an upload operation or timeout, and jump to user code. - -The second version of this bootloader will eliminate this dependence -on resetting and timing out by having the bootloader run in the -background. It will additionally own the serial port. In this scheme, -sending data over the COM port while DTR is pulled low results in that -packet being captured by the bootloader and interpreted as a -bootloader command. When the user uploads a new program, the -bootloader will overwrite the old one, reset the various peripheral -registers, and jump to user code. All of this will occur without -resetting the chip and thus causing Maple to connect and disconnect -from your computer (which seems to cause many problems). - -The final version of this bootloader scheme will involve a separate -microcontroller, whose responsibilities are to drive the USB port, -program the main processor, and offer some amount of debugging -capability. This will allow user sketches to run on the bare metal of -the main processor, without any bootloader hiding underneath. This -approach is similar to the approaches taken by mbed and the Arduino -Uno. - -Regardless of which generation of the new serial bootloader you are -working with, the command interface is the same. The low level -communication protocol is inspired by STK-500, the protocol used to -program many AVR-based development boards. The protocol is a -packetized query-response scheme. The host PC initiates every -transaction, and for every query sent to the bootloader, a single -response will be returned (or the system times out). Data is -transmitted over 115.2kbps, 8 data bits, 1 stop bit, no parity -bit. Every query or response follows the same packet format that looks -like this: - -.. _bootloader-packet-structure: - -Packet Structure -^^^^^^^^^^^^^^^^ - -A bootloader packet is composed of a sequence of fields, as follows. - -.. list-table:: - :header-rows: 1 - - * - Field - - Length (bytes) - - Value - - Description - - * - START - - 1 - - 0x1B - - Magic constant, indicates bootloader packet - - * - SEQUENCE_NUM - - 1 - - 0--0xFF - - Queries and responses must have the same sequence number; rolls - over to 0 after 0xFF - - * - MESSAGE_SIZE - - 2 - - 0--0xFFFF - - Size of message body, currently limited to a 1024B=1KB maximum - - * - TOKEN - - 1 - - 0x7F - - Differs from STK500 value of 0x0E - - * - MESSAGE_BODY - - Variable, determined by MESSAGE_SIZE field - - Command query or response - - See :ref:`next section ` - - * - CHECKSUM - - 4 - - XOR of all other 32-bit words in packet - - See :ref:`below ` - -.. _bootloader-checksum: - -.. highlight:: cpp - -.. note:: When computing the checksum, the words in a packet are - interpreted big-endian (as if the packet were a sequence of 32-bit, - big-endian unsigned integers). If the end of the MESSAGE_BODY is - not aligned with a four-byte boundary, then the checksum will treat - it as if it was padded with zero bytes to a four-byte boundary. - - As a concrete example, an entire GET_INFO query (see :ref:`below - `), including the packet structure, is - comprised of the byte sequence :: - - {0x1B, 0x7F, 0x00, 0x01, 0x7F, 0x00, 0x64, 0x7F, 0x00, 0x01} - - The SEQUENCE_NUM of this query is 0x7F. +.. .. _bootloader-rev6: + +.. Maple Rev6 - The Serial Bootloader (Tentative) +.. ---------------------------------------------- + +.. .. note:: This section documents an in-progress version of the Maple +.. bootloader. **No Maples yet sold use this bootloader protocol**. +.. It has not been yet been publicly released, and its interface is +.. not stable. + +.. The bootloader in Rev3/Rev5 works well on Linux, acceptably on Mac, +.. but was unsatisfactory on Windows. Unlike the other operating systems, +.. Windows needed to be manually pointed to both the driver to use for +.. programming (DFU, via `libusb `_) and the +.. driver to use for serial communication (usbser.sys, built in to +.. Windows). Since Maple operates in only one of these modes at a time, +.. driver installation was unnecessarily complicated. It was necessary to +.. bring Maple into the correct mode before installing each of the +.. drivers. Furthermore, because libusb is not bundled with Windows, and +.. its driver is not signed, Windows 7 users have been forced to +.. laboriously disable driver signing checks. Finally, Windows hates the +.. constant switching of the device between Serial and DFU modes (during +.. programming), and often prompts users to install drivers that are +.. already installed. We have therefore decided to abandon DFU. + +.. In our new bootloader scheme, Maple is simply a serial device. +.. Windows comes bundled with usbser.sys, so no driver signing is +.. required. The IDE installation process is greatly simplified, there +.. is no more switching back and forth between "modes", and we can build +.. in new functionality outside the DFU spec. + +.. The first incarnation of this serial-only bootloader leaves libmaple +.. and user code untouched. However, during programming, instead of +.. calling :command:`dfu-util` to upload code we will now call a newly +.. written utility script similar to `avr-dude +.. `_. The high level +.. operation of the bootloader will remain the same - come on at startup, +.. wait for an upload operation or timeout, and jump to user code. + +.. The second version of this bootloader will eliminate this dependence +.. on resetting and timing out by having the bootloader run in the +.. background. It will additionally own the serial port. In this scheme, +.. sending data over the COM port while DTR is pulled low results in that +.. packet being captured by the bootloader and interpreted as a +.. bootloader command. When the user uploads a new program, the +.. bootloader will overwrite the old one, reset the various peripheral +.. registers, and jump to user code. All of this will occur without +.. resetting the chip and thus causing Maple to connect and disconnect +.. from your computer (which seems to cause many problems). + +.. The final version of this bootloader scheme will involve a separate +.. microcontroller, whose responsibilities are to drive the USB port, +.. program the main processor, and offer some amount of debugging +.. capability. This will allow user sketches to run on the bare metal of +.. the main processor, without any bootloader hiding underneath. This +.. approach is similar to the approaches taken by mbed and the Arduino +.. Uno. + +.. Regardless of which generation of the new serial bootloader you are +.. working with, the command interface is the same. The low level +.. communication protocol is inspired by STK-500, the protocol used to +.. program many AVR-based development boards. The protocol is a +.. packetized query-response scheme. The host PC initiates every +.. transaction, and for every query sent to the bootloader, a single +.. response will be returned (or the system times out). Data is +.. transmitted over 115.2kbps, 8 data bits, 1 stop bit, no parity +.. bit. Every query or response follows the same packet format that looks +.. like this: + +.. .. _bootloader-packet-structure: + +.. Packet Structure +.. ^^^^^^^^^^^^^^^^ + +.. A bootloader packet is composed of a sequence of fields, as follows. + +.. .. list-table:: +.. :header-rows: 1 + +.. * - Field +.. - Length (bytes) +.. - Value +.. - Description + +.. * - START +.. - 1 +.. - 0x1B +.. - Magic constant, indicates bootloader packet + +.. * - SEQUENCE_NUM +.. - 1 +.. - 0--0xFF +.. - Queries and responses must have the same sequence number; rolls +.. over to 0 after 0xFF + +.. * - MESSAGE_SIZE +.. - 2 +.. - 0--0xFFFF +.. - Size of message body, currently limited to a 1024B=1KB maximum + +.. * - TOKEN +.. - 1 +.. - 0x7F +.. - Differs from STK500 value of 0x0E + +.. * - MESSAGE_BODY +.. - Variable, determined by MESSAGE_SIZE field +.. - Command query or response +.. - See :ref:`next section ` + +.. * - CHECKSUM +.. - 4 +.. - XOR of all other 32-bit words in packet +.. - See :ref:`below ` + +.. .. _bootloader-checksum: + +.. .. highlight:: cpp + +.. .. note:: When computing the checksum, the words in a packet are +.. interpreted big-endian (as if the packet were a sequence of 32-bit, +.. big-endian unsigned integers). If the end of the MESSAGE_BODY is +.. not aligned with a four-byte boundary, then the checksum will treat +.. it as if it was padded with zero bytes to a four-byte boundary. -.. highlight:: sh +.. As a concrete example, an entire GET_INFO query (see :ref:`below +.. `), including the packet structure, is +.. comprised of the byte sequence :: + +.. {0x1B, 0x7F, 0x00, 0x01, 0x7F, 0x00, 0x64, 0x7F, 0x00, 0x01} + +.. The SEQUENCE_NUM of this query is 0x7F. + +.. .. highlight:: sh -.. _bootloader-commands: +.. .. _bootloader-commands: -Commands -^^^^^^^^ +.. Commands +.. ^^^^^^^^ -The packet structure overhead is for reliability. The actual queries -and responses are transacted inside of the message body. Following -the STK-500 protocol, each query or response begins with the single -byte command field. For each query, the resultant response must begin -with the same CMD byte. For each type of command, the structure of -queries and responses is of fixed size. +.. The packet structure overhead is for reliability. The actual queries +.. and responses are transacted inside of the message body. Following +.. the STK-500 protocol, each query or response begins with the single +.. byte command field. For each query, the resultant response must begin +.. with the same CMD byte. For each type of command, the structure of +.. queries and responses is of fixed size. -Also following STK-500, fields longer than 1 byte are transmitted MSB -first (big-endian). However, READ and WRITE commands operate byte-wise -(not word-wise); it is up to the host PC to ensure that alignment and -ordering issues are handled appropriately. +.. Also following STK-500, fields longer than 1 byte are transmitted MSB +.. first (big-endian). However, READ and WRITE commands operate byte-wise +.. (not word-wise); it is up to the host PC to ensure that alignment and +.. ordering issues are handled appropriately. -.. _bootloader-get-info: +.. .. _bootloader-get-info: -GET_INFO -"""""""" +.. GET_INFO +.. """""""" -Used to query device characteristics. +.. Used to query device characteristics. -GET_INFO Query: +.. GET_INFO Query: -.. list-table:: - :header-rows: 1 +.. .. list-table:: +.. :header-rows: 1 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - GET_INFO - - 1 - - Value 0 +.. * - GET_INFO +.. - 1 +.. - Value 0 -GET_INFO Response: +.. GET_INFO Response: -.. list-table:: - :header-rows: 1 - :widths: 4 2 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 4 2 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - GET_INFO - - 1 - - Value 0 +.. * - GET_INFO +.. - 1 +.. - Value 0 - * - Endianness - - 1 - - 0 indicates little-endian, 1 indicates big-endian. - (Currently returns 0; this field allows for future - expansion). +.. * - Endianness +.. - 1 +.. - 0 indicates little-endian, 1 indicates big-endian. +.. (Currently returns 0; this field allows for future +.. expansion). - * - Available Ram - - 4 - - In bytes +.. * - Available Ram +.. - 4 +.. - In bytes - * - Available Flash - - 4 - - In bytes +.. * - Available Flash +.. - 4 +.. - In bytes - * - Flash Page Size - - 2 - - In bytes +.. * - Flash Page Size +.. - 2 +.. - In bytes - * - Starting Address (FLASH) - - 4 - - Usually 0x08005000 +.. * - Starting Address (FLASH) +.. - 4 +.. - Usually 0x08005000 - * - Starting Address (RAM) - - 4 - - Usually 0x200000C0 +.. * - Starting Address (RAM) +.. - 4 +.. - Usually 0x200000C0 - * - Bootloader Version - - 4 - - Current version 0x00060000 (MAJ,MIN) +.. * - Bootloader Version +.. - 4 +.. - Current version 0x00060000 (MAJ,MIN) -.. _bootloader-erase-page: +.. .. _bootloader-erase-page: -ERASE_PAGE -"""""""""" +.. ERASE_PAGE +.. """""""""" -Used to erase flash pages. +.. Used to erase flash pages. -ERASE_PAGE query: +.. ERASE_PAGE query: -.. list-table:: - :header-rows: 1 - :widths: 4 2 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 4 2 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - ERASE_PAGE - - 1 - - Value 1 +.. * - ERASE_PAGE +.. - 1 +.. - Value 1 - * - ADDRESS - - 4 - - Will erase whichever page contains ADDRESS +.. * - ADDRESS +.. - 4 +.. - Will erase whichever page contains ADDRESS -ERASE_PAGE response: +.. ERASE_PAGE response: -.. list-table:: - :header-rows: 1 - :widths: 3 2 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 3 2 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - ERASE_PAGE - - 1 - - Value 1 +.. * - ERASE_PAGE +.. - 1 +.. - Value 1 - * - SUCCESS - - 1 - - Either 0 (failure) or 1 (success) +.. * - SUCCESS +.. - 1 +.. - Either 0 (failure) or 1 (success) -WRITE_BYTES -""""""""""" +.. WRITE_BYTES +.. """"""""""" -Used to write to RAM or flash. +.. Used to write to RAM or flash. -WRITE_BYTES query: +.. WRITE_BYTES query: -.. list-table:: - :header-rows: 1 - :widths: 4 4 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 4 4 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - WRITE_BYTES - - 1 - - Value 2 +.. * - WRITE_BYTES +.. - 1 +.. - Value 2 - * - Starting Address - - 4 - - Can address arbitrary RAM, or :ref:`cleared - ` flash pages. +.. * - Starting Address +.. - 4 +.. - Can address arbitrary RAM, or :ref:`cleared +.. ` flash pages. - * - DATA - - MESSAGE_SIZE - 5 - - See :ref:`Packet Structure ` +.. * - DATA +.. - MESSAGE_SIZE - 5 +.. - See :ref:`Packet Structure ` -WRITE_BYTES response: +.. WRITE_BYTES response: -.. list-table:: - :header-rows: 1 - :widths: 2 2 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 2 2 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - WRITE_BYTES - - 1 - - Value 2 +.. * - WRITE_BYTES +.. - 1 +.. - Value 2 - * - SUCCESS - - 1 - - Either 0 (failure) or 1 (success). Will fail if writes were - made to uncleared pages. Does not clean up failed writes - (memory will be left in an undefined state). +.. * - SUCCESS +.. - 1 +.. - Either 0 (failure) or 1 (success). Will fail if writes were +.. made to uncleared pages. Does not clean up failed writes +.. (memory will be left in an undefined state). -READ_BYTES -"""""""""" +.. READ_BYTES +.. """""""""" -Used to read from RAM or flash. +.. Used to read from RAM or flash. -READ_BYTES query: +.. READ_BYTES query: -.. list-table:: - :header-rows: 1 - :widths: 2 2 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 2 2 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - READ_BYTES - - 1 - - Value 3 +.. * - READ_BYTES +.. - 1 +.. - Value 3 - * - ADDRESS - - 4 - - Start of block to read. Must be a multiple of 4. +.. * - ADDRESS +.. - 4 +.. - Start of block to read. Must be a multiple of 4. - * - LENGTH - - 2 - - Maximum number of bytes to read (currently, this may be at most - 1024 = 1KB). Must be a multiple of 4. +.. * - LENGTH +.. - 2 +.. - Maximum number of bytes to read (currently, this may be at most +.. 1024 = 1KB). Must be a multiple of 4. -READ_BYTES response: +.. READ_BYTES response: -.. list-table:: - :header-rows: 1 - :widths: 2 2 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 2 2 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - READ_BYTES - - 1 - - Value 3 +.. * - READ_BYTES +.. - 1 +.. - Value 3 - * - DATA - - MESSAGE_SIZE - 1 - - Contains read bytes. The actual number of bytes read may be - less than the LENGTH field of the corresponding READ_BYTES - query. If this section is of length 0, this should be - interpreted as a read failure. See - :ref:`bootloader-packet-structure`. +.. * - DATA +.. - MESSAGE_SIZE - 1 +.. - Contains read bytes. The actual number of bytes read may be +.. less than the LENGTH field of the corresponding READ_BYTES +.. query. If this section is of length 0, this should be +.. interpreted as a read failure. See +.. :ref:`bootloader-packet-structure`. -JUMP_TO_USER -"""""""""""" +.. JUMP_TO_USER +.. """""""""""" -Causes the bootloader to jump to user code's starting address. +.. Causes the bootloader to jump to user code's starting address. -JUMP_TO_USER query: +.. JUMP_TO_USER query: -.. list-table:: - :header-rows: 1 - :widths: 2 1 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 2 1 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - JUMP_TO_USER - - 1 - - Value 4 +.. * - JUMP_TO_USER +.. - 1 +.. - Value 4 - * - Location - - 1 - - 0 means jump to flash starting address, 1 means jump to RAM - starting address. See the :ref:`bootloader-get-info` command - for more information. +.. * - Location +.. - 1 +.. - 0 means jump to flash starting address, 1 means jump to RAM +.. starting address. See the :ref:`bootloader-get-info` command +.. for more information. -JUMP_TO_USER response: +.. JUMP_TO_USER response: -.. list-table:: - :header-rows: 1 - :widths: 2 1 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 2 1 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - JUMP_TO_USER - - 1 - - Value 4 +.. * - JUMP_TO_USER +.. - 1 +.. - Value 4 - * - SUCCESS - - 1 - - Either 0 (failure) or 1 (success). If successful, after the - response is sent, the bootloader ends this session and jumps to - the user code in flash or RAM as specified in the query's - Location field. +.. * - SUCCESS +.. - 1 +.. - Either 0 (failure) or 1 (success). If successful, after the +.. response is sent, the bootloader ends this session and jumps to +.. the user code in flash or RAM as specified in the query's +.. Location field. -SOFT_RESET -"""""""""" +.. SOFT_RESET +.. """""""""" -Engages a full software reset. +.. Engages a full software reset. -SOFT_RESET query: +.. SOFT_RESET query: -.. list-table:: - :header-rows: 1 - :widths: 2 1 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 2 1 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - SOFT_RESET - - 1 - - Value 5 +.. * - SOFT_RESET +.. - 1 +.. - Value 5 -SOFT_RESET response: +.. SOFT_RESET response: -.. list-table:: - :header-rows: 1 - :widths: 2 1 10 +.. .. list-table:: +.. :header-rows: 1 +.. :widths: 2 1 10 - * - Field - - Bytes - - Comments +.. * - Field +.. - Bytes +.. - Comments - * - SOFT_RESET - - 1 - - Value 5 +.. * - SOFT_RESET +.. - 1 +.. - Value 5 - * - SUCCESS - - 1 - - Either 0 or 1 (FAILED and OK, respectively). Will end this - bootloader session and reset the processor. +.. * - SUCCESS +.. - 1 +.. - Either 0 or 1 (FAILED and OK, respectively). Will end this +.. bootloader session and reset the processor. .. _bootloader-reflashing: diff --git a/docs/source/compatibility.rst b/docs/source/compatibility.rst index a070b42..848a3d3 100644 --- a/docs/source/compatibility.rst +++ b/docs/source/compatibility.rst @@ -119,8 +119,6 @@ differences, most of which are improvements: Shield and Device Compatibility ------------------------------- -.. TODO update for 0.0.9 - .. list-table:: :header-rows: 1 @@ -134,7 +132,7 @@ Shield and Device Compatibility * - WiFi Shield - Yes! - - Tested; no library yet (expected for 0.0.9) + - Tested; preliminary library support * - MIDI shield - Yes! @@ -146,7 +144,8 @@ Shield and Device Compatibility * - Bluetooth shield - Unknown - - + - Some Bluetooth <-> UART boards have been tested and are known + to work. * - Cellular shield - Unknown @@ -158,11 +157,12 @@ Library Porting Status The state of currently ported Arduino libraries is the :ref:`libraries`. -.. TODO update for 0.0.9; update as libraries are ported. +.. TODO Update as libraries are ported. .. list-table:: :header-rows: 1 + * - Library - Ported? - Notes @@ -180,9 +180,11 @@ The state of currently ported Arduino libraries is the - Planned * - EEPROM - - No - - The Maple doesn't have EEPROM; use flash instead. Perhaps this - library could be emulated? + - (Unsupported) third-party emulation + - The Maple doesn't have EEPROM; it uses flash instead. There is + an `EEPROM emulation library + `_ by + `x893 `_, but we haven't tested it. * - Firmata - Not yet @@ -192,6 +194,10 @@ The state of currently ported Arduino libraries is the - Not yet - Planned + * - Servo + - **Yes** + - :ref:`Included since IDE 0.0.9 ` + * - SoftwareSerial - Not yet - Planned diff --git a/docs/source/cpp.rst b/docs/source/cpp.rst deleted file mode 100644 index a20578e..0000000 --- a/docs/source/cpp.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _cpp: - -============== -C++ for Maple -============== - -.. _index-language-index-cpp-index: - -.. toctree:: - :maxdepth: 1 - :glob: - - lang/cpp/* \ No newline at end of file diff --git a/docs/source/external-interrupts.rst b/docs/source/external-interrupts.rst index 79492ef..5187ca4 100644 --- a/docs/source/external-interrupts.rst +++ b/docs/source/external-interrupts.rst @@ -121,6 +121,5 @@ Recommended Reading * STMicro documentation for STM32F103RB microcontroller: - * `All `_ * `Datasheet `_ (pdf) * `Reference Manual `_ (pdf) diff --git a/docs/source/gpio.rst b/docs/source/gpio.rst index ee2b6eb..4017862 100644 --- a/docs/source/gpio.rst +++ b/docs/source/gpio.rst @@ -14,9 +14,9 @@ peripheral functions. This page documents those capabilities, by pin. The current and voltage limitations have not been copied over from the STM32 datasheet (see the :ref:`Recommended Reading ` for a link). In particular, a number of -GPIO pins are 5v tolerant (which means that applying 5v to a pin and -reading it as input or allowing it to drain to ground will not damage -that pin), while some are not. +GPIO pins are 5V tolerant (which means that applying 5 volts to a pin +and reading it as input or allowing it to drain to ground will not +damage that pin), while some are not. .. contents:: Contents :local: @@ -26,11 +26,10 @@ that pin), while some are not. Pin Mapping Mega Table ---------------------- -This huge reference table shows the available functionality on every -GPIO pin, by peripheral type. The "STM32" column refers to the port -and number that the header is connected to on the microcontroller. -The "5v?" column documents whether or not the pin is 5v tolerant (see -above). +This table shows the available functionality on every GPIO pin, by +peripheral type. The "STM32" column refers to the port and number that +the header is connected to on the microcontroller. The "5V?" column +documents whether or not the pin is 5 volt tolerant (see above). .. csv-table:: :header: "Pin", "STM32", ":ref:`ADC `", ":ref:`Timer `", ":ref:`I2C `", ":ref:`UART `", ":ref:`SPI `", "5v?" @@ -99,6 +98,5 @@ Recommended Reading STMicro documentation for STM32F103RB microcontroller: - * `All `_ * `Datasheet `_ (pdf) * `Reference Manual `_ (pdf) diff --git a/docs/source/home.rst b/docs/source/home.rst deleted file mode 100644 index db5b56e..0000000 --- a/docs/source/home.rst +++ /dev/null @@ -1,32 +0,0 @@ -.. _home: - -======================== -Maple Documentation Home -======================== - - -Welcome! - -Maple is a user-friendly prototyping platform developed by LeafLabs in Cambridge, MA. Using Maple, creators with any level of experience can implement beautiful ideas that require the power of a 32-bit processor. For more details about Maple's hardware, please see its :ref:`technical specifications `. To start using your Maple, keep reading - -.. _home-Getting-Started: - -Getting Started -^^^^^^^^^^^^^^^ - -:ref:`Quickstart ` - -:ref:`IDE Anatomy ` - -:ref:`Basic Language Reference ` - -:ref:`Tech Specs` - -.. _home-Problem-Solving: - -Problem Solving -^^^^^^^^^^^^^^^ - -Check out our :ref:`troubleshooting ` and :ref:`known problems` pages. - -If you don't find what you're looking for, hit the `forums `_ to ask the LeafLabs team and other Maple users questions. Good luck, and have fun! diff --git a/docs/source/i2c.rst b/docs/source/i2c.rst index 6e5b946..b4a996b 100644 --- a/docs/source/i2c.rst +++ b/docs/source/i2c.rst @@ -80,7 +80,6 @@ Recommended Reading * `Arduino i2c/TWI reference `_ * STMicro documentation for STM32F103RB microcontroller: - * `All `_ * `Datasheet `_ (pdf) * `Reference Manual `_ (pdf) * `Application Note on Advanced I2C Usage diff --git a/docs/source/index.rst b/docs/source/index.rst index c552dd4..825ec81 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,7 +1,15 @@ .. _index: Maple Documentation Contents -============================= +============================ + +Welcome! This is the Maple documentation index. If you just bought a +Maple, you probably want to head to the :ref:`quickstart +`. If you're having problems, check out the +:ref:`troubleshooting ` and :ref:`known problems +` pages. + +Have fun! .. _index-usage: @@ -15,7 +23,7 @@ Maple Documentation Contents IDE Anatomy .. _index-maple-programming: - + **Maple Programming:** .. toctree:: @@ -29,7 +37,7 @@ Maple Documentation Contents Bootloader - Troubleshooting + Troubleshooting Known Problems .. _index-hardware: @@ -38,7 +46,7 @@ Maple Documentation Contents .. toctree:: :maxdepth: 1 - + i2c pwm gpio @@ -55,8 +63,8 @@ Maple Documentation Contents .. toctree:: :maxdepth: 1 - + Technical Specifications Complete Language Index - + diff --git a/docs/source/jtag.rst b/docs/source/jtag.rst index 7cfba5f..e3c8111 100644 --- a/docs/source/jtag.rst +++ b/docs/source/jtag.rst @@ -15,24 +15,24 @@ and hardware peripherals (we use it when working on :ref:`libmaple Note that the STM32 on the Maple has a built-in low level serial debugger which could also be used to flash bootloaders, and that the :ref:`ASSERT ` framework allows basic debugging over -a USART serial channel. We expect only advanced users to use this -feature. +a USART serial channel. We expect only fairly advanced users to use +this feature. .. contents:: Contents :local: - Wiring Diagram -------------- .. figure:: /_static/img/jtag-wiring.png :align: center :alt: JTAG wiring diagram + :width: 7.4in - JTAG wiring diagram to connect a standard 20-pin ARM JTAG device to - the 8-pin JTAG port on the Maple. - -.. FIXME jtag wiring diagram (above) looks terrible; replace it + JTAG wiring diagram (`large version + `_) + to connect a standard 20-pin ARM JTAG device to the 8-pin JTAG port + on the Maple. The Maple has holes for a 8-pin JTAG header but that header is not soldered on by default. If you know ahead of time that you'll be @@ -42,14 +42,7 @@ probably solder one on for no charge. Otherwise, you can simply attach standard 0.1" pitch male header pins (either the exact 4x2 block or two 4-pin pieces of breakaway straight header). For a one-off usage hack, the header can be jammed in the holes and twisted to -ensure electrical contact; this is what we do to flash our bootloader. - -The above schematic assumes that the header has been soldered on to -the *bottom* of the board, not the top; most ribbon cable connectors -will interfere with the power header. If you don't want a header -coming off the bottom, you can use a slim connector and invert this -diagram appropriately. - +ensure electrical contact. Compatible Devices ------------------ @@ -65,6 +58,8 @@ Recommended Reading * `STM32/gdb/OpenOCD HOWTO `_ * STMicro documentation for STM32F103RB microcontroller: - * `All `_ * `Datasheet `_ (pdf) * `Reference Manual `_ (pdf) +* There's a `thread on JTAG + `_ in our `forum`_ + which you may find useful. diff --git a/docs/source/lang/api/analogread.rst b/docs/source/lang/api/analogread.rst index c614aca..35c6fbc 100644 --- a/docs/source/lang/api/analogread.rst +++ b/docs/source/lang/api/analogread.rst @@ -32,11 +32,6 @@ Before calling analogRead() on a pin, that pin must first be configured for analog input, using :ref:`lang-pinMode` (you only have to do this once, so it's usually done in :ref:`lang-setup`\ ). -It takes about 0.8 microseconds (.0000008 seconds) to read an analog -input, so the maximum sample rate using this function is approximately -1.3 million samples per second\ [#fsamp]_. - - Parameter Discussion -------------------- @@ -115,40 +110,10 @@ Some basic tools to accomplish this are `resistor dividers . However, opamps and other powered components can also be used if greater precision is required. -Finally, On the Arduino, it takes significantly longer to read analog -input: about 100 microseconds (0.0001 s), so the maximum reading rate -is 10,000 times a second. - - See also -------- - :ref:`ADC note ` - `(Arduino) Tutorial: Analog Input Pins `_ - -.. rubric:: Footnotes - -.. [#fsamp] This is based on the current configuration of a 55.5 cycle - sample time, at 72 MHz. However, the minimum sample time *possible* - is 1.5 cycles, leading to a theoretical maximum of approximately 48 - million samples per second (of course, doing anything with the - readings also consumes cycles, so this maximum can't be reached in - practice). - - See the `STM32 Reference Manual `_, §§11.12.4--5 - (pp. 225--226), for more information on the low-level bit twiddling - currently necessary to change the sample time. For examples of how - the ADCs are configured in libmaple, see `adc.h - `_ - and `adc.c - `_\ - . Be aware that changing the sample time has important - consequences related to the impedance of the device connected to - the input pin. If you want to make changes, as a minimum, you - should first read ST's application notes on `ADC modes - `_ and `ADC oversampling - `_. - - .. include:: cc-attribution.txt diff --git a/docs/source/lang/api/analogwrite.rst b/docs/source/lang/api/analogwrite.rst index 01820ef..9147b96 100644 --- a/docs/source/lang/api/analogwrite.rst +++ b/docs/source/lang/api/analogwrite.rst @@ -11,19 +11,18 @@ analogWrite() .. note:: On the Maple, calling analogWrite() is the same as calling - :ref:`lang-pwmwrite`\ ; see that function's documentation for more - information. + :ref:`lang-pwmwrite`\ ; we recommend using that function directly + instead. This is because PWM is not true analog output (i.e., is not the output of a `DAC `_\ ), so - the function is badly named. For instance, **analogWrite() has + the function is badly named. For instance, analogWrite() **has absolutely nothing to do with** :ref:`lang-analogread`\ , which is potentially confusing. - The alias of analogWrite() to pwmWrite() is provided (sigh) for the - sake of compatibility with Arduino, but we recommend using - :ref:`lang-pwmwrite` when writing new software, for clarity. + The alias of analogWrite() to pwmWrite() is provided for the sake + of compatibility with Arduino only. .. contents:: Contents :local: @@ -97,23 +96,21 @@ Difference 3: No PWM on pin 10 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ On the Maple, the pins which support PWM are: 0, 1, 2, 3, 5, 6, 7, 8, -9, 11, 12, and 14, or twelve pins in total. That is at least as -*many* PWM pins as any Arduino board, but there are differences in -*which* pins support it. +9, 11, 12, 14, 24, 27, and 28 or fifteen pins in total. That's *more* +PWM-capable pins as any Arduino board, but there are differences in +*which* pins support PWM. * On **most Arduino boards** (those with the ATmega168 or ATmega328; this includes the **Arduino Uno**), this function works on pins 3, 5, 6, 9, 10, and 11, or six pins total. Note that these boards support PWM on pin 10, while Maple does not. -* On the **Arduino Mega**, PWM works on pins 2 through 13, or twelve pins - total. Note that this board supports PWM on pins 4, 10, and 13, - while the Maple does not. Maple supports PWM on pins 0, 1, and 14, - which the Mega does not, making the total number of pins supporting - PWM equal on these boards. +* On the **Arduino Mega**, PWM works on pins 2 through 13, or twelve + pins total. Note that this board supports PWM on pins 4, 10, and + 13, while the Maple does not. -* **Older Arduino boards** with an ATmega8 only support analogWrite() on - pins 9, 10, and 11. Maple does not support PWM on pin 10. +* **Older Arduino boards** with an ATmega8 only support analogWrite() + on pins 9, 10, and 11. Maple does not support PWM on pin 10. In all cases, Arduino boards support PWM on pin 10, unlike Maple. We did our best to make PWM as pin-compatible as possible; however, @@ -125,7 +122,8 @@ work on any Arduino board and on Maple. The "safe" pins, which work on most recent Arduino boards, the Arduino Mega and the Maple, are pins 3, 5, 6, 9, and 11. Thus, if you want your project to be as portable as possible between Maple and Arduino, we recommend using the -"safest" pins first, then the "safe" pins, as necessary. +"safest" pins first, then the "safe" pins, then any other pins, as +necessary. Difference 4: PWM frequency ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,17 +136,23 @@ Hz, or 1.1 KHz. This is because the PWM frequency is the frequency of the timer which controls PWM output on the particular pin (\ :ref:`the PWM tutorial has the details `\ ). -If your application absolutely requires Arduino's PWM frequency (it -probably doesn't), then the steps are: +If your application definitely requires Arduino's PWM frequency, then +the steps are: -1. Figure out which timer controls PWM output on your pin (\ :ref:`this table ` is your friend here). Let's say it's ``Timern``\ , where ``n`` is some number 1, 2, 3, or 4. +1. Figure out which :ref:`timer ` controls PWM + output on your pin (\ :ref:`this table ` is your + friend here). Let's say it's ``Timern``\ , where ``n`` is some + number 1, 2, 3, or 4. -2. Call ``Timern.setPeriod(2041)``\ . This will set the timer's period to approximately 2041 microseconds, which is a frequency of approximately 490 Hz. +2. Call ``Timern.setPeriod(2041)``\ . This will set the timer's + period to approximately 2041 microseconds, which is a frequency of + approximately 490 Hz. Be aware that this will change the period for the **entire timer**\ , and will affect anything else in your program that depends on that -timer. One example is :ref:`interrupts `\ . -You've been :ref:`warned `\ . +timer. The important examples are :ref:`timer interrupts +` and :ref:`PWM +`\ . See also -------- diff --git a/docs/source/lang/api/constants.rst b/docs/source/lang/api/constants.rst index bc5c894..4426293 100644 --- a/docs/source/lang/api/constants.rst +++ b/docs/source/lang/api/constants.rst @@ -288,6 +288,29 @@ exponent indicators. Some examples are given in the following table: - 67.0×10\ :sup:`-12` - ``0.000000000067`` +.. _lang-constants-board: + +Board-Specific Constants +------------------------ + +This section documents constants whose value might change across +different LeafLabs boards. You can use these constants to help ensure +that your code will be portable across different boards. + +.. TODO replace "upcoming" when Mini, Native come out + +.. _lang-constants-led: + +- ``BOARD_LED_PIN``: the number of the pin which connects to the + built-in LED. On the Maple, this is pin 13, but it's not guaranteed + to be the same in upcoming boards like the Maple Mini. + +.. _lang-constants-but: + +- ``BOARD_BUTTON_PIN``: the number of the pin which connects to the + built-in button (labeled "BUT"). On the Maple, this is pin 38, but + it's not guaranteed to be the same in other boards. + See Also -------- diff --git a/docs/source/lang/api/hardwarespi.rst b/docs/source/lang/api/hardwarespi.rst new file mode 100644 index 0000000..c71b2c3 --- /dev/null +++ b/docs/source/lang/api/hardwarespi.rst @@ -0,0 +1,152 @@ +.. highlight:: cpp + +.. _lang-hardwarespi: + +HardwareSPI +=========== + +This class is used for creating objects to manage the Maple's built-in +SPI ports. The Maple has two SPI ports. The relevant pins +corresponding to each port's logic signals are documented in the +following table (and on the Maple silkscreen): + +.. _lang-hardwarespi-pinout: + +.. list-table:: + :header-rows: 1 + + * - Port number + - NSS + - MOSI + - MISO + - SCK + + * - 1 + - 10 + - 11 + - 12 + - 13 + + * - 2 + - 31 + - 32 + - 33 + - 34 + +If you use a SPI port, you cannot simultaneously use its associated +pins for other purposes. + +Library Documentation +--------------------- + +HardwareSPI Class Reference +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can use the SPI interface by including a declaration ``HardwareSPI +Spi(number);`` at the start of the sketch or program. The ``number`` +must be either 1 or 2 and specifies which port to use. Once this is +done, you can call any of the methods documented here using +``Spi.method(arguments)``; for example, ``Spi.send(0x13)`` would send +the value ``0x13`` into the port buffer to be transmitted as soon as +possible. + +.. cpp:class:: HardwareSPI + + Class for interacting with SPI. + +.. cpp:function:: HardwareSPI::HardwareSPI(uint32 spi_num) + + Construct an object for managing a SPI peripheral. ``spi_num`` + must be 1 or 2; see the :ref:`table above + ` for pinout information. + +.. cpp:function:: void HardwareSPI::begin(SPIFrequency freq, uint32 endianness, uint32 mode) + + Configure the baudrate of the given SPI port and set up the header + pins appropriately. + + Parameters: + + - ``freq``: one of the ``SPIFrequency`` values, given :ref:`below + `. + + - ``endianness``: either ``LSBFIRST`` (little-endian) or + ``MSBFIRST`` (big-endian). + + - ``mode``: one of 0, 1, 2, or 3, and specifies which SPI mode is + used. The mode number determines a combination of polarity and + phase according to the following table: + + .. list-table:: + :header-rows: 1 + + * - Mode + - Polarity + - Phase + + * - 0 + - 0 + - 0 + + * - 1 + - 0 + - 1 + + * - 2 + - 1 + - 0 + + * - 3 + - 1 + - 1 + + For more information on polarity and phase, see the + :ref:`external references, below `. + +.. cpp:function:: void HardwareSPI::begin() + + A convenience ``begin()``, equivalent to ``begin(SPI_1_125MHZ, + MSBFIRST, 0)``. + +.. cpp:function:: uint8 HardwareSpi::send(uint8 *data, uint32 length) + + Writes ``data`` into the port buffer to be transmitted as soon as + possible, where ``length`` is the number of bytes to send from + ``data``. Returns the last byte shifted back from slave. + +.. cpp:function:: uint8 HardwareSpi::send(uint8 data) + + Writes the single byte ``data`` into the port buffer to be + transmitted as soon as possible. Returns the data byte shifted + back from the slave. + +.. cpp:function:: uint8 HardwareSpi::recv() + + Reads a byte from the peripheral. Returns the next byte in the + buffer. + +SPI Speeds +^^^^^^^^^^ + +.. _lang-hardwarespi-spifrequency: + +The possible SPI speeds are configured using the ``SPIFrequency`` enum: + +.. doxygenenum:: SPIFrequency + +.. _lang-hardwarespi-seealso: + +See Also +-------- + +* `Wikipedia Article on Serial Peripheral Interface Bus (SPI) + `_ +* `Arduino reference on SPI + `_ +* `Hardcore SPI on Arduino `_ by kik64 +* STMicro documentation for STM32F103RB microcontroller: + + * `Datasheet `_ (pdf) + * `Reference Manual `_ (pdf) + + diff --git a/docs/source/lang/api/hardwaretimer.rst b/docs/source/lang/api/hardwaretimer.rst new file mode 100644 index 0000000..258471b --- /dev/null +++ b/docs/source/lang/api/hardwaretimer.rst @@ -0,0 +1,368 @@ +.. highlight:: cpp + +.. _lang-hardwaretimer: + +HardwareTimer +============= + +This class defines the public API for interfacing with the STM32's +built-in timer peripherals. More information on these peripherals +(including code examples) is available in the :ref:`timers reference +`. + +Library Documentation +--------------------- + +HardwareTimer Class Reference +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To interact with a particular timer, call one of the methods +documented below on one of the predefined ``HardwareTimer`` instances. +For example, to set the prescale factor on timer 1 to 5, call +``Timer1.setPrescaleFactor(5)``. + +.. cpp:class:: HardwareTimer + + Class for interacting with a timer. There are four predefined + instances available on the Maple: ``Timer1``, ``Timer2``, + ``Timer3``, and ``Timer4``. + +.. _lang-hardwaretimer-attachinterrupt: + +.. cpp:function:: void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) + + Attach an interrupt handler to the given ``channel``. This + interrupt handler will be called when the timer's counter reaches + the given channel :ref:`compare ` + value. + + ``handler`` should be a function which takes no arguments and has + :ref:`void ` value; i.e. it should have signature :: + + void handler(void); + + You can later detach the interrupt using :ref:`detachInterrupt() + `. + + .. note:: The function (often called an *interrupt service + routine*, or ISR) should attempt to return as quickly as + possible. :ref:`Blinking the LED `, some + logic, :ref:`PWM ` updates, and :ref:`Serial + ` writes are fine; writing to + :ref:`SerialUSB ` or :ref:`waiting + ` for user input can take a long + time and prevent other interrupts from firing on time. + + Tip: if you have a :ref:`delay() ` in your + ISR, you're probably doing it wrong. + +.. cpp:function:: void HardwareTimer::attachCompare1Interrupt(voidFuncPtr handler) + + Equivalent to :ref:`attachInterrupt + `\ ``(1, handler)``. + +.. cpp:function:: void HardwareTimer::attachCompare2Interrupt(voidFuncPtr handler) + + Equivalent to :ref:`attachInterrupt + `\ ``(2, handler)``. + +.. cpp:function:: void HardwareTimer::attachCompare3Interrupt(voidFuncPtr handler) + + Equivalent to :ref:`attachInterrupt + `\ ``(3, handler)``. + +.. cpp:function:: void HardwareTimer::attachCompare4Interrupt(voidFuncPtr handler) + + Equivalent to :ref:`attachInterrupt + `\ ``(4, handler)``. + +.. _lang-hardwaretimer-setchannelmode: + +.. cpp:function:: void HardwareTimer::setChannelMode(int channel, TimerMode mode) + + Set the given channel of this timer to the given :ref:`mode + `. The parameter ``channel`` is one of + 1, 2, 3, and 4, and corresponds to the compare channel you would + like to set. Refer to the full :ref:`pin mapping table + ` to match up timer channels and pin + numbers. + +.. cpp:function:: void HardwareTimer::setChannel1Mode(TimerMode mode) + + Equivalent to :ref:`setChannelMode `\ + ``(1, mode)``. + +.. cpp:function:: void HardwareTimer::setChannel2Mode(TimerMode mode) + + Equivalent to :ref:`setChannelMode `\ + ``(2, mode)``. + +.. cpp:function:: void HardwareTimer::setChannel3Mode(TimerMode mode) + + Equivalent to :ref:`setChannelMode `\ + ``(3, mode)``. + +.. cpp:function:: void HardwareTimer::setChannel4Mode(TimerMode mode) + + Equivalent to :ref:`setChannelMode `\ + ``(4, mode)``. + +.. _lang-hardwaretimer-getcompare: + +.. cpp:function:: uint16 HardwareTimer::getCompare(int channel) + + Gets the compare value for the given ``channel``, from 1 to 4. See + :ref:`setCompare() `. + +.. cpp:function:: uint16 HardwareTimer::getCompare1() + + Equivalent to :ref:`getCompare `\ + ``(1, mode)``. + +.. cpp:function:: uint16 HardwareTimer::getCompare2() + + Equivalent to :ref:`getCompare `\ + ``(2, mode)``. + +.. cpp:function:: uint16 HardwareTimer::getCompare3() + + Equivalent to :ref:`getCompare `\ + ``(3, mode)``. + +.. cpp:function:: uint16 HardwareTimer::getCompare4() + + Equivalent to :ref:`getCompare `\ + ``(4, mode)``. + +.. _lang-hardwaretimer-setcompare: + +.. cpp:function:: void HardwareTimer::setCompare(int channel, uint16 compare) + + Sets the compare value for the given ``channel`` to ``compare``. + If ``compare`` is greater than this timer's overflow value, it will + be truncated to the overflow value. The default compare value is + 65,535 (the largest unsigned 16-bit integer value). + + When the counter reaches this value the interrupt for this channel + will fire if the given ``channel`` :ref:`mode + ` is ``TIMER_OUTPUTCOMPARE`` and + an interrupt is :ref:`attached + `. + + By default, this only changes the relative offsets between events + on a single timer ("phase"); they don't control the frequency with + which they occur. However, a common trick is to increment the + compare value manually in the interrupt handler so that the event + will fire again after the increment period. There can be a + different increment value for each channel, so this trick allows + events to be programmed at 4 different rates on a single + timer. Note that function call overheads mean that the smallest + increment rate is at least a few microseconds. + +.. cpp:function:: void HardwareTimer::setCompare1(uint16 compare) + + Equivalent to :ref:`setCompare `\ + ``(1, compare)``. + +.. cpp:function:: void HardwareTimer::setCompare2(uint16 compare) + + Equivalent to :ref:`setCompare `\ + ``(2, compare)``. + +.. cpp:function:: void HardwareTimer::setCompare3(uint16 compare) + + Equivalent to :ref:`setCompare `\ + ``(3, compare)``. + +.. cpp:function:: void HardwareTimer::setCompare4(uint16 compare) + + Equivalent to :ref:`setCompare `\ + ``(4, compare)``. + +.. cpp:function:: uint16 HardwareTimer::getCount() + + Gets the current timer count. Due to function call overhead, the + return value will be increasingly accurate with smaller prescale + values. Also see :ref:`setCount() `. + +.. _lang-hardwaretimer-setcount: + +.. cpp:function:: void HardwareTimer::setCount(uint16 val) + + Set the timer's current count to ``val``. + + Note that there is some function call overhead associated with + calling this method, so using it is not a robust way to get + multiple timers to share a count value. + + If ``val`` exceeds the timer's :ref:`overflow value + `, it is truncated to the overflow + value. + + +.. _lang-hardwaretimer-detachinterrupt: + +.. cpp:function:: void HardwareTimer::detachInterrupt(int channel) + + Remove the interrupt handler attached to the given ``channel``, if + any. The handler will no longer be called by this timer. + +.. cpp:function:: void HardwareTimer::detachCompare1Interrupt() + + Equivalent to :ref:`detachInterrupt + `\ ``(1)``. + +.. cpp:function:: void HardwareTimer::detachCompare2Interrupt() + + Equivalent to :ref:`detachInterrupt + `\ ``(2)``. + +.. cpp:function:: void HardwareTimer::detachCompare3Interrupt() + + Equivalent to :ref:`detachInterrupt + `\ ``(3)``. + +.. cpp:function:: void HardwareTimer::detachCompare4Interrupt() + + Equivalent to :ref:`detachInterrupt + `\ ``(4)``. + +.. _lang-hardwaretimer-generateupdate: + +.. cpp:function:: void HardwareTimer::generateUpdate() + + Re-initializes the counter (to 0 in upcounting mode, which is the + default), and generates an update of the prescale and overflow + registers. + +.. _lang-hardwaretimer-getoverflow: + +.. cpp:function:: uint16 HardwareTimer::getOverflow() + + Gets the timer's overflow value. See :ref:`setOverflow() + `. + +.. _lang-hardwaretimer-setoverflow: + +.. cpp:function:: void HardwareTimer::setOverflow(uint16 val) + + Sets the timer overflow (or "reload") value to ``val``. + + When the timer's counter reaches this, value it resets to + zero. Its default value is 65535 (the largest unsigned 16-bit + integer); setting the overflow to anything lower will cause + interrupts to be called more frequently (see :ref:`setPeriod() + ` function for a shortcut). + + After the next :ref:`timer update + `, this number will be the + maximum value for the timer's channel compare values. + +.. _lang-hardwaretimer-pause: + +.. cpp:function:: void HardwareTimer::pause() + + Stop the timer's counter, without affecting its configuration. + + The timer will no longer count or fire interrupts after this + function is called, until it is resumed. This function is useful + during timer setup periods, in order to prevent interrupts from + firing before the timer is fully configured. + + Note that there is some function call overhead associated with this + method, so using it in concert with :ref:`resume() + ` is not a robust way to align multiple + timers to the same count value. + +.. _lang-hardwaretimer-setperiod: + +.. cpp:function:: uint16 HardwareTimer::setPeriod(uint32 microseconds) + + Configure the :ref:`prescaler + ` and :ref:`overflow + ` values to generate a timer reload + with a period as close to the given number of ``microseconds`` as + possible. + + The return value is the new overflow value, which may be used to + set channel compare values. However, if a clock that fires an + interrupt every given number of microseconds is all that is + desired, and the relative "phases" are unimportant, channel compare + values may all be set to 1. + +.. _lang-hardwaretimer-getprescalefactor: + +.. cpp:function:: uint16 HardwareTimer::getPrescaleFactor() + + Returns the timer's prescale factor. See + :ref:`setPrescaleFactor() `. + +.. _lang-hardwaretimer-setprescalefactor: + +.. cpp:function:: void HardwareTimer::setPrescaleFactor(uint16 factor) + + Set the timer's prescale factor to ``factor``. + + The prescaler acts as a clock divider to slow down the rate at + which the counter increments. + + For example, the system clock rate is 72MHz, so the counter will + reach 65535 in (13.89 nanoseconds) × (65535 counts) = (910.22 + microseconds), or about a thousand times a second. If the + prescaler equals 1098, then the clock rate is effectively 72MHz / + 1098 = 65.56KHz, and the counter will reach 65536 in (15.25 + microseconds) × (65536 counts) = (0.999 seconds), or about once + per second. + + The :ref:`setPeriod() ` method may + also be used as a convenient alternative. + +.. cpp:function:: void HardwareTimer::resume() + + Resume a paused timer, without affecting its configuration. + + The timer will resume counting and firing interrupts as + appropriate. + + Note that there is some function call overhead associated with + using this method, so using it in concert with :ref:`pause() + ` is not a robust way to align multiple + timers to the same count value. + +.. cpp:function:: timer_dev_num HardwareTimer::getTimerNum() + + Returns the :ref:`timer device number + ` associated with the timer. For + example, ``Timer1.getTimerNum()`` would return ``TIMER1``. + + In most cases, you should not need to use this function. If you do + use it, be careful; the constant ``TIMER1`` is *not equal* to the + number 1; similarly, ``TIMER2`` is *not* the number 2, etc. Be + sure to refer to the timer device number by name. + +.. _lang-hardwaretimer-modes: + +Timer Modes +^^^^^^^^^^^ +.. doxygenenum:: TimerMode + +.. _lang-hardwaretimer-timer-dev-num: + +Timer Device Numbers +^^^^^^^^^^^^^^^^^^^^ + +These provide a lower-level interface for interacting with timers. +They are mostly useful in context with the :ref:`getTimer() +` function. **Be careful** when using +these not to confuse e.g. ``TIMER1`` with the number 1; they are +different. + +.. doxygenenum:: timer_dev_num + +.. _lang-hardwaretimer-convenience: + +.. _lang-hardwaretimer-gettimer: + +Other Functions +^^^^^^^^^^^^^^^ +.. doxygenfunction:: getTimer diff --git a/docs/source/lang/api/interrupts.rst b/docs/source/lang/api/interrupts.rst new file mode 100644 index 0000000..58fd2cc --- /dev/null +++ b/docs/source/lang/api/interrupts.rst @@ -0,0 +1,47 @@ +.. highlight:: cpp + +.. _lang-interrupts: + +interrupts() +============ + +Re-enables interrupts (after they've been disabled by +:ref:`noInterrupts() `). Interrupts allow certain +important tasks to happen in the background, and certain interrupts +are enabled by default. + +Some functions will not work while interrupts are disabled, and both +incoming and outgoing communication may be ignored. Interrupts can +slightly disrupt the timing of code, however, and may be disabled for +particularly critical sections of code. + +Library Documentation +--------------------- + +.. doxygenfunction:: interrupts + +Example +------- + +:: + + void setup() {} + + void loop() { + noInterrupts(); + // critical, time-sensitive code here + interrupts(); + // other code here + } + +See Also +-------- + +- :ref:`noInterrupts() ` +- :ref:`attachInterrupt() ` +- :ref:`detachInterrupt() ` +- :ref:`Timers reference ` +- :ref:`Timer API ` +- :ref:`External interrupts ` + +.. include:: /lang/cc-attribution.txt diff --git a/docs/source/lang/api/isbuttonpressed.rst b/docs/source/lang/api/isbuttonpressed.rst new file mode 100644 index 0000000..dbff0c9 --- /dev/null +++ b/docs/source/lang/api/isbuttonpressed.rst @@ -0,0 +1,17 @@ +.. _lang-isbuttonpressed: + +isButtonPressed() +================= + +Check whether the board's built-in button (labeled BUT on the +silkscreen) is pressed. + +Library Documentation +--------------------- + +.. doxygenfunction:: isButtonPressed + +See Also +-------- + +- :ref:`lang-waitforbuttonpress` diff --git a/docs/source/lang/api/nointerrupts.rst b/docs/source/lang/api/nointerrupts.rst new file mode 100644 index 0000000..68f0498 --- /dev/null +++ b/docs/source/lang/api/nointerrupts.rst @@ -0,0 +1,47 @@ +.. highlight:: cpp + +.. _lang-nointerrupts: + +noInterrupts() +============== + +Description +----------- + +Disables interrupts. Interrupts allow certain important tasks to +happen in the background and are enabled by default. Some functions +will not work while interrupts are disabled, and incoming +communication may be ignored. Interrupts can slightly disrupt the +timing of code, however, and may be disabled for particularly critical +sections of code. + +Library Documentation +--------------------- + +.. doxygenfunction:: noInterrupts + +Example +------- + +:: + + void setup() {} + + void loop() { + noInterrupts(); + // critical, time-sensitive code here + interrupts(); + // other code here + } + +See Also +-------- + +- :ref:`interrupts() ` +- :ref:`attachInterrupt() ` +- :ref:`detachInterrupt() ` +- :ref:`Timers reference ` +- :ref:`Timer API ` +- :ref:`External interrupts ` + +.. include:: /lang/cc-attribution.txt diff --git a/docs/source/lang/api/pinmode.rst b/docs/source/lang/api/pinmode.rst index b9095da..03cbcfa 100644 --- a/docs/source/lang/api/pinmode.rst +++ b/docs/source/lang/api/pinmode.rst @@ -13,6 +13,8 @@ Library Documentation .. doxygenfunction:: pinMode +.. _lang-pinmode-wiringpinmode: + .. doxygenenum:: WiringPinMode Discussion diff --git a/docs/source/lang/api/pwmwrite.rst b/docs/source/lang/api/pwmwrite.rst index 7a1d51f..2c858ab 100644 --- a/docs/source/lang/api/pwmwrite.rst +++ b/docs/source/lang/api/pwmwrite.rst @@ -11,6 +11,13 @@ pwmWrite(), the pin will output a steady square wave with the given duty cycle. You can change the duty cycle later by calling pwmWrite() again with the same pin and a different duty. +On the Maple, the pins which support PWM are: 0, 1, 2, 3, 5, 6, 7, 8, +9, 11, 12, 14, 24, 27, and 28. + +The Arduino function :ref:`analogWrite() ` is an +alias for ``pwmWrite()``, but it is badly named, and its use is +discouraged. + .. contents:: Contents :local: @@ -25,12 +32,11 @@ Example Sets the output to the LED proportional to the value read from the potentiometer:: - int ledPin = 13; // LED connected to pin 13 (Maple) int analogPin = 3; // potentiometer connected to analog pin 3 int val = 0; // variable to store the read value void setup() { - pinMode(ledPin, OUTPUT); // sets the LED pin as output + pinMode(BOARD_LED_PIN, OUTPUT); // sets the LED pin as output pinMode(analogPin, PWM); // sets the potentiometer pin as PWM // output @@ -39,8 +45,9 @@ potentiometer:: void loop() { val = analogRead(analogPin); // read the input pin - analogWrite(ledPin, val / 16); // analogRead values go from 0 to 4095, - // analogWrite values from 0 to 65535 + analogWrite(BOARD_LED_PIN, val / 16); // analogRead values go from 0 + // to 4095, analogWrite values + // from 0 to 65535 } See Also diff --git a/docs/source/lang/api/serialusb.rst b/docs/source/lang/api/serialusb.rst index af3a7e0..e1d12bf 100644 --- a/docs/source/lang/api/serialusb.rst +++ b/docs/source/lang/api/serialusb.rst @@ -52,7 +52,9 @@ world!")``. .. cpp:class:: USBSerial Emulated serial-over-USB class. ``SerialUSB`` is the predefined - instance. + (singleton) instance. + +.. _lang-serialusb-begin: .. cpp:function:: USBSerial::begin() @@ -65,7 +67,12 @@ world!")``. .. cpp:function:: USBSerial::end() - Disables the USB peripheral. + Disables the USB peripheral. Note that using this function will + terminate all USB communications between the Maple and the USB + host; in particular, it implies that you won't be able to upload + any new programs without resetting the board or using + :ref:`perpetual bootloader mode + `. .. cpp:function:: unsigned int USBSerial::available() diff --git a/docs/source/lang/api/toggleled.rst b/docs/source/lang/api/toggleled.rst new file mode 100644 index 0000000..0cc20c2 --- /dev/null +++ b/docs/source/lang/api/toggleled.rst @@ -0,0 +1,17 @@ +.. _lang-toggleled: + +toggleLED() +=========== + +Switches the LED from off to on, or on to off. + +Library Documentation +--------------------- + +.. doxygenfunction:: toggleLED + +See Also +-------- + +- :ref:`BOARD_LED_PIN ` +- :ref:`togglePin() ` diff --git a/docs/source/lang/api/togglepin.rst b/docs/source/lang/api/togglepin.rst new file mode 100644 index 0000000..290718d --- /dev/null +++ b/docs/source/lang/api/togglepin.rst @@ -0,0 +1,17 @@ +.. _lang-togglepin: + +togglePin() +=========== + +Switches a digital output pin from :ref:`HIGH ` +to :ref:`LOW `, or from LOW to HIGH. + +Library Documentation +--------------------- + +.. doxygenfunction:: togglePin + +See Also +-------- + +- :ref:`toggleLED() ` diff --git a/docs/source/lang/api/waitforbuttonpress.rst b/docs/source/lang/api/waitforbuttonpress.rst new file mode 100644 index 0000000..34c5066 --- /dev/null +++ b/docs/source/lang/api/waitforbuttonpress.rst @@ -0,0 +1,17 @@ +.. _lang-waitforbuttonpress: + +waitForButtonPress() +==================== + +Wait for the board's built-in button (labeled BUT on the silkscreen) +to be pressed, possibly with timeout. + +Library Documentation +--------------------- + +.. doxygenfunction:: waitForButtonPress + +See Also +-------- + +- :ref:`lang-isbuttonpressed` diff --git a/docs/source/lang/cpp/built-in-types.rst b/docs/source/lang/cpp/built-in-types.rst new file mode 100644 index 0000000..1323db8 --- /dev/null +++ b/docs/source/lang/cpp/built-in-types.rst @@ -0,0 +1,95 @@ +.. highlight:: cpp + +.. _lang-built-in-types: + +================ + Built-in Types +================ + +This document serves as a reference for many of the built-in types +which are available when programming in the IDE. Programmers using +the :ref:`command-line tools ` will have access to +these types as long as they have imported `wirish.h +`_; +several are defined in in `libmaple_types.h +`_. + +.. _lang-built-in-types-integral: + +Integral types +-------------- + +.. cpp:type:: char + + 8-bit integer value. + +.. cpp:type:: short + + 16-bit integer value. + +.. cpp:type:: int + + 32-bit integer value. + +.. cpp:type:: long + + 64-bit integer value. + +.. cpp:type:: long long + + 64-bit integer value. + +.. cpp:type:: int8 + + Synonym for ``char``. + +.. cpp:type:: uint8 + + Synonym for ``unsigned char``. + +.. cpp:type:: int16 + + Synonym for ``short``. + +.. cpp:type:: uint16 + + Synonym for ``unsigned short``. + +.. cpp:type:: int32 + + Synonym for ``int``. + +.. cpp:type:: uint32 + + Synonym for ``unsigned int`` + +.. cpp:type:: int64 + + Synonym for ``long long`` + +.. cpp:type:: uint64 + + Synonym for ``unsigned long long``. + +Floating-Point Types +-------------------- + +.. cpp:type:: float + + 32-bit, IEEE 754 single-precision floating-point type. + +.. cpp:type:: double + + 64-bit, IEEE 754 double-precision floating-point type. + +Other Types +----------- + +.. cpp:type:: voidFuncPtr + + Pointer to a function that takes no arguments and returns nothing, i.e. + + :: + + typedef void (*voidFuncPtr)(void); + diff --git a/docs/source/lang/cpp/keywords.rst b/docs/source/lang/cpp/keywords.rst index e4ebe99..e3bc20d 100644 --- a/docs/source/lang/cpp/keywords.rst +++ b/docs/source/lang/cpp/keywords.rst @@ -94,7 +94,7 @@ The following keywords are used for built-in types. - :ref:`lang-float` - :ref:`lang-int` - :ref:`lang-long` -- :ref:`short ` +- :ref:`short ` - :ref:`void ` (not really a type, but used in the absence of one) diff --git a/docs/source/lang/cpp/numeric-types.rst b/docs/source/lang/cpp/numeric-types.rst deleted file mode 100644 index 9d2be48..0000000 --- a/docs/source/lang/cpp/numeric-types.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. _lang-numeric-types: - -Numeric types -============= - -This document serves as a reference for all of the built-in numeric -types which are available when programming in the IDE. Programmers -using the :ref:`command-line tools ` will have access -to these types as long as they have imported ``wirish.h``; several are -defined in in `libmaple_types.h -`_. - -.. _lang-numeric-types-integral: - -Integral types --------------- - -.. cpp:type:: char - - 8-bit integer value. - -.. cpp:type:: short - - 16-bit integer value. - -.. cpp:type:: int - - 32-bit integer value. - -.. cpp:type:: long - - 64-bit integer value. - -.. cpp:type:: long long - - 64-bit integer value. - -.. cpp:type:: int8 - - Synonym for ``char``. - -.. cpp:type:: uint8 - - Synonym for ``unsigned char``. - -.. cpp:type:: int16 - - Synonym for ``short``. - -.. cpp:type:: uint16 - - Synonym for ``unsigned short``. - -.. cpp:type:: int32 - - Synonym for ``int``. - -.. cpp:type:: uint32 - - Synonym for ``unsigned int`` - -.. cpp:type:: int64 - - Synonym for ``long long`` - -.. cpp:type:: uint64 - - Synonym for ``unsigned long long``. - -Floating-Point Types --------------------- - -.. cpp:type:: float - - 32-bit, IEEE 754 single-precision floating-point type. - -.. cpp:type:: double - - 64-bit, IEEE 754 double-precision floating-point type. diff --git a/docs/source/lang/cpp/variables.rst b/docs/source/lang/cpp/variables.rst index 9094cd5..e6da0c9 100644 --- a/docs/source/lang/cpp/variables.rst +++ b/docs/source/lang/cpp/variables.rst @@ -37,7 +37,7 @@ named ``inputVariable2``, with an initial value of ``0``:: int inputVariable2 = 0; The Maple environment comes ready to use with many useful types of -variables. See the :ref:`built-in types ` page +variables. See the :ref:`built-in types ` page for more information. Here are a few examples of declaring variables of different types:: @@ -116,7 +116,7 @@ he goes past the left side of the screen, he reappears on the right:: x = x + 1; // x now contains -2,147,483,648; rolled over "right to left" Each numeric type's reference page includes its range. See the -:ref:`built-in types ` reference for links to each +:ref:`built-in types ` reference for links to each type's reference page. Using Variables @@ -149,7 +149,7 @@ See Also -------- - :ref:`lang-scope` -- :ref:`lang-numeric-types` +- :ref:`lang-built-in-types` .. rubric:: Footnotes diff --git a/docs/source/lang/cpp/void.rst b/docs/source/lang/cpp/void.rst index 88bd448..88c9c64 100644 --- a/docs/source/lang/cpp/void.rst +++ b/docs/source/lang/cpp/void.rst @@ -5,10 +5,12 @@ ``void`` ======== -The ``void`` keyword is used only in function declarations. It -indicates that the function is expected to return no information to -the function from which it was called, or that it expects no arguments -from its caller. +.. cpp:type:: void + + The ``void`` keyword is used in function declarations. It indicates + that the function is expected to return no information to the + function from which it was called, or that it expects no arguments + from its caller. Example ------- diff --git a/docs/source/lang/unimplemented/interrupts.rst b/docs/source/lang/unimplemented/interrupts.rst deleted file mode 100644 index 55b8e93..0000000 --- a/docs/source/lang/unimplemented/interrupts.rst +++ /dev/null @@ -1,59 +0,0 @@ -.. _lang-interrupts: - -interrupts() -============ - -Re-enables interrupts (after they've been disabled by -`noInterrupts `_\ ()). -Interrupts allow certain important tasks to happen in the -background and are enabled by default. Some functions will not work -while interrupts are disabled, and incoming communication may be -ignored. Interrupts can slightly disrupt the timing of code, -however, and may be disabled for particularly critical sections of -code. - - - -Parameters ----------- - -None - - - -Returns -------- - -None - - - -Example -------- - -:: - - void setup() {} - - void loop() - { - noInterrupts(); - // critical, time-sensitive code here - interrupts(); - // other code here - } - - - -See Also --------- - - -- `noInterrupts `_\ () -- `attachInterrupt `_\ () -- `detachInterrupt `_\ () - - - - -.. include:: /lang/cc-attribution.txt diff --git a/docs/source/lang/unimplemented/nointerrupts.rst b/docs/source/lang/unimplemented/nointerrupts.rst deleted file mode 100644 index fb2e5f9..0000000 --- a/docs/source/lang/unimplemented/nointerrupts.rst +++ /dev/null @@ -1,59 +0,0 @@ -.. _lang-nointerrupts: - -noInterrupts() -============== - -Description ------------ - -Disables interrupts (you can re-enable them with interrupts()). -Interrupts allow certain important tasks to happen in the -background and are enabled by default. Some functions will not work -while interrupts are disabled, and incoming communication may be -ignored. Interrupts can slightly disrupt the timing of code, -however, and may be disabled for particularly critical sections of -code. - - - -Parameters ----------- - -None. - - - -Returns -------- - -None. - - - -Example -------- - -:: - - void setup() {} - - void loop() - { - noInterrupts(); - // critical, time-sensitive code here - interrupts(); - // other code here - } - - - -See Also --------- - - -- `interrupts `_\ () - - - - -.. include:: /lang/cc-attribution.txt diff --git a/docs/source/language-index.rst b/docs/source/language-index.rst index 7843cb0..e160e2b 100644 --- a/docs/source/language-index.rst +++ b/docs/source/language-index.rst @@ -4,37 +4,37 @@ Complete Language Index ======================= -This is the index of Maple's :ref:`language reference ` documentation. The 'Maple API' column includes language specific to Maple as a microcontroller development platform, while the language in 'C++ for Maple' is more generally applied. - -# Fix above explanation +This is the index of Maple's :ref:`language reference +` documentation. The "Maple API" column provides +API references for documented libmaple functionality. The "C++ for +Maple".. pages are adaptations of the Arduino C++ documentation to the +.. Maple, and are intended as a minimal reference/refresher for +.. programmers familiar with the Arduino language. .. _index-language-index-cpp: .. _index-language-index-api: -+--------------------------------------------+----------------------------------------------+ -| Maple API | :ref:`C++ for Maple ` | -| | | -+============================================+==============================================+ -| | | -| .. toctree:: | .. toctree:: | -| :maxdepth: 1 | :maxdepth: 1 | -| :glob: | :glob: | -| | | -| lang/api/* | lang/cpp/* | -| | | -+--------------------------------------------+----------------------------------------------+ - -.. Unfinished, unimplemented in libmaple: ++----------------------------------+------------------------------------+ +| Maple API | C++ for Maple | +| | | ++==================================+====================================+ +| | | +| .. toctree:: | .. toctree:: | +| :maxdepth: 1 | :maxdepth: 1 | +| :glob: | :glob: | +| | | +| lang/api/* | lang/cpp/* | +| | | ++----------------------------------+------------------------------------+ + +.. Unimplemented in libmaple or not part of current release: .. toctree:: :hidden: - lang/unimplemented/interrupts.rst - lang/unimplemented/nointerrupts.rst lang/unimplemented/notone.rst lang/unimplemented/pulsein.rst lang/unimplemented/shiftout.rst lang/unimplemented/stringclass.rst lang/unimplemented/stringobject.rst lang/unimplemented/tone.rst - diff --git a/docs/source/language.rst b/docs/source/language.rst index 8e5d454..018eb8c 100644 --- a/docs/source/language.rst +++ b/docs/source/language.rst @@ -52,8 +52,8 @@ Unique Maple Additions Maple Language Reference ------------------------ -The following table summarizes the available language features. A -more exhaustive index is available at the :ref:`language-index`. +The following table summarizes the available core language features. +A more exhaustive index is available at the :ref:`language-index`. +--------------------------------------------+----------------------------------------------+---------------------------------------------------+ | Structure | Variables | Functions | @@ -67,129 +67,129 @@ more exhaustive index is available at the :ref:`language-index`. |**Control Structures** |* :ref:`INPUT ` | | | | | :ref:`OUTPUT ` |* :ref:`digitalRead() ` | |* :ref:`if/else ` | | | -| |* :ref:`true ` | | | -|* :ref:`for ` | :ref:`false ` |**Analog I/O** | +| |* :ref:`true ` | |* :ref:`togglePin() ` | +|* :ref:`for ` | :ref:`false ` | | +| | |* :ref:`toggleLED() ` | +|* :ref:`switch/case ` |* :ref:`BOARD_LED_PIN ` | | | +| | :ref:`BOARD_BUTTON_PIN `|* :ref:`isButtonPressed() ` | +|* :ref:`while ` | | | +| |* :ref:`Constants |* :ref:`waitForButtonPress() | +|* :ref:`do...while ` | ` (:ref:`integers | ` | +| | `, :ref:`floating | | +|* :ref:`break ` | point `) |**Analog I/O** | | | | | -|* :ref:`switch/case ` |* :ref:`Constants |* :ref:`analogRead() ` | -| | ` (:ref:`integers | | -|* :ref:`while ` | `, :ref:`floating |* :ref:`pwmWrite() ` | -| | point `) | (:ref:`analogWrite() ` is | -|* :ref:`do...while ` | | also available, though its use is discouraged) | -| |**Data Types** | | -|* :ref:`break ` | | | -| | The size of each datatype, in bytes, is |**Advanced I/O** | -|* :ref:`continue ` | given in parentheses where appropriate. | | -| | |* tone(): TODO | -|* :ref:`return ` | *Note*: The ``word`` type is (deliberately) | | -| | :ref:`not supported `. |* noTone(): TODO | -|* :ref:`goto ` | | | -| |* :ref:`void ` |* shiftOut(): TODO | +|* :ref:`continue ` |**Data Types** |* :ref:`analogRead() ` | | | | | -|**Further syntax** |* :ref:`boolean ` (1 byte) |* pulseIn(): TODO | +|* :ref:`return ` | The size of each datatype, in bytes, is |* :ref:`pwmWrite() ` | +| | given in parentheses where appropriate. | (:ref:`analogWrite() ` is | +|* :ref:`goto ` | | also available, though its use is discouraged) | +| | *Note*: The ``word`` type is (deliberately) | | +| | :ref:`not supported `. | | +|**Further syntax** | |**Advanced I/O** | +| |* :ref:`void ` | | +|* :ref:`; (semicolon) ` | |* tone(): TODO | +| |* :ref:`boolean ` (1 byte) | | +|* :ref:`{} (curly braces) | |* noTone(): TODO | +| ` |* :ref:`char ` (1 byte) | | +| | |* shiftOut(): TODO | +|* :ref:`// (single-line comment) |* :ref:`unsigned char | | +| ` | ` (1 byte) |* pulseIn(): TODO | | | | | -|* :ref:`; (semicolon) ` |* :ref:`char ` (1 byte) | | -| | |**Time** | -|* :ref:`{} (curly braces) |* :ref:`unsigned char | | -| ` | ` (1 byte) |* :ref:`millis() ` | +|* :ref:`/\* \*/ (multi-line comment) |* :ref:`byte ` (1 byte) | | +| ` | |**Time** | +| |* :ref:`int ` (4 bytes) | | +|* :ref:`#define ` | |* :ref:`millis() ` | +| |* :ref:`unsigned int ` | | +|* :ref:`#include ` | (4 bytes) |* :ref:`micros() ` | | | | | -|* :ref:`// (single-line comment) |* :ref:`byte ` (1 byte) |* :ref:`micros() ` | -| ` | | | -| |* :ref:`int ` (4 bytes) |* :ref:`delay() ` | -|* :ref:`/\* \*/ (multi-line comment) | | | -| ` |* :ref:`unsigned int ` |* :ref:`delayMicroseconds() | -| | (4 bytes) | ` | -|* :ref:`#define ` | | | -| |* :ref:`long ` (8 bytes) | | -|* :ref:`#include ` | |**Math** | -| |* :ref:`unsigned long ` | | -| | (8 bytes) |* :ref:`min() ` | +| |* :ref:`long ` (8 bytes) |* :ref:`delay() ` | |**Arithmetic Operators** | | | -| |* :ref:`float ` (4 bytes) |* :ref:`max() ` | -|* :ref:`= ` | | | -| (assignment operator) |* :ref:`double ` (8 bytes) |* :ref:`abs() ` | +| |* :ref:`unsigned long ` |* :ref:`delayMicroseconds() | +|* :ref:`= ` | (8 bytes) | ` | +| (assignment operator) | | | +| |* :ref:`float ` (4 bytes) | | +|* :ref:`+ ` (addition) | |**Math** | +| |* :ref:`double ` (8 bytes) | | +|* :ref:`- ` | |* :ref:`min() ` | +| (subtraction) |* :ref:`Strings ` | | +| | |* :ref:`max() ` | +|* :ref:`* ` |* :ref:`Arrays ` | | +| (multiplication) | |* :ref:`abs() ` | +| |* :ref:`enum ` | | +|* :ref:`/ ` (division) | |* :ref:`constrain() ` | +| |* :ref:`Numeric types ` | | +|* :ref:`% ` (modulo) | |* :ref:`map() ` | +| |**Conversion** | | +| | |* :ref:`pow() ` | +|**Comparison Operators** |* :ref:`char() ` | | +| | |* :ref:`sqrt() ` | +|* :ref:`== ` (equal to) |* :ref:`byte() ` | | | | | | -|* :ref:`+ ` (addition) |* :ref:`Strings ` |* :ref:`constrain() ` | +|* :ref:`\!= ` |* :ref:`int() ` |**Trigonometry** | +| (not equal to) | | | +| |* :ref:`long() ` |* :ref:`sin() ` | +|* :ref:`< ` (less than) | | | +| |* :ref:`float() ` |* :ref:`cos() ` | +|* :ref:`> ` | | | +| (greater than) |* :ref:`double() ` |* :ref:`tan() ` | | | | | -|* :ref:`- ` |* :ref:`Arrays ` |* :ref:`map() ` | -| (subtraction) | | | -| |* :ref:`enum ` |* :ref:`pow() ` | -|* :ref:`* ` | | | -| (multiplication) |* :ref:`Numeric types ` |* :ref:`sqrt() ` | +|* :ref:`<= ` | | | +| (less than or equal to) |**Variable Scope & Qualifiers** |**Random Numbers** | | | | | -|* :ref:`/ ` (division) |**Conversion** | | -| | |**Trigonometry** | -|* :ref:`% ` (modulo) |* :ref:`char() ` | | -| | |* :ref:`sin() ` | -| |* :ref:`byte() ` | | -|**Comparison Operators** | |* :ref:`cos() ` | -| |* :ref:`int() ` | | -|* :ref:`== ` (equal to) | |* :ref:`tan() ` | -| |* :ref:`long() ` | | -|* :ref:`\!= ` | | | -| (not equal to) |* :ref:`float() ` |**Random Numbers** | +|* :ref:`>= ` |* :ref:`variables `, |* :ref:`randomSeed() ` | +| (greater than or equal to) | :ref:`scope ` | | +| | |* :ref:`random() ` | +| |* :ref:`static ` | | +|**Boolean Operators** | | | +| |* :ref:`volatile ` |**Bits and Bytes** | +|* :ref:`&& ` (and) | | | +| |* :ref:`const ` |* :ref:`lowByte() ` | +|* :ref:`|| ` (or) | | | +| | |* :ref:`highByte() ` is | +|* :ref:`\! ` (not) |**Utilities** | provided, though its use is discouraged. | | | | | -|* :ref:`< ` (less than) |* :ref:`double() ` |* :ref:`randomSeed() ` | -| | | | -|* :ref:`> ` | |* :ref:`random() ` | -| (greater than) |**Variable Scope & Qualifiers** | | -| | | | -|* :ref:`<= ` |* :ref:`variables `, |**Bits and Bytes** | -| (less than or equal to) | :ref:`scope ` | | -| | |* :ref:`lowByte() ` | -|* :ref:`>= ` |* :ref:`static ` | | -| (greater than or equal to) | |* :ref:`highByte() ` is | -| |* :ref:`volatile ` | provided, though its use is discouraged. | -| | | | -|**Boolean Operators** |* :ref:`const ` |* :ref:`bitRead() ` | -| | | | -|* :ref:`&& ` (and) | |* :ref:`bitWrite() ` | -| |**Utilities** | | -|* :ref:`|| ` (or) | |* :ref:`bitSet() ` | -| |* :ref:`sizeof() ` | | -|* :ref:`\! ` (not) | |* :ref:`bitClear() ` | -| | | | -| | |* :ref:`bit() ` | +| |* :ref:`sizeof() ` |* :ref:`bitRead() ` | |**Pointer Operators** | | | +| | |* :ref:`bitWrite() ` | +|* :ref:`* dereference operator | | | +| ` | |* :ref:`bitSet() ` | | | | | -|* :ref:`* dereference operator | |**External Interrupts** | +|* :ref:`& reference operator | |* :ref:`bitClear() ` | | ` | | | -| | |* :ref:`Reference Page ` | -|* :ref:`& reference operator | | | -| ` | |* :ref:`attachInterrupt() | -| | | ` | +| | |* :ref:`bit() ` | | | | | -|**Bitwise Operators** | |* :ref:`detachInterrupt() | -| | | ` | +|**Bitwise Operators** | | | +| | |**External Interrupts** | |* :ref:`& ` | | | -| (bitwise and) | | | -| | |**Interrupts** | -|* :ref:`| ` | | | -| (bitwise or) | |* interrupts(): TODO | +| (bitwise and) | |* :ref:`Reference Page ` | | | | | -|* :ref:`^ ` | |* noInterrupts(): TODO | -| (bitwise xor) | | | +|* :ref:`| ` | |* :ref:`attachInterrupt() | +| (bitwise or) | | ` | | | | | -|* :ref:`~ ` | |**Communication** | -| (bitwise not) | | | -| | |* :ref:`SerialUSB ` | -|* :ref:`\<\< ` | | | -| (shift left) | |* :ref:`Serial ` | +|* :ref:`^ ` | |* :ref:`detachInterrupt() | +| (bitwise xor) | | ` | | | | | -|* :ref:`>> ` | |**Looking for something else?** | -| (shift right) | | | -| | | See the :ref:`libraries` page for interfacing with| -| | | particular types of hardware. Maple links | -|**Compound Operators** | | against `newlib `_ | -| | | and allows the use of any of its functions; see | -|* :ref:`++ ` | | its documentation for more details. | -| (increment) | | | +|* :ref:`~ ` | | | +| (bitwise not) | |**Interrupts** | | | | | -|* :ref:`- - ` | | | -| (decrement) | | | +|* :ref:`\<\< ` | |* :ref:`interrupts() ` | +| (shift left) | | | +| | |* :ref:`noInterrupts() ` | +|* :ref:`>> ` | | | +| (shift right) | | | +| | |**Communication** | | | | | -|* :ref:`+= ` | | | -| (compound add) | | | +|**Compound Operators** | |* :ref:`SerialUSB ` | | | | | +|* :ref:`++ ` | |* :ref:`Serial ` | +| (increment) | | | +| | |**Looking for something else?** | +|* :ref:`- - ` | | | +| (decrement) | | See the :ref:`libraries` page for interfacing with| +| | | particular types of hardware. Maple links | +|* :ref:`+= ` | | against `newlib `_ | +| (compound add) | | and allows the use of any of its functions; see | +| | | its documentation for more details. | |* :ref:`-= | | | | ` (compound | | | | subtract) | | | @@ -222,6 +222,8 @@ more exhaustive index is available at the :ref:`language-index`. Missing Arduino Features ------------------------ +.. _langage-missing-analogreference: + **analogReference()** It is not possible to implement this function on the Maple @@ -256,8 +258,6 @@ Unimplemented Arduino Features The following Wiring/Arduino features are currently unimplemented on the Maple. However, they will be present in future versions: -- `interrupts() `_ -- `noInterrupts() `_ - `noTone() `_ - `pulseIn() `_ - `shiftOut() `_ @@ -272,7 +272,11 @@ the Maple. However, they will be present in future versions: C++ for Maple -------------- -If you haven't programmed in C++, or if you just need to jog your memory, you may want to check out our :ref:`C++ for Maple Index`. It covers programming ideas and C++ that will definitely come in handy. + +If you haven't programmed in C++, or if you just need to jog your +memory, you may want to check out our :ref:`Language Index +`. It provides some introductory coverage of +programming ideas and C++. .. _arduino_c_for_c_hackers: @@ -366,9 +370,7 @@ contains ``setup()`` and ``loop()``:: } void loop() { - static int toggle = 0; - toggle ^= 1; - digitalWrite(the_pin, toggle); + togglePin(the_pin); } The second file contains the (not very useful) implementation for @@ -388,9 +390,7 @@ Then the results of the concatenation process might be :: } void loop() { - static int toggle = 0; - toggle ^= 1; - digitalWrite(the_pin, toggle); + togglePin(the_pin); } int choose_a_pin(void); @@ -415,9 +415,7 @@ Which could plausibly be turned into the final source file :: } void loop() { - static int toggle = 0; - toggle ^= 1; - digitalWrite(the_pin, toggle); + togglePin(the_pin); } int choose_a_pin(void); @@ -441,7 +439,6 @@ Recommended Reading * `newlib Documentation `_ * STMicro documentation for STM32F103RB microcontroller: - * `All documents `_ * `Datasheet `_ (pdf) * `Reference Manual `_ (pdf) * `Programming Manual `_ (assembly language and register reference) diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 567aec8..7623963 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -21,13 +21,69 @@ in the description of the library. .. contents:: Contents :local: +.. toctree:: + :hidden: + + libs/servo.rst + +.. _libraries-servo: + +Servo +----- + +The Servo library is provided for convenient control of RC +servomotors. For more information, see the :ref:`Servo ` +reference. + +**Compatibility Note** + +The Servo class provides a public interface identical to the Arduino +version's documented functionality (as of Arduino 0021), so in most +cases, this library will be a drop-in replacement. + +However, there are some differences, essentially at the level of +implementation details. + +The major difference is that while the Arduino implementation drives +the servos with "bit-banged" :ref:`PWM `, the Maple +implementation uses :ref:`timers ` to drive the PWM directly. + +Consequently, **the Maple implementation only allows Servo instances +to** :ref:`attach ` **to pins that support PWM**. + +To determine if a pin supports PWM (15 Maple pins do), you can either +check if "PWM" appears next to its number on the Maple silkscreen, or +consult the :ref:`pwmWrite() ` documentation. + +RC Servos expect a pulse approximately every 20ms. In the Maple +implementation, :ref:`periods ` are set +for entire timers, rather than individual channels. Thus, +``attach()``\ ing a Servo to a pin can interfere with other pins +associated with the same timer\ [#fard-servo]_. + +Because of this, we recommend connecting multiple servomotors to pins +which share a timer, in order to keep as many timers free for other +purposes as possible. Consult the :ref:`table provided in the timers +reference ` to match up pins and timer +channels. + +Another difference: although it is not publicly documented to do so, +the Arduino implementation of `attach() +`_ returns the timer +channel associated with the newly-attached pin, or 0 on failure (as of +Arduino 0021). The Maple implementation returns true on success, and +false on failure (and this is its documented behavior). + .. _libraries-liquid-crystal: LiquidCrystal ------------- +.. TODO 0.0.10 make our own LiquidCrystal docs + The LiquidCrystal library allows Maple to control LCD screens. For -more information, see the Arduino LiquidCrystal documentation. +more information, see the `Arduino LiquidCrystal documentation +`_. **Compatibility Note** @@ -57,6 +113,8 @@ the hardware i2c peripheral on the stm32 as well as the DMA for performance. Support for slave, smBUS, and multimaster modes are also slated for inclusion in the enhanced Wire port. +.. TODO 0.0.10 Wire docs in the cpp domain in own page under /libs/ + Wire Function Reference ^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,3 +185,10 @@ Wire Function Reference Returns the number of bytes which are still available for reading (with ``Wire.receive()``) from the last call to ``Wire.requestFrom(uint8, int)``. + +.. rubric:: Footnotes + +.. [#fard-servo] The Arduino implementation also captures timer + channels in groups as more Servo objects are attached, but the + details of which channels have their periods reset when are + slightly different. diff --git a/docs/source/libs/servo.rst b/docs/source/libs/servo.rst new file mode 100644 index 0000000..f92fd91 --- /dev/null +++ b/docs/source/libs/servo.rst @@ -0,0 +1,108 @@ +.. highlight:: cpp + +.. _libs-servo: + +======= + Servo +======= + +This documents the Servo library for controlling RC servomotors. It +is implemented as a thin layer over the built-in :ref:`timer +peripherals `. + +You can use this library in the :ref:`IDE ` by choosing the Servo +item under the Sketch > Import Library... menu. + +If you are using the :ref:`Unix toolchain `, the +library is located in ``$LIB_MAPLE_HOME/libraries/Servo/``. + +Servo Class Reference +--------------------- + +You can construct a Servo object by including the declaration :: + + Servo servo; + +in your sketch. This will create a Servo object called ``servo``. +You can then use any of its methods; for instance, to control a +servomotor attached to pin 9, you could write :: + + servo.attach(9); + +.. cpp:class:: Servo + + Class for controlling RC servomotors via :ref:`timers `. + +.. _libs-servo-attach: + +.. cpp:function:: bool Servo::attach(uint8 pin, uint16 min, uint16 max) + + Attach this Servo object to the given ``pin``. The pin must be + capable of PWM. You can check this by seeing if "PWM" is written + next to its number on the Maple silkscreen, or by consulting the + :ref:`pwmWrite() ` documentation. + + Sets this pin's :ref:`mode ` to :ref:`PWM + `, and returns true if successful. + Does nothing and returns false if the pin doesn't support PWM. + + Parameter ``min`` is the pulse width corresponding to 0 degrees; + ``max`` is the pulse width corresponding to 180 degrees (both are + in microseconds). + +.. cpp:function:: bool Servo::attach(uint8 pin) + + Equivalent to :ref:`attach(pin, 544, 2400) `. + +.. _libs-servo-attached: + +.. cpp:function:: int Servo::attached() const + + If currently attached (via :ref:`attach() `) to + a pin, returns that pin's number. Returns ``NOT_ATTACHED`` + otherwise. + +.. cpp:function:: bool Servo::detach() + + If this Servo object is currently attached to pin, stops driving + the servo by setting a zero pulse width (this is accomplished by + setting the associated :ref:`channel mode + ` to ``TIMER_DISABLED``). + + Subsequently, calling :ref:`attached() ` will + return ``NOT_ATTACHED``. + +.. cpp:function:: void Servo::write(unsigned int value) + + If ``value`` is less than ``SERVO_MAX_WRITE_ANGLE`` (which, for + Arduino compatibility, is 200), it's interpreted as an angle in + degrees. Otherwise, it's treated as a pulse width in microseconds. + + Drives the servo to target the given angle, based on a linear + interpolation of the ``min`` and ``max`` pulse widths determined + when :ref:`attach() ` was called. + + Be aware that some (especially lower-cost) servos have fairly + non-linear maps between pulse width and target angle. Make sure to + test your motor before relying on this method. + +.. cpp:function:: void Servo::writeMicroseconds(uint16 pulseWidth) + + Drives the servo using a ``pulseWidth``-microsecond pulse. + + If ``pulseWidth`` is outside of the [``min``, ``max``\ ] pulse + width range set during :ref:`attach() `, it will + be clamped to lie in this range. + +.. cpp:function:: int Servo::read() const + + Returns the servo's target angle, in degrees. This will be clamped + to lie between 0 (when the pulse width is at most ``min``) and 180 + (when the pulse width is at least ``max``). + +.. cpp:function:: uint16 Servo::readMicroseconds() const + + Returns the pulse width of the wave currently driving the servo, in + microseconds. This will be clamped to lie in the [``min``, + ``max``\ ] pulse width range set during :ref:`attach() + `. diff --git a/docs/source/pwm.rst b/docs/source/pwm.rst index fd72842..1a8f4df 100644 --- a/docs/source/pwm.rst +++ b/docs/source/pwm.rst @@ -28,9 +28,9 @@ Note that unlike the Arduino, the Maple does not have PWM functionality on pin D10; all other pins are :ref:`compatible `. -The following table shows which :ref:`timer ` generates which -PWM outputs. See the :ref:`pin mapping table ` -to track down exactly which timer *channel* corresponds to each pin. +The following table shows which timer can generate which PWM +outputs. See the :ref:`pin mapping table ` to +track down exactly which timer *channel* corresponds to each pin. .. _pwm-timer-table: @@ -65,12 +65,13 @@ The Maple has 16-bit PWM resolution, which means that the counter and variables can be as large as 65535, as opposed to 255 with 8-bit resolution. With a 72MHz clock rate, a PWM output could have maximum period of about one millisecond; using a :ref:`prescaler -` (clock divider) in front of the counter can increase -this maximum period. Setting the :ref:`period ` to -something other than the maximum value gives further control over the -total length of the waveform. However, this effectively limits the -resolution with which the duty can be modified: the duty must be less -than or equal to the period. +` (clock divider) in front of +the counter can increase this maximum period. Setting the +:ref:`period ` to something other than +the maximum value gives further control over the total length of the +waveform. However, this effectively limits the resolution with which +the duty can be modified: the duty must be less than or equal to the +period. Here are some commonly used PWM configurations (note that servos are notoriously variable, especially the lower cost models): @@ -93,82 +94,13 @@ notoriously variable, especially the lower cost models): Function Reference ------------------ -``pinMode(pin_num, PWM)`` - - This command is usually called from :ref:`setup() ` to - tell the microcontroller that pin_num should be configured to PWM - output. ``PWM`` implies regular driven OUTPUT; ``PWM_OPEN_DRAIN`` - is also available (see the list of :ref:`GPIO modes ` - for more information). - -.. _pwm-pwmwrite: - -``pwmWrite(pin_num, value)`` - - This command sets the PWM duty. User code is expected to determine - and honor the maximum value (based on the configured period). As a - convenience, ``analogWrite`` is an alias for ``pwmWrite`` to ease - porting Arduino code, though period and duty will have to be - recalibrated (see :ref:`compatibility `). - -.. _pwm-overflow: - -``Timer[1,2,3,4].setOverflow(overflow)`` - - This function sets the period ("reload" or "overflow") value for - an entire PWM timer bank. The value is 16bit (0 to 65535) and - determines the maximum value that can be written with - :ref:`pwmWrite() ` corresponding to 100% duty - cycle. This also affects the PWM frequency: the higher reload is, - the lower the PWM frequency will be. - - The PWM output pin starts HIGH, then the timer begins counting up - from zero (with frequency equal to 72MHz/:ref:`prescaler - `) until it hits the duty value, at which point it - drops to LOW. The timer then continues counting up until it hits - the total period (set with this function), at which point the - cycle starts again. - -.. _pwm-prescaler: - -``Timer[1,2,3,4].setPrescaleFactor(prescale)`` - - Find the appropriate timer for a given PWM header using the table - :ref:`above `, then set the prescaler. A - prescaler is a clock divider. The timer will normally count with - frequency equal to the STM32's normal clock (72MHz); this - corresponds to setting ``prescale`` to 1 (which is the default). - - If a longer frequency is desired, use a larger ``prescale`` value. - For instance, an 8MHz frequency can be achieved by setting - ``prescale`` to 9, since 72MHz / 9 = 8MHz. - - This function is normally called once from, :ref:`lang-setup`, but - the timer can be reconfigured with a new prescaler at any time. - - * Configure the prescaler and overflow values to generate a timer - * reload with a period as close to the given number of - * microseconds as possible. - * - * The return value is the overflow, which may be used to set - * channel compare values. However, if a clock that fires an - * interrupt every given number of microseconds is all that is - * desired, and the relative "phases" are unimportant, channel - * compare values may all be set to 1. - -``Timer[1,2,3,4].setPeriod(period_in_microseconds)`` - - Configure the prescaler and overflow values to generate a timer - reload with a period as close to the given number of microseconds - as possible. - - The return value is the overflow, which may be used to set channel - compare values. However, if a clock that fires an interrupt every - given number of microseconds is all that is desired, and the - relative "phases" are unimportant, channel compare values may all - be set to 1. - - +- :ref:`lang-pinmode` +- :ref:`lang-pwmwrite` +- :ref:`Timer API` (especially :ref:`setOverflow() + `, :ref:`setPrescaleFactor() + `, and :ref:`setPeriod() + `). +- :ref:`Timers reference `. Recommended Reading ------------------- @@ -182,6 +114,5 @@ Recommended Reading * `So You Want To Use PWM, Eh? `_ at Non-Lexical Vocables * STMicro documentation for STM32F103RB microcontroller: - * `All `_ * `Datasheet `_ (pdf) * `Reference Manual `_ (pdf) diff --git a/docs/source/spi.rst b/docs/source/spi.rst index ca9415c..ba43eef 100644 --- a/docs/source/spi.rst +++ b/docs/source/spi.rst @@ -4,54 +4,16 @@ SPI ===== -The Maple has two SPI ports. The first has NSS on D10, MOSI on D11, -MISO on D12, and SCK on D13. The second has NSS on D31, SCK on D32, -MISO on D33, and MOSI on D34. +The Serial Peripheral Interface Bus (SPI) is a serial data transfer +protocol useful for interacting with a wide variety of hardware +peripherals. -.. _spi-speeds: +The Maple has two SPI ports. The first has NSS on D10, MOSI on +D11, MISO on D12, and SCK on D13. The second has NSS on D31, SCK on +D32, MISO on D33, and MOSI on D34. -Each port can be configured at one of the following speeds: - -* ``SPI_18MHZ``: 18 MHz -* ``SPI_9MHZ``: 9 MHz -* ``SPI_4_5MHZ``: 4.5 MHz -* ``SPI_2_25MHZ``: 2.25 MHz -* ``SPI_1_125MHZ``: 1.124 MHz -* ``SPI_562_500KHZ``: 562.500 KHz -* ``SPI_281_250KHZ``: 281.250 KHz -* ``SPI_140_625KHZ``: 140.625 KHz - -.. contents:: Contents - :local: - -Function Reference ------------------- - -``HardwareSPI Spi(number);`` - - This declaration must be included at the start of any sketch or - program that uses the SPI interface. The argument number is either - 1 or 2 and specifies which port to use. - -``Spi.begin(freq, endianness, mode)`` - - ``begin`` is usually called in :ref:`lang-setup` to configure the - baudrate of the given SPI port and to set up the header pins - appropriately. ``freq`` is one of the set listed :ref:`above - `; ``endianness`` is either ``LSBFIRST`` or - ``MSBFIRST``; mode is one of 0, 1, 2, 3, and specifies which "SPI - Mode" is used (see specification docs linked below). - -``Spi.begin()`` - - A default ``begin`` with no arguments is provided for the lazy; it - is equivalent to ``Spi.begin(SPI_1_125MHZ, MSBFIRST, 0)``. - -``Spi.send(data, size)`` - - Writes data into the port buffer to be transmitted as soon as - possible. ``data`` should be an array of type ``byte*``; ``size`` - should be the number of elements in ``data``. +The public libmaple API for managing the SPI ports is the +:ref:`HardwareSpi ` class. Recommended Reading ------------------- @@ -63,7 +25,6 @@ Recommended Reading * `Hardcore SPI on Arduino `_ by kik64 * STMicro documentation for STM32F103RB microcontroller: - * `All `_ * `Datasheet `_ (pdf) * `Reference Manual `_ (pdf) diff --git a/docs/source/timers.rst b/docs/source/timers.rst index 948805b..56dd686 100644 --- a/docs/source/timers.rst +++ b/docs/source/timers.rst @@ -8,25 +8,46 @@ Timers There are four general purpose timers in the Maple microcontroller that can be configured to generate periodic or delayed events with minimal work done by the microcontroller. For example, the :ref:`PWM -` channels, once enabled, generate regular square-wave signals on -specific output pins that will continue even if the microcontroller is -busy crunching numbers or handling communications interrupts. By -attaching interrupt handlers to these channels (instead of just -changing the voltage on an external pin), more complex events like -printing to a serial port, updating a variable, or emitting a whale -mating call can be scheduled. You can even modify the configuration of -the timer itself at a regular interval; the possibilities are endless! - -The four timers each have four separate compare channels. Each timer -is a single 16-bit counter that can be configured with both a -prescaler and an overflow value. The prescaler acts as a divider of -the 72MHz system clock; without prescaling the counter would get up to -65536 (2 to the 16th power) and roll over more than a thousand times a -second; even with the full prescaler it rolls over about once a -minute. The overflow value is the maximum value the counter will go up -to. It defaults to the full 65535; smaller values will cause the -counter to reset to zero more frequently. +` channels can generate regular square-wave signals on specific +output pins without consuming extra clock cycles. By attaching +interrupt handlers to these channels (instead of just changing the +voltage on an external pin), more complex events can be scheduled. + +.. contents:: Contents + :local: + +Introduction +------------ + +.. _timers-prescale: + +The four timers each have four separate compare channels. Each channel +has an associated 16-bit counter that can be configured with a 16-bit +prescaler and a 16-bit overflow value. The prescaler determines how +fast the counter changes, while the overflow value determines when it +gets reset. + +The prescaler acts as a divider of the 72MHz system clock. That is, +with a prescaler of 1, the channel's counter increments with a +frequency of 72MHz, rolling over (passing the maximum 16-bit unsigned +integer value of 65,535) more than a thousand times a second. With a +prescaler of 7200, it has a frequency of (72/7200) MHz = 10 KHz, +rolling over approximately every 6.55 seconds. + +The overflow value is the maximum value the counter will go up to. It +defaults to the full 65,535; smaller values will cause the counter to +reset to zero more frequently. + +Whenever a channel's counter reaches its overflow value, an "update +event" interrupt is generated. You can configure the Maple to notify +you when this takes place, by registering an interrupt handler, which +is a function that will be called when the update event occurs. + +libmaple Reference +------------------ +The libmaple API for interacting with timers is documented at the +:ref:`HardwareTimer reference `. Caveats ------- @@ -36,9 +57,18 @@ Caveats **PWM Conflicts:** Because PWM functionality on a given pin depends on the configuration of the timer and channel, you must chose your channels carefully if you want to use both timer interrupts and PWM in -the same program. Refer to the full :ref:`pin mapping table -` to match up timer channels and Maple header -pin numbers. +the same program. Refer to the following table to match up timer +channels and Maple header pin numbers: + +.. _timers-pin-channel-map: + +.. csv-table:: + :header: Timer, Ch. 1 pin, Ch. 2 pin, Ch. 3 pin, Ch. 4 pin + + ``Timer1``, 6, 7, 8, -- + ``Timer2``, 2, 3, 1, 0 + ``Timer3``, 12, 11, 27, 28 + ``Timer4``, 5, 9, 14, 24 **Overhead:** there is some overhead associated with function and interrupt calls (loading and unloading the stack, preparing state, @@ -59,7 +89,8 @@ configuration being the same. auto-reset and communications functionality. This will require that you put your Maple into :ref:`perpetual bootloader mode ` before uploading a new - program to it. + program to it (or somehow causing your program to re-enable serial + over USB using :ref:`SerialUSB.begin() `). Disabling SysTick with ``systick_disable()`` helps as well. However, calling this function will break the ``micros()`` and @@ -73,33 +104,6 @@ a handler isn't going to block other interrupts from firing (e.g. USB, Serial, SysTick) if those other interrupts are important for your program. -.. _timers-modes: - -General Timer Modes -------------------- - -``TIMER_DISABLED`` - - Exactly what it sounds like: the timer stops counting, interrupts - are not called, and no state changes are output. - -``TIMER_PWM`` - - This is the default mode for pins after initialization. See the - :ref:`PWM docs ` for more information on this mode. - - .. note:: - - ``Timer1.setChannel1Mode(TIMER_PWM)`` may not work as expected; - if you want PWM functionality on a channel, make sure you don't - set it to something else. - -``TIMER_OUTPUTCOMPARE`` - - In this mode, the timer counts from 0 to the overflow value - repeatedly; every time the counter value reaches one of the - channel compare values, the corresponding interrupt is fired. - SysTick Peripheral ------------------ @@ -111,136 +115,22 @@ VGA code, where the timing jitters are transformed into visual jags in the image. The SysTick peripheral can be disabled by calling ``systick_disable()``, and re-enabled using ``systick_resume()``. -Function Reference ------------------- - -For all of these functions, ``Timer1`` can be replaced with -``Timer2``, ``Timer3``, or ``Timer4``; the channel numbers also range -from 1 to 4. - -``Timer1.pause()``/\ ``Timer1.resume()`` - - These functions start and stop the counter without affecting the - rest of the configuration. These functions can be used during the - setup period to prevent interrupts from firing before they are - completely configured. Note that there is some function call - overhead with these functions, so they are not a perfect way to - align multiple timers to the same count value. - -``Timer1.setOverflow(val)`` - - Sets the overflow (or "reload") value for the whole timer; when - the counter reaches this value it resets to zero. Defaults to - 65535 (the largest unsigned 16bit integer); setting it to anything - lower will cause interrupts to be called more frequently (see the - setPeriod function below for a shortcut). This number sets the - maximum value for the channel compare values. - -``Timer1.setPrescaleFactor(val)`` - - The prescaler acts as a clock divider to slow down the rate at - which the counter increments. For example, the system clock rate - is 72MHz, so the counter will reach 65535 in (13.89 nanoseconds) * - (65535 counts) = (910.22 microseconds), or about a thousand times - a second. If you set the prescaler to 1098, then the clock rate is - effectively 65.56KHz, and the counter will reach 65536 in (15.25 - microseconds) * (65536 counts) = (0.999 seconds), or just about - once a second. Use the :ref:`setPeriod ` - function below if you are allergic to math! - -.. _timers-set-period: - -``Timer1.setPeriod(val)`` - - This tricky trick will configure the prescaler and overflow values - to generate a timer reload with a period as close to val - microseconds as possible. It returns the chosen overflow value, - which you can then use to set the channel compare values - appropriately: if you just want the interrupts to fire when the - clock rolls over and you don't care about the relative "phase", - you can always set the channel compare values to 1. - - Remember: a microsecond is 1/1,000,000th of a second, or 1/1,000 - of a millisecond. The prescaler itself is 16bit, so the longest - period that can be configured is 1/(72MHz) * (2^32) = (59.65 - seconds) or about a minute. You can get around this by creating an - interrupt that increments a 32-bit variable, by using the - ``millis()`` function, or by interfacing with an external - real-time-clock chip. - -``Timer1.setCount(val)``/\ ``Timer1.getCount()`` - - These functions let you mess with the counter's brains - directly. You can probably make it not work if you try! The timer - is 16bit, so ``val`` and the return value of ``getCount`` are - ``uint16``. - -``Timer1.setChannel1Mode(MODE)`` - - This sets the given channel (here 1) of the given timer (here 1) - to the given mode. See the :ref:`list above ` for - possible values; for interrupts you want ``TIMER_OUTPUTCOMPARE``. - -``Timer1.setCompare1(val)`` - - Sets the compare value for the given channel; when the counter - reaches this value the interrupt for this channel will fire if the - channel is in output compare mode and an interrupt is attached. - - By default this only changes the relative offsets between events - on a single timer ("phase"); they don't control the frequency with - which they occur. However, a common trick is to increment the - compare value manually in the interrupt handler so that the event - will fire again after the increment period. There can be a - different increment value for each channel, so this trick allows - events to be programmed at 4 different rates on a single timer! - Note that function call overhead means that the smallest increment - rate is a couple microseconds. - -.. _timers-attachinterrupt: -.. _timers-detachinterrupt: - -``Timer1.attachCompare1Interrupt(function)``/\ ``Timer1.detachCompare1Interrupt()`` - - This is how to attach or disable an interrupt handlers to timer - channels; this what will get called when the counter reaches the - compare value set with ``setCompareN(val)``. ``function`` - (sometimes referred to as an ISR: "interrupt service routine") - should be of a type that does not accept or return any values - (C/C++ programmers: ``void (function*)(void)``). They are just - like any other function in your sketch/program and must be - initialized at the top of the file and defined below. - - ``function`` should try to do what it has to do as fast as - possible. Blinking the LED, some logic, PWM updates, and Serial - writes are fine; writing to SerialUSB or waiting for user input - can take a long time and other compare interrupts won't fire. Tip: - if you have a ``delay()`` in your ISR, you're probably doing it - wrong. - - Stay vigilant here... function pointers are serious business, and - once you go down that path you'll find yourself in a `forest of - parentheses `_ before you know it. - Code Examples ------------- LED blink ^^^^^^^^^ -\ :: +:: - #define LED_PIN 13 #define LED_RATE 500000 // in microseconds; should give 0.5Hz toggles void handler_led(void); - int toggle = 0; - void setup() { // Set up the LED to blink - pinMode(LED_PIN, OUTPUT); + pinMode(BOARD_LED_PIN, OUTPUT); // Setup Timer Timer2.setChannel1Mode(TIMER_OUTPUTCOMPARE); @@ -254,16 +144,13 @@ LED blink } void handler_led(void) { - toggle ^= 1; - digitalWrite(LED_PIN, toggle); + toggleLED(); } Racing Counters ^^^^^^^^^^^^^^^ -\ :: - - #define BUTTON_PIN 38 +:: void handler_count1(void); void handler_count2(void); @@ -274,7 +161,7 @@ Racing Counters void setup() { // Set up BUT for input - pinMode(BUTTON_PIN, INPUT_PULLUP); + pinMode(BOARD_BUTTON_PIN, INPUT_PULLUP); // Setup Counting Timers Timer3.setChannel1Mode(TIMER_OUTPUTCOMPARE); @@ -302,7 +189,7 @@ Racing Counters // Run... while BUT is held, pause Count2 for(int i = 0; i<1000; i++) { - if(digitalRead(BUTTON_PIN)) { + if(digitalRead(BOARD_BUTTON_PIN)) { Timer4.pause(); } else { Timer4.resume(); diff --git a/docs/source/troubleshooting.rst b/docs/source/troubleshooting.rst index 0c10d01..f3052d9 100644 --- a/docs/source/troubleshooting.rst +++ b/docs/source/troubleshooting.rst @@ -150,7 +150,11 @@ is several times more FLASH memory available for user programs. ``No DFU capable USB device found`` ----------------------------------- -This probably means you don't have a Maple plugged in or powered on! +This probably means you don't have a Maple plugged in or powered on. +Try unplugging and plugging your Maple or pressing the RESET button. + +This can also happen if you disable the USB peripheral, e.g. using +:ref:`SerialUSB.end() `. I have multiple Maples installed; how do I know which one will get flashed? --------------------------------------------------------------------------- @@ -161,19 +165,26 @@ board. There's no solution to this problem for now: you'll have to just plug in the Maples one at a time. If this is a real problem let us know and we'll see if we can come up with a better solution. +My flash programs don't seem to stick; they behave like they are RAM! +--------------------------------------------------------------------- + +If you have uploaded a program to RAM, this will take priority over +any program subsequently uploaded to flash. We'll be removing this +bug in a later version of the bootloader. For now, you can fix this +by unplugging your Maple to clear the contents of RAM, then plugging +it back in. + +If you are using the :ref:`Unix toolchain `, Make sure +you :command:`make clean` when switching between FLASH and RAM +targets; :command:`make` isn't smart enough to rebuild everything that +needs to be for the new target. + .. _troubleshooting-shell: ===================== Command-line issues ===================== -My flash programs don't seem to stick; they behave like they are RAM! ---------------------------------------------------------------------- - -Make sure you :command:`make clean` when switching between FLASH and -RAM targets; :command:`make` isn't smart enough to rebuild everything -that needs to be for the new target. - [Linux] ``cdc_acm 3-1:1.0: no more free acm devices`` ----------------------------------------------------- diff --git a/docs/source/usart.rst b/docs/source/usart.rst index c0334a9..3beb3fc 100644 --- a/docs/source/usart.rst +++ b/docs/source/usart.rst @@ -30,6 +30,5 @@ Recommended Reading * `Arduino reference on Serial `_ * STMicro documentation for STM32F103RB microcontroller: - * `All `_ * `Datasheet `_ (pdf) * `Reference Manual `_ (pdf) diff --git a/docs/source/usb.rst b/docs/source/usb.rst index 5494b06..f502f31 100644 --- a/docs/source/usb.rst +++ b/docs/source/usb.rst @@ -39,7 +39,6 @@ Recommended Reading * Linux Kernel documentation for `USB ACM `_ and `USB Serial `_ * STMicro documentation for STM32F103RB microcontroller: - * `All documents `_ * `Datasheet `_ (pdf) * `Reference Manual `_ (pdf) * `Programming Manual `_ (pdf; assembly diff --git a/libmaple/libmaple_types.h b/libmaple/libmaple_types.h index a976a9e..8d216a8 100644 --- a/libmaple/libmaple_types.h +++ b/libmaple/libmaple_types.h @@ -45,6 +45,8 @@ typedef void (*voidFuncPtr)(void); #define __io volatile +#define ALWAYS_INLINE inline __attribute__((always_inline)) + #ifndef NULL #define NULL 0 #endif diff --git a/libmaple/timers.h b/libmaple/timers.h index 7589283..8d28f60 100644 --- a/libmaple/timers.h +++ b/libmaple/timers.h @@ -228,16 +228,16 @@ extern struct timer_dev timer_dev_table[]; /** * Initializes timer with prescale as the clock divisor. * - * @param timer Timer number. Valid values are TIMER1, TIMER2, - * TIMER3, TIMER4, and (on high-density devices) TIMER5, TIMER8. + * @param timer_num Timer number. * * @param prescale value in the range 1--65535 to use as a prescaler * for timer counter increment frequency. * + * @see timer_dev_num * @see timer_set_prescaler() * @see timer_set_mode() */ -void timer_init(timer_dev_num, uint16); +void timer_init(timer_dev_num timer_num, uint16 prescale); /** * Quickly disable all timers. Calling this function is faster than, @@ -250,34 +250,34 @@ void timer_disable_all(void); * this value is likely to be inaccurate if the counter is running * with a low prescaler. * - * @param timer the timer whose counter to return. + * @param timer_num the timer whose counter to return. * * @pre Timer has been initialized. */ -uint16 timer_get_count(timer_dev_num); +uint16 timer_get_count(timer_dev_num timer_num); /** * Sets the counter value for the given timer. * - * @param timer the timer whose counter to set. + * @param timer_num the timer whose counter to set. * * @param value the new counter value. * * @pre Timer has been initialized. */ -void timer_set_count(timer_dev_num,uint16); +void timer_set_count(timer_dev_num timer_num, uint16 value); /** * Stops the timer's counter from incrementing. Does not modify the * timer's mode or settings. * - * @param timer the timer to pause. + * @param timer_num the timer to pause. * * @see timer_resume() * * @pre Timer has been initialized. */ -void timer_pause(timer_dev_num); +void timer_pause(timer_dev_num timer_num); /** * Starts the counter for the given timer. Does not modify the @@ -285,17 +285,19 @@ void timer_pause(timer_dev_num); * first rising clock cycle after it has been re-enabled using this * function. * - * @param timer the timer to resume. + * @param timer_num the timer to resume. * * @see timer_pause() * * @pre Timer has been initialized. */ -void timer_resume(timer_dev_num); +void timer_resume(timer_dev_num timer_num); /** * Returns the prescaler for the given timer. * + * @param timer_num the timer whose prescaler to return. + * * @see timer_set_prescaler() * * @pre Timer has been initialized. @@ -308,7 +310,7 @@ uint16 timer_get_prescaler(timer_dev_num timer_num); * per clock cycle). This prescale does not take effect until the * next update event. * - * @param timer the timer whose prescaler to set. + * @param timer_num the timer whose prescaler to set. * * @param prescale the new prescaler. * @@ -331,10 +333,6 @@ uint16 timer_get_reload(timer_dev_num timer_num); * After this function returns, the timer's counter will reset to 0 * after it has reached the value max_reload. * - * @param timer the timer whose reload to set. - * - * @param max_reload the new reload value. - * * @pre Timer has been initialized. */ void timer_set_reload(timer_dev_num timer_num, uint16 max_reload); @@ -344,52 +342,32 @@ void timer_set_reload(timer_dev_num timer_num, uint16 max_reload); /** * Set the mode of an individual timer channel. * - * @param timer the timer whose channel mode to set. - * - * @param channel the channel whose mode to set (1 <= channel <= 4). - * - * @param mode the new mode value. Currently acceptable values - * include TIMER_DISABLED, TIMER_PWM, and TIMER_OUTPUTCOMPARE. Note - * that timer_disable_all() will disable all timers and all channels - * much more quickly than repeated calls to this function with mode - * TIMER_DISABLED. - * - * @see TimerMode - * * @see timer_disable_all() - * + * @see TimerMode + * @see timer_dev_num * @pre Timer has been initialized. */ -void timer_set_mode(timer_dev_num timer_num, uint8 channel_num, uint8 mode); +void timer_set_mode(timer_dev_num timer_num, uint8 channel, TimerMode mode); /** * Get the compare value for the given timer channel. * @see timer_set_compare_value() - * + * @see timer_dev_num * @pre Timer has been initialized. */ -uint16 timer_get_compare_value(timer_dev_num timer_num, uint8 channel_num); +uint16 timer_get_compare_value(timer_dev_num timer_num, uint8 channel); /** * Sets the compare value for a given timer channel. Useful for * scheduling when interrupt handlers will be called. * - * @param timer the timer whose channel compare to set. - * - * @param channel the channel whose compare to set (1 <= channel <= 4). - * - * @param compare the new compare value. This new value must be less - * than or equal to the timer's reload value. - * * @see timer_attach_interrupt() - * * @see timer_detach_interrupt() - * * @see timer_set_reload() - * + * @see timer_dev_num * @pre Timer has been initialized. */ -void timer_set_compare_value(timer_dev_num timer_num, uint8 channel_num, +void timer_set_compare_value(timer_dev_num timer_num, uint8 channel, uint16 value); /** @@ -397,44 +375,27 @@ void timer_set_compare_value(timer_dev_num timer_num, uint8 channel_num, * After this function returns, any handler attached to the given * channel will no longer be called. * - * @param timer the timer whose channel to detach the interrupt - * handler from. - * - * @param channel the channel from which to detach the interrupt handler. - * * @see timer_attach_interrupt() - * * @pre Timer has been initialized. + * @see timer_dev_num */ -void timer_detach_interrupt(timer_dev_num timer_num, uint8 channel_num); +void timer_detach_interrupt(timer_dev_num timer_num, uint8 channel); /** * Attach an interrupt handler for the given timer and channel. The - * handler will be called whenever the timer's counter reaches the - * compare value for the given timer and channel. - * - * @param timer the timer whose channel to register with an interrupt handler. - * - * @param channel the channel with which the new handler will be - * associated. timer_set_compare_value() can be used to set the value - * which the timer's counter must reach before handler is called (1 <= - * channel <= 4). - * - * @param handler the interrupt handler to call once the timer reaches - * the given channel's compare value. - * - * @pre The channel's mode must be set to TIMER_OUTPUTCOMPARE, or the - * interrupt handler will not get called. + * given ISR, handler, will be called whenever the timer's counter + * reaches the compare value for the given timer and channel. * * @see timer_set_compare_value() - * * @see timer_detach_interrupt() - * * @see timer_set_mode() - * + * @see timer_dev_num + * @see voidFuncPtr * @pre Timer has been initialized. + * @pre The channel's mode must be set to TIMER_OUTPUTCOMPARE, or the + * interrupt handler will not get called. */ -void timer_attach_interrupt(timer_dev_num timer_num, uint8 channel_num, +void timer_attach_interrupt(timer_dev_num timer_num, uint8 channel, voidFuncPtr handler); /** @@ -449,18 +410,18 @@ void timer_generate_update(timer_dev_num timer_num); /** * Turn on PWM with duty_cycle. * - * @param channel TIMERx_CHn_CCR, where x goes from 1 to NR_TIMERS, + * @param ccr TIMERx_CHn_CCR, where x goes from 1 to NR_TIMERS, * and n goes from 1 to 4. * - * @param duty_cycle 0--65535. duty_cycle=0 means always off; - * duty_cycle=65535 means always on. + * @param duty_cycle: A number between 0 and + * timer_get_compare_value(TIMERx, y), where x and y are as above. * * @pre Pin has been set to alternate function output. * * @pre Timer has been initialized. */ -static inline void timer_pwm_write_ccr(TimerCCR CCR, uint16 duty_cycle) { - *CCR = duty_cycle; +static inline void timer_pwm_write_ccr(TimerCCR ccr, uint16 duty_cycle) { + *ccr = duty_cycle; } #ifdef __cplusplus diff --git a/support/scripts/copy-to-ide b/support/scripts/copy-to-ide index 5bf52a4..c6b4c16 100755 --- a/support/scripts/copy-to-ide +++ b/support/scripts/copy-to-ide @@ -4,9 +4,7 @@ # repository. # Change this -DEST=`pwd`/../maple-ide/hardware/leaflabs/cores/maple/ - -ARCH=`uname -a` +DEST=`pwd`/../maple-ide-java/hardware/leaflabs/cores/maple FILES="LICENSE ./libmaple/*.h @@ -21,8 +19,8 @@ FILES="LICENSE ./wirish/*.cpp ./wirish/comm/*.cpp ./wirish/comm/*.h - ./support/ld/maple/ - ./support/ld/maple_native/ + ./support/ld/maple + ./support/ld/maple_native ./support/ld/libcs3-lanchon-stm32.a ./support/ld/names.inc" @@ -34,9 +32,9 @@ then exit -1 fi -echo "Then delete the old files..." -rm -r $DEST/*.c $DEST/*.cpp $DEST/*.h $DEST/*.cxx $DEST/*.ld $DEST/*.inc $DEST/*.a $DEST/maple/ $DEST/maple_native/ +echo "\nThen delete the old files..." +rm -r $DEST/*.c $DEST/*.cpp $DEST/*.h $DEST/*.cxx $DEST/*.inc $DEST/*.a $DEST/maple $DEST/maple_native -echo "Finally copy the new source files!" -cp -r $FILES $DEST +echo "\nFinally copy the new source files!" +cp -R $FILES $DEST echo "Done." diff --git a/wirish/HardwareTimer.cpp b/wirish/HardwareTimer.cpp index 92c6adf..354663e 100644 --- a/wirish/HardwareTimer.cpp +++ b/wirish/HardwareTimer.cpp @@ -221,7 +221,6 @@ HardwareTimer* getTimer(timer_dev_num timerNum) { return &Timer8; #endif default: - ASSERT(0); return 0; } } diff --git a/wirish/HardwareTimer.h b/wirish/HardwareTimer.h index c72175f..4034b1f 100644 --- a/wirish/HardwareTimer.h +++ b/wirish/HardwareTimer.h @@ -89,7 +89,7 @@ class HardwareTimer { * * Note that there is some function call overhead associated with * using this method, so using it in concert with - * HardwareTimer::resume() is not a robust way to align multiple + * HardwareTimer::pause() is not a robust way to align multiple * timers to the same count value. * * @see HardwareTimer::pause() @@ -103,7 +103,7 @@ class HardwareTimer { uint16 getPrescaleFactor(); /** - * Set the timer prescale. + * Set the timer's prescale factor. * * The prescaler acts as a clock divider to slow down the rate at * which the counter increments. @@ -155,7 +155,7 @@ class HardwareTimer { * Set the current timer count. * * Note that there is some function call overhead associated with - * callign this method, so using it is not a robust way to get + * calling this method, so using it is not a robust way to get * multiple timers to share a count value. * * @param val The new count value to set. If this value exceeds @@ -184,10 +184,6 @@ class HardwareTimer { /** * Set the given channel of this timer to the given mode. * - * Note: Timer1.setChannel1Mode(TIMER_PWM) may not work as - * expected; if you want PWM functionality on a channel make sure - * you don't set it to something else! - * * @param channel Timer channel, from 1 to 4 * @param mode Mode to set */ @@ -228,24 +224,24 @@ class HardwareTimer { */ uint16 getCompare(int channel); - /** Like getCompare(1) */ + /** Equivalent to getCompare(1) */ uint16 getCompare1(); - /** Like getCompare(2) */ + /** Equivalent to getCompare(2) */ uint16 getCompare2(); - /** Like getCompare(3) */ + /** Equivalent to getCompare(3) */ uint16 getCompare3(); - /** Like getCompare(4) */ + /** Equivalent to getCompare(4) */ uint16 getCompare4(); /** * Sets the compare value for the given channel. * * When the counter reaches this value the interrupt for this - * channel will fire if channel 1 mode is TIMER_OUTPUTCOMPARE and - * an interrupt is attached. + * channel will fire if the channel mode is TIMER_OUTPUTCOMPARE + * and an interrupt is attached. * * By default, this only changes the relative offsets between * events on a single timer ("phase"); they don't control the @@ -259,32 +255,33 @@ class HardwareTimer { * few microseconds. * * @param channel the channel whose compare to set, from 1 to 4. - * @param val The compare value to set. If greater than this - * timer's overflow value, it will be truncated to the - * overflow value. + * @param compare The compare value to set. If greater than this + * timer's overflow value, it will be truncated to + * the overflow value. * * @see TimerMode * @see HardwareTimer::setChannelMode() + * @see HardwareTimer::attachInterrupt() */ void setCompare(int channel, uint16 compare); /** - * Like setCompare(1, compare). + * Equivalent to setCompare(1, compare). */ void setCompare1(uint16 compare); /** - * Like setCompare(2, compare). + * Equivalent to setCompare(2, compare). */ void setCompare2(uint16 compare); /** - * Like setCompare(3, compare). + * Equivalent to setCompare(3, compare). */ void setCompare3(uint16 compare); /** - * Like setCompare(4, compare). + * Equivalent to setCompare(4, compare). */ void setCompare4(uint16 compare); @@ -313,25 +310,25 @@ class HardwareTimer { void attachInterrupt(int channel, voidFuncPtr handler); /** - * Like attachCompareInterrupt(1, handler). + * Equivalent to attachCompareInterrupt(1, handler). * @see HardwareTimer::attachCompareInterrupt() */ void attachCompare1Interrupt(voidFuncPtr handler); /** - * Like attachCompareInterrupt(2, handler). + * Equivalent to attachCompareInterrupt(2, handler). * @see HardwareTimer::attachCompareInterrupt() */ void attachCompare2Interrupt(voidFuncPtr handler); /** - * Like attachCompareInterrupt(3, handler). + * Equivalent to attachCompareInterrupt(3, handler). * @see HardwareTimer::attachCompareInterrupt() */ void attachCompare3Interrupt(voidFuncPtr handler); /** - * Like attachCompareInterrupt(4, handler). + * Equivalent to attachCompareInterrupt(4, handler). * @see HardwareTimer::attachCompareInterrupt() */ void attachCompare4Interrupt(voidFuncPtr handler); @@ -346,25 +343,25 @@ class HardwareTimer { void detachInterrupt(int channel); /** - * Like detachInterrupt(1). + * Equivalent to detachInterrupt(1). * @see HardwareTimer::detachInterrupt() */ void detachCompare1Interrupt(void); /** - * Like detachInterrupt(2). + * Equivalent to detachInterrupt(2). * @see HardwareTimer::detachInterrupt() */ void detachCompare2Interrupt(void); /** - * Like detachInterrupt(3). + * Equivalent to detachInterrupt(3). * @see HardwareTimer::detachInterrupt() */ void detachCompare3Interrupt(void); /** - * Like detachInterrupt(4). + * Equivalent to detachInterrupt(4). * @see HardwareTimer::detachInterrupt() */ void detachCompare4Interrupt(void); @@ -394,6 +391,22 @@ extern HardwareTimer Timer5; extern HardwareTimer Timer8; #endif +/** + * Get one of the pre-instantiated HardwareTimer instances, given a + * timer device number. + * + * Be careful not to pass an actual number to this function. For + * example, getTimer(1) will not return Timer1. Use a real + * timer_dev_num, e.g. TIMER1, TIMER2, etc. + * + * @param timerNum the timer device number, e.g. TIMER1. + * + * @return Pointer to the HardwareTimer instance corresponding to the + * given timer device number. If timerNum is TIMER_INVALID, returns a + * null pointer. + * + * @see timer_dev_num + */ HardwareTimer* getTimer(timer_dev_num timerNum); #endif diff --git a/wirish/comm/HardwareSPI.h b/wirish/comm/HardwareSPI.h index 03d1ea1..7241d0b 100644 --- a/wirish/comm/HardwareSPI.h +++ b/wirish/comm/HardwareSPI.h @@ -29,18 +29,23 @@ #ifndef _HARDWARESPI_H_ #define _HARDWARESPI_H_ +/** + * Defines the possible SPI communication speeds. + */ typedef enum SPIFrequency { - SPI_18MHZ = 0, - SPI_9MHZ = 1, - SPI_4_5MHZ = 2, - SPI_2_25MHZ = 3, - SPI_1_125MHZ = 4, - SPI_562_500KHZ = 5, - SPI_281_250KHZ = 6, - SPI_140_625KHZ = 7, - MAX_SPI_FREQS = 8, + SPI_18MHZ = 0, /**< 18 MHz */ + SPI_9MHZ = 1, /**< 9 MHz */ + SPI_4_5MHZ = 2, /**< 4.5 MHz */ + SPI_2_25MHZ = 3, /**< 2.25 MHZ */ + SPI_1_125MHZ = 4, /**< 1.125 MHz */ + SPI_562_500KHZ = 5, /**< 562.500 KHz */ + SPI_281_250KHZ = 6, /**< 281.250 KHz */ + SPI_140_625KHZ = 7, /**< 140.625 KHz */ + MAX_SPI_FREQS = 8, /**< The number of SPI frequencies. */ } SPIFrequency; +/* Documented by hand in docs/source/lang/api/hardwarespi.rst; if you + make any changes, make sure to update this document. */ class HardwareSPI { private: uint32 spi_num; diff --git a/wirish/ext_interrupts.h b/wirish/ext_interrupts.h index 057c0d3..304e267 100644 --- a/wirish/ext_interrupts.h +++ b/wirish/ext_interrupts.h @@ -86,7 +86,7 @@ void detachInterrupt(uint8 pin); * * @see noInterrupts() */ -static inline __attribute__((always_inline)) void interrupts() { +static ALWAYS_INLINE void interrupts() { nvic_globalirq_enable(); } @@ -100,7 +100,7 @@ static inline __attribute__((always_inline)) void interrupts() { * * @see interrupts() */ -static inline __attribute__((always_inline)) void noInterrupts() { +static ALWAYS_INLINE void noInterrupts() { nvic_globalirq_disable(); } diff --git a/wirish/io.h b/wirish/io.h index 547dc8e..2d22dcd 100644 --- a/wirish/io.h +++ b/wirish/io.h @@ -145,7 +145,7 @@ void digitalWrite(uint8 pin, uint8 value); * @return LOW or HIGH. * @see pinMode() */ -uint32 digitalRead(uint8); +uint32 digitalRead(uint8 pin); /** * Read an analog value from pin. This function blocks during ADC diff --git a/wirish/wirish_math.h b/wirish/wirish_math.h index 4156722..14614ba 100644 --- a/wirish/wirish_math.h +++ b/wirish/wirish_math.h @@ -79,8 +79,10 @@ long random(long min, long max); * @return the mapped value. */ /* TODO: profile code bloat due to inlining this */ -inline long map(long x, long in_min, long in_max, long out_min, long out_max) { - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +inline long map(long value, long fromStart, long fromEnd, + long toStart, long toEnd) { + return (value - fromStart) * (toEnd - toStart) / (fromEnd - fromStart) + + toStart; } #define PI 3.1415926535897932384626433832795 -- cgit v1.2.3