/** Soft SPI receive */ uint8_t spiRec(void) { uint8_t data = 0; // no interrupts during byte receive - about 8 us cli(); // output pin high - like sending 0XFF fastDigitalWrite(SPI_MOSI_PIN, HIGH); for (uint8_t i = 0; i < 8; i++) { fastDigitalWrite(SPI_SCK_PIN, HIGH); // adjust so SCK is nice nop; nop; data <<= 1; if (fastDigitalRead(SPI_MISO_PIN)) { data |= 1; } fastDigitalWrite(SPI_SCK_PIN, LOW); } // enable interrupts sei(); return data; }
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) { if(duration > 0) { pinMode(_pin, OUTPUT_FAST); if(frequency > 0) { delayAmount = (long)(1000000/frequency)/2 - 1; loopTime = (long)((duration*1000)/(delayAmount*2)); for (int x=0;x<loopTime;x++) { time1 = micros(); time2 = time1; fastDigitalWrite(_pin,HIGH); while(((long)(time2 - time1)) <= delayAmount) { time2 = micros(); } time1 = micros(); fastDigitalWrite(_pin,LOW); while(((long)(time2 - time1)) <= delayAmount) { time2 = micros(); } } } else { //no tone generated, basically a pause or rest note time1 = micros(); time2 = time1; delayAmount = duration*1000; while(((long)(time2 - time1)) <= delayAmount) { time2 = micros(); } } } else { //tone(pin, frequency) is called with two parameters only or duration is set 0 //generate a constant tone. //since this generates a constant tone, it needs to be non-blocking else we would be stuck in an infinite loop pthread_mutex_lock(&pinMutex[_pin]); int tempThreadControl = ++threadControl[_pin]; pthread_mutex_unlock(&pinMutex[_pin]); pthread_t toneThread; struct tone_thread_param *params; params=(tone_thread_param *)malloc(sizeof(tone_thread_param)); params->tonePin = _pin; params->frequency = frequency; params->duration = duration; params->threadID = tempThreadControl; int iret1 = pthread_create( &toneThread, NULL, toneHandler, (void*) params); pthread_detach(toneThread); } }
/** * @brief Starts serial port * @param baud Baud rate to operate at. Defaults to 2400 */ void OTSoftSerial::begin(uint16_t _baud) { baud = _baud; uint16_t bitCycles = (F_CPU/4) / baud; // delay function burns 4 cpu instructions per cycle halfDelay = bitCycles/2-readTuning; fullDelay = bitCycles; pinMode(rxPin, INPUT_PULLUP); pinMode(txPin, OUTPUT); fastDigitalWrite(txPin, HIGH); // set txPin to high }
/** Soft SPI send */ void spiSend(uint8_t data) { // no interrupts during byte send - about 8 us cli(); for (uint8_t i = 0; i < 8; i++) { fastDigitalWrite(SPI_SCK_PIN, LOW); fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); data <<= 1; fastDigitalWrite(SPI_SCK_PIN, HIGH); } // hold SCK high for a few ns nop; nop; nop; nop; fastDigitalWrite(SPI_SCK_PIN, LOW); // enable interrupts sei(); }
/** Soft SPI send */ void spiSend(uint8_t data) { // no interrupts during byte send - about 8 us cli(); for (uint8_t i = 0; i < 8; i++) { fastDigitalWrite(SPI_SCK_PIN, LOW); //delayMicroseconds(5); //nop;nop; fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); //delayMicroseconds(5); nop;nop; data <<= 1; fastDigitalWrite(SPI_SCK_PIN, HIGH); //delayMicroseconds(5); nop;nop; } fastDigitalWrite(SPI_SCK_PIN, LOW); // enable interrupts sei(); }
// Called from startup() after some initial setup has been done. // Can abort with panic() if need be. void POSTalt() { #ifdef USE_OTNULLRADIO // FIXME #elif defined USE_MODULE_SIM900 //The config for the GSM depends on if you want it stored in flash or EEPROM. // //The SIM900LinkConfig object is located at the start of POSTalt() in AltMain.cpp and takes a set of void pointers to a \0 terminated string, either stored in flash or EEPROM. // //For EEPROM: //- Set the first field of SIM900LinkConfig to true. //- The configs are stored as \0 terminated strings starting at 0x300. //- You can program the eeprom using ./OTRadioLink/dev/utils/sim900eepromWrite.ino // static const void *SIM900_PIN = (void *)0x0300; // TODO confirm this address // static const void *SIM900_APN = (void *)0x0305; // static const void *SIM900_UDP_ADDR = (void *)0x031B; // static const void *SIM900_UDP_PORT = (void *)0x0329; // static const OTSIM900Link::OTSIM900LinkConfig_t SIM900Config { // true, // SIM900_PIN, // SIM900_APN, // SIM900_UDP_ADDR, // SIM900_UDP_PORT }; //For Flash: //- Set the first field of SIM900LinkConfig to false. //- Make a set of \0 terminated strings with the PROGMEM attribute holding the config details. //- set the void pointers to point to the strings (or just cast the strings and pass them to SIM900LinkConfig directly) // // const char myPin[] PROGMEM = "0000"; // const char myAPN[] PROGMEM = "m2mkit.telefonica.com"; // FIXME check this // const char myUDPAddr[] PROGMEM = "0.0.0.0"; // const char myUDPPort[] PROGMEM = "9999"; // static const OTSIM900Link::OTSIM900LinkConfig_t SIM900Config { // false, // SIM900_PIN, // SIM900_APN, // SIM900_UDP_ADDR, // SIM900_UDP_PORT }; static const void *SIM900_PIN = (void *)myPin; static const void *SIM900_APN = (void *)myAPN; static const void *SIM900_UDP_ADDR = (void *)myUDPAddr; static const void *SIM900_UDP_PORT = (void *)myUDPPort; static const OTSIM900Link::OTSIM900LinkConfig_t SIM900Config { false, SIM900_PIN, SIM900_APN, SIM900_UDP_ADDR, SIM900_UDP_PORT }; static const OTRadioLink::OTRadioChannelConfig RFMConfig(&SIM900Config, true, true, true); fastDigitalWrite(A3, LOW); // This turns power to the shield on pinMode(A3, OUTPUT); #elif defined(ENABLE_RADIO_PRIMARY_RFM23B) static const OTRadioLink::OTRadioChannelConfig RFMConfig(NULL, true, true, true); #endif // USE_MODULE_SIM900 #if defined(ENABLE_RADIO_PRIMARY_RFM23B) // Initialise the radio, if configured, ASAP because it can suck a lot of power until properly initialised. PrimaryRadio.preinit(NULL); // Check that the radio is correctly connected; panic if not... if(!PrimaryRadio.configure(1, &RFMConfig) || !PrimaryRadio.begin()) { panic(F("PANIC!")); } #endif // Force initialisation into low-power state. const int heat = TemperatureC16.read(); #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINT_FLASHSTRING("temp: "); DEBUG_SERIAL_PRINT(heat); DEBUG_SERIAL_PRINTLN(); #endif const int light = AmbLight.read(); //#if 0 && defined(DEBUG) // DEBUG_SERIAL_PRINT_FLASHSTRING("light: "); // DEBUG_SERIAL_PRINT(light); // DEBUG_SERIAL_PRINTLN(); //#endif // Trailing setup for the run // -------------------------- // Set up async edge interrupts. ATOMIC_BLOCK (ATOMIC_RESTORESTATE) { //PCMSK0 = PB; PCINT 0--7 (LEARN1 and Radio) //PCMSK1 = PC; PCINT 8--15 //PCMSK2 = PD; PCINT 16--24 (LEARN2 and MODE, RX) PCICR = #if defined(MASK_PB) && (MASK_PB != 0) // If PB interrupts required. 1 | // 0x1 enables PB/PCMSK0. #endif #if defined(MASK_PC) && (MASK_PC != 0) // If PC interrupts required. 2 | // 0x2 enables PC/PCMSK1. #endif #if defined(MASK_PD) && (MASK_PD != 0) // If PD interrupts required. 4 | // 0x4 enables PD/PCMSK2. #endif 0; #if defined(MASK_PB) && (MASK_PB != 0) // If PB interrupts required. PCMSK0 = MASK_PB; #endif #if defined(MASK_PC) && (MASK_PC != 0) // If PC interrupts required. PCMSK1 = MASK_PC; #endif #if defined(MASK_PD) && (MASK_PD != 0) // If PD interrupts required. PCMSK2 = MASK_PD; #endif } // pinMode(3, INPUT); // FIXME Move to where they are set automatically // digitalWrite(3, LOW); bareStatsTX(false, false, false); }
void *toneHandler(void *arg) { tone_thread_param *param; param = (tone_thread_param*)arg; int tPin = param->tonePin; pinMode(tPin, OUTPUT_FAST); long delayAmount; long loopTime; unsigned long time1; unsigned long time2; int currentThreadControlID = param->threadID; //when threadControl[tPin] is modified by another thread it will no longer be equal to currentThreadControlID which exits the loop below allowing it to die if((param->frequency) > 0) { delayAmount = (long)(1000000/(param->frequency))/2 - 1; loopTime = (long)((param->duration*1000)/(delayAmount*2)); if((param->duration) > 0) { //implementing this way because delayMicroseconds is blocking which makes the generated tone not accurate enough for (int x=0;x<loopTime;x++) { if(currentThreadControlID != threadControl[tPin]) { break; } time1 = micros(); time2 = time1; fastDigitalWrite(tPin,HIGH); while(((long)(time2 - time1)) <= delayAmount) { time2 = micros(); } time1 = micros(); fastDigitalWrite(tPin,LOW); while(((long)(time2 - time1)) <= delayAmount) { time2 = micros(); } } } else { //infinite loop while(true) { if(currentThreadControlID != threadControl[tPin]) { break; } time1 = micros(); time2 = time1; fastDigitalWrite(tPin,HIGH); while(((long)(time2 - time1)) <= delayAmount) { time2 = micros(); } time1 = micros(); fastDigitalWrite(tPin,LOW); while(((long)(time2 - time1)) <= delayAmount) { time2 = micros(); } } } } else { time1 = micros(); time2 = time1; delayAmount = (param->duration)*1000; while(((long)(time2 - time1)) <= delayAmount) { time2 = micros(); if(currentThreadControlID != threadControl[tPin]) { break; } } } }
// test - watch for input int main(int argc, char **argv) { unsigned char buffer[2048]; unsigned char bitmap[8192]; char temp[256]; Timer playbackTimer; if (argc < 2) { printf("usage: pispi <input.c64>\n"); return 1; } const char *fname = argv[1]; int frameSkip = 5; memset(buffer, 0, 1024); if (argc == 3) { const char *outfname = argv[2]; mp4toc64(fname, outfname, 12.0); printf("done.\n"); exit(1); } // convert mp4 C64FrameDataSource source(fname); //MP4FrameDataSource source(fname, 6.0); wiringPiSetup(); pinMode(0, INPUT); pullUpDnControl(0, PUD_UP); pinMode(1, OUTPUT); pullUpDnControl(1, PUD_OFF); fastDigitalWrite(1, LOW); // reset MCU int spi = wiringPiSPISetup(0, 2000000); delayMicroseconds(100000); fastDigitalWrite(1, HIGH); printf("checking for commands..\n"); int frames = 0; unsigned char *imgptr = NULL; bool done = false; bool started = false; while (!done) { // loop - check for updates unsigned char cmd; while (fastDigitalRead(0) == HIGH) { delayMicroseconds(10); } // get byte int r = read(spi, &cmd, 1); // start a frame if (cmd == 0) { if (!started) { started = true; playbackTimer.start(); } playbackTimer.end(); const unsigned char *frameChunk = source.getFrameChunk(cmd); int s = write(spi, frameChunk, 1024); float currTime = playbackTimer.getCurrentElapsedTime(); float currFps = (float)frames / currTime; } else if (cmd < 9) { const unsigned char *frameChunk = source.getFrameChunk(cmd); int s = write(spi, frameChunk, 1024); } // wait for deassert while (fastDigitalRead(0) == LOW) { delayMicroseconds(10); } float curr_playback_time = playbackTimer.getCurrentElapsedTime(); source.workForChunk(cmd, curr_playback_time); } return 1; }