OUTA[26..23] := 0b1011; in Propeller C
in Propeller 1
Hello,
i converted an assembler program into C
I was trying to use OUTA[26..23] := 0b1111; to set some bits, but I get error
to many decimal points in number;
I need to set a specific range of pins to a pattern without affecting pins outside the range above or below
like
OUTA ^= 0b101010101010101 << 26;
any help would be helpful
thank you
regards
Jeff
i converted an assembler program into C
I was trying to use OUTA[26..23] := 0b1111; to set some bits, but I get error
to many decimal points in number;
I need to set a specific range of pins to a pattern without affecting pins outside the range above or below
like
OUTA ^= 0b101010101010101 << 26;
any help would be helpful
thank you
regards
Jeff

Comments
That will do the same thing in C/C++ as
OUTA[26..23] := 0b1111
in Spin.
Where "mask" is the bit mask of pins you want to write, and value is the value you want written to the port.
Example:
Source
Beat me to it
Ex:
This will set bit 23:
var |= (0x01 << 23); // set
This will clear bit 23
var &= ~(0x01 << 23); // clear
This will toggle a bit each time it is called:
var ^= 0x01 << 23; // toggle
These could be placed in a function where you have a start and stop value for a range.
The Macro way would be to do something like:
#define BIT_MASK(bit) (1 << (bit))
#define SET_BIT(value,bit) ((value) |= BIT_MASK(bit))
#define CLEAR_BIT(value,bit) ((value) &= ~BIT_MASK(bit))
#define TEST_BIT(value,bit) (((value) & BIT_MASK(bit)) ? 1 : 0)
However, for a range, you would look at some sort of loop or a function that accepts a range to set or clear or even toggle a bit, or use the other great examples the David's have posted.
// Macro example: #include <iostream> #include <stdint.h> #include <iomanip> #define BIT_MASK(bit) (0x01 << (bit)) #define SET_BIT(value,bit) ((value) |= BIT_MASK(bit)) #define CLEAR_BIT(value,bit) ((value) &= ~BIT_MASK(bit)) #define TEST_BIT(value,bit) (((value) & BIT_MASK(bit)) ? 1 : 0) using namespace std; void set_some_bits(uint32_t from_val, uint32_t to_val, uint32_t val) { for(uint32_t i = from_val; i <= to_val; i++ ) { SET_BIT(val, i ); cout << "After set bit " << dec << i << " = " << "0x" << setfill('0') << hex << setw(8) << val << endl; } } int main(){ uint32_t OUTA = 0x00020304; cout << "This is a test\n"; cout << "Original value of OUTA = " << "0x" << setfill('0') << hex << setw(8) << OUTA << endl; uint32_t byte1 = SET_BIT(OUTA,25); cout << "Set bit value 25 = " << "0x" << setfill('0') << hex << setw(8) << byte1 << endl; cout << "Clear a bit 25 = " << "0x" << setfill('0') << hex << setw(8) << CLEAR_BIT(OUTA, 25) << endl; set_some_bits(23, 26, OUTA); return 0; }// This will produce:
This is a test
Original value of OUTA = 0x00020304
Set bit value 25 = 0x02020304
Clear a bit 25 = 0x00020304
After set bit 23 = 0x00820304
After set bit 24 = 0x01820304
After set bit 25 = 0x03820304
After set bit 26 = 0x07820304
http://learn.parallax.com/tutorials/language/propeller-c/propeller-c-simple-circuits/seven-segment-display
I'm putting together a Noise Level Indicator project and this might come in handy with outputting the sound levels to a Bar Graph display.
There's a great example of using PropWare and an MCP3000 (an ADC) to turn the 8 LEDs on a Quickstart board into a bar graph, just as you're looking to do. Long version here, and short version following:
#include <PropWare/gpio/simpleport.h> #include <PropWare/sensor/analog/mcp3xxx.h> using PropWare::MCP3xxx; using PropWare::Port; using PropWare::SimplePort; using PropWare::SPI; static const MCP3xxx::PartNumber PART_NUMBER = MCP3xxx::PartNumber::MCP300x; static const MCP3xxx::Channel CHANNEL = MCP3xxx::Channel::CHANNEL_1; static const Port::Mask MOSI = Port::P0; static const Port::Mask MISO = Port::P1; static const Port::Mask SCLK = Port::P2; static const Port::Mask CS = Port::P3; static const Port::Mask FIRST_LED_PIN = Port::P16; static const int LED_COUNT = 8; static const uint16_t DIVISOR = 1024 / LED_COUNT; int main () { SPI spi(MOSI, MISO, SCLK); MCP3xxx adc(spi, CS, PART_NUMBER); // Set the Quickstart LEDs for output SimplePort scale(FIRST_LED_PIN, LED_COUNT, Port::Dir::OUT); while (1) { const uint16_t data = adc.read(CHANNEL); // convert the ADC's value (ranging from 0-1023) to a number representing // how many LEDs should be lit const uint8_t scaledValue = (uint8_t) ((data + DIVISOR / 2 - 1) / DIVISOR); uint32_t ledOutput = 0; for (uint8_t i = 0; i < scaledValue; ++i) ledOutput = (ledOutput << 1) | 1; scale.write(ledOutput); } }And here's a simpler snippet explaining the PropWare::SimplePort object's use:
This code will set the direction and write alternating 0s and 1s. Just like Simple's set_outputs() function, the shifting is done automagically for you. SimplePort is designed for ports with all pins in consecutive order. Ports with pins in non consecutive order can make use of PropWare::Port.
Interestingly, my PropWare example is actually 100 bytes smaller than Andy's Simple example (2,364 vs 2,468 when compiled in LMM). Sometimes, C++ does indeed win
Nice!
Not to hijack this discussion but I have a example working with an Arduino board where I have the sound input through an OpAMP which is then sent to the Arduino where the LED range on the Bar Graph is determined by a mapping between the input value and the appropriate LED or LEDs on the Display. This is done without an I/O expander however I do like the idea of using something like a MCP3000 series device to reduce the number of connections.
I'll have to give this whirl.
Thanks!
I wish it were true. Unfortunately, it isn't, and you can't use the "using" keyword with enums either (no "using PropWare::Port::Mask") - not even class enums. In fact, I won't swear to it, but I don't think you can even use it with inner classes. Here's the error message that GCC 4.6 throws with "using PropWare::Port::Mask":