//-------------------------------------------------------------------- void ccreg(char *in) { uint8_t hb, out; if(fromhex(in+1, &hb, 1)) { if(hb == 0x99) { for(uint8_t i = 0; i < 0x30; i++) { DH2(cc1100_readReg(i)); if((i&7) == 7) DNL(); } } else { out = cc1100_readReg(hb); DC('C'); // prefix DH2(hb); // register number DS_P( PSTR(" = ") ); DH2(out); // result, hex DS_P( PSTR(" / ") ); DU(out,2); // result, decimal DNL(); } } }
//-------------------------------------------------------------------- void ccreg(char *in) { uint8_t hb, out, addr; if(in[1] == 'w' && fromhex(in+2, &addr, 1) && fromhex(in+4, &hb, 1)) { cc1100_writeReg(addr, hb); ccStrobe( CC1100_SCAL ); ccRX(); DH2(addr); DH2(hb); DNL(); } else if(fromhex(in+1, &hb, 1)) { if(hb == 0x99) { for(uint8_t i = 0; i < 0x30; i++) { DH2(cc1100_readReg(i)); if((i&7) == 7) DNL(); } } else { out = cc1100_readReg(hb); DC('C'); // prefix DH2(hb); // register number DS_P( PSTR(" = ") ); DH2(out); // result, hex DS_P( PSTR(" / ") ); DU(out,2); // result, decimal DNL(); } } }
void batfunc(char *in) { uint8_t hb[2]; uint16_t bv; uint8_t l = fromhex(in+1,hb,2); #ifdef CURV3 // hb[0] = 00 Charge with 500mA (hb[1]=01) or 100mA (hb[1]=00) // hb[0] = 01 Disable USB charging (hb[1]=01) or enable it (hb[1]=00) if(l == 2) { uint8_t pin = BAT_PEN2; if(hb[0] == 1) pin = BAT_USUS; if(hb[1]) { BAT_PORT |= _BV(pin); } else { BAT_PORT &= ~_BV(pin); } } else #endif { // This will displayed on the 13char title row on the CUR bv = get_adcw(BAT_MUX); if(l >= 1 && hb[0]) { DU(bv, 4); } else { raw2percent(bv); DU(battery_state,3); DC('%'); } #ifdef CURV3 if( !bit_is_set( BAT_PIN, BAT_CHG ) ) DS_P( PSTR(" charging")); if( !bit_is_set( BAT_PIN, BAT_DONE) ) DS_P( PSTR(" charged")); if( !bit_is_set( BAT_PIN, BAT_FLT) ) DS_P( PSTR(" error")); #else uint8_t s1; s1 = (bit_is_set( BAT_PIN, BAT_PIN1) ? 2 : 0); s1 |= (bit_is_set( BAT_PIN, BAT_PIN2) ? 1 : 0); if(s1==0) DS_P( PSTR(" discharge")); if(s1==1) DS_P( PSTR(" charged")); if(s1==2) DS_P( PSTR(" charging")); if(s1==3) DS_P( PSTR(" error")); #endif #ifdef CURV3 if( !bit_is_set( BAT_PIN, BAT_DOK) ) DS_P( PSTR(" DC")); // not wired ;) if( !bit_is_set( BAT_PIN, BAT_UOK) ) DS_P( PSTR(" USB")); #endif DNL(); } }
void lcd_brightness(uint8_t hb) { int16_t brightness = erb((uint8_t*)EE_BRIGHTNESS); if(hb == 0xFE) { brightness += 0x20; } else if (hb == 0xFD) { brightness -= 0x20; } else if (hb == 0xFC) { //keep the eeprom value } else { brightness = hb; } if(brightness < 0) brightness = 0; if(brightness > 255) brightness = 255; ewb((uint8_t*)EE_BRIGHTNESS, brightness); LCD_BL_PWM = brightness; DS_P( PSTR("Brightns:") ); DU(brightness*100/255, 3); DC('%'); DNL(); }
void lcd_contrast(uint8_t hb) { uint8_t contrast = erb((uint8_t*)EE_CONTRAST); if(hb == 0xFE) { contrast--; } else if (hb == 0xFD) { contrast++; } else if (hb == 0xFC) { //keep the eeprom value } else { contrast = hb; } if(contrast < 40) contrast = 40; if(contrast > 80) contrast = 80; ewb((uint8_t*)EE_CONTRAST, contrast); lcd_sendcmd (LCD_CMD_SETCON); lcd_senddata (contrast); DS_P( PSTR("Contrast:") ); DU(100-(contrast-40)*100/40, 3); DC('%'); DNL(); }
void native_func(char *in) { uint8_t mode = 0; if(in[1] == 'r') { // Reception on // "Er<x>" - where <x> is mode if (in[2]) fromdec(in+2, &mode); if (!mode || mode>MAX_MODES) { DS_P(PSTR("specify valid mode number\r\n")); return; } native_init(mode); } else if(in[1] == 'x') { // Reception off if (native_on) ccStrobe( CC1100_SIDLE ); native_on = 0; } DH2(native_on); DNL(); }
void moritz_func(char *in) { if(in[1] == 'r') { // Reception on rf_moritz_init(); } else if(in[1] == 's' || in[1] == 'f' ) { // Send/Send fast uint8_t dec[MAX_MORITZ_MSG]; uint8_t hblen = fromhex(in+2, dec, MAX_MORITZ_MSG-1); if ((hblen-1) != dec[0]) { DS_P(PSTR("LENERR\r\n")); return; } moritz_sendraw(dec, in[1] == 's'); } else if(in[1] == 'a') { // Auto-Ack fromhex(in+2, autoAckAddr, 3); } else if(in[1] == 'w') { // Fake Wall-Thermostat fromhex(in+2, fakeWallThermostatAddr, 3); } else { // Off moritz_on = 0; } }
void kopp_fc_func(char *in) { int SingleBlkOnly=0; // Default: we will send key off if Keycode >= 0x80 uint32_t LastWatchdog; uint8_t blkTXcode=0x00; uint8_t inhex_dec[kopp_fc_Command_char]; // in_decbin: decimal value of hex commandline uint8_t hblen = fromhex(in+2, inhex_dec, strlen(in)); strcpy(ErrorMSG,"ok"); // If parameter 2 = "t" then "Transmitt Free Control Telegram" SingleBlkOnly=0; // Default: we will send key off if Keycode >= 0x80 if((in[1] == 't') || (in[1] == 's')) // Transmitt Command // ================= { kopp_fc_tx_on = 1; // Transmitt activated if (in[15]=='J') printon[0]='Y'; else printon[0]='N'; // Sollen wir Daten ausgeben (Zeitstempel etc) if(in[1] == 's') SingleBlkOnly=1; // Command = "s", -> If KeyCode > 0x80 we will send no !! Key Off Code LastWatchdog=ticks; // I guess, Watchdog reset was done shortly before BlockStartTime=ticks; // print some status Information if (printon[0]=='Y') { DS_P(PSTR("Transmitt\r\n")); DS_P(PSTR("commandlineparameter: ")); DS(in); DS_P(PSTR("\r\nStringlength: ")); DU(strlen(in),0); DS_P(PSTR("\r\nNext Character (int) after parameter (should be line end character): ")); DU((int)in[strlen(in)],0); DS_P(PSTR("\r\nAmount of Bytes (Hex) found inside command line parameter: ")); DU(hblen,0); DS_P(PSTR("\r\n")); // following code to check whether ticks uses full 32 bits or will be reset afer 125 ticks DS_P(PSTR("Tick Timer: ")); DH((uint16_t)(( BlockStartTime>>16) & 0xffff),4); DH((uint16_t)(BlockStartTime & 0xffff),4); DS_P(PSTR("\r\n")); }
void testmem(char *unused) { char *buf; uint16_t size; DS_P( PSTR("testing ") ); size = 32765; display_udec(size, 5,' '); DS_P( PSTR(" bytes of RAM - ") ); buf = malloc( size ); if (buf != NULL) { // write memset( buf, 0x77, size ); for (uint16_t i = 0; i<size; i++) *(buf+i) = (i & 0xff); // read for (uint16_t i = 0; i<size; i++) { if (*(buf+i) != (i & 0xff)) { DS_P( PSTR("Problmes at ") ); display_udec(i, 5,' '); DNL(); free( buf ); return; } } free( buf ); DS_P( PSTR("OK") ); } else { DS_P( PSTR("Alloc failed") ); } DNL(); }
void analyze_ttydata(uint8_t channel) { static int cmdlen; /* we need int because TTY_BUFSIZE may be >255 */ uint8_t ucCommand; uint8_t odc = display_channel; display_channel = channel; while(TTY_Rx_Buffer.nbytes) { ucCommand = rb_get(&TTY_Rx_Buffer); #ifdef RPI_TTY_FIX // eat RPi rubbish if (ucCommand == 0xff) continue; #endif if(ucCommand == '\n' || ucCommand == '\r') { if(!cmdlen) // empty return continue; cmdbuf[cmdlen] = 0; if(!callfn(cmdbuf)) { DS_P(PSTR("? (")); display_string(cmdbuf); DS_P(PSTR(" is unknown) Use one of")); callfn(0); DNL(); } cmdlen = 0; } else { if(cmdlen < sizeof(cmdbuf)-1) cmdbuf[cmdlen++] = ucCommand; } } display_channel = odc; }
void read_eeprom(char *in) { uint8_t hb[2], d; uint16_t addr; #ifdef HAS_ETHERNET if(in[1] == 'i') { if(in[2] == 'm') { display_ee_mac(EE_MAC_ADDR); } else if(in[2] == 'd') { DH2(erb(EE_USE_DHCP)); } else if(in[2] == 'a') { display_ee_ip4(EE_IP4_ADDR); } else if(in[2] == 'n') { display_ee_ip4(EE_IP4_NETMASK); } else if(in[2] == 'g') { display_ee_ip4(EE_IP4_GATEWAY); } else if(in[2] == 'N') { display_ee_ip4(EE_IP4_NTPSERVER); } else if(in[2] == 'o') { DH2(erb(EE_IP4_NTPOFFSET)); } else if(in[2] == 'p') { DU(eeprom_read_word((uint16_t *)EE_IP4_TCPLINK_PORT), 0); } } else #endif if(in[1] == 'M') { display_ee_mac(EE_DUDETTE_MAC); } else if(in[1] == 'P') { display_ee_bytes(EE_DUDETTE_PUBL, 16); } else { hb[0] = hb[1] = 0; d = fromhex(in+1, hb, 2); if(d == 2) addr = (hb[0] << 8) | hb[1]; else addr = hb[0]; d = erb((uint8_t *)addr); DC('R'); // prefix DH(addr,4); // register number DS_P( PSTR(" = ") ); DH2(d); // result, hex DS_P( PSTR(" / ") ); DU(d,2); // result, decimal } DNL(); }
void helios_func(char *in) { switch(in[1]) { case 'D': helios_debug = 1; break; case 'd': helios_debug = 0; break; default: DS_P(PSTR("use d/D to toggle raw message dump")); DNL(); } }
void moritz_send(char *in) { /* we are not affected by CC1101 errata #6, because MDMCFG2.SYNC_MODE != 0 */ uint8_t dec[MAX_MORITZ_MSG]; uint8_t hblen = fromhex(in+1, dec, MAX_MORITZ_MSG-1); if ((hblen-1) != dec[0]) { DS_P(PSTR("LENERR\r\n")); return; } moritz_sendraw(dec, 1); }
void helios_task(void) { if (helios_next>ticks) return; DC( 'F' ); DS_P(PSTR(HELIOS_EMU_HC)); DH2( 0 ); switch (helios_power) { case 0x1: DH2( 0x1 ); break; case 0x3: DH2( 0x3 ); break; case 0x7: DH2( 0x5 ); break; case 0xf: DH2( 0x7 ); break; case 0x1f: DH2( 0x9 ); break; case 0x3f: DH2( 0xb ); break; case 0x7f: DH2( 0xd ); break; case 0xff: DH2( 0xf ); break; } DH2( 0xff ); // RSSI DNL(); helios_next = ticks + 41000; // roughly 5 min }
static void fht80b_print(uint8_t full) { uint8_t *p = fht80b_buf; if(!p[0]) DS_P( PSTR("N/A") ); while(p[0] && (p < (fht80b_buf+FHTBUF_SIZE))) { if(p != fht80b_buf) DC(' '); uint8_t i = 1; DH2(p[i++]); DH2(p[i++]); if(full) { DC(':'); while(i < p[0]) { if(i > 3 && (i&1)) DC(','); DH2(p[i++]); } } p += p[0]; } }
void version(char *in) { #if defined(CUL_HW_REVISION) if (in[1] == 'H') { DS_P( PSTR(CUL_HW_REVISION) ); DNL(); return; } #endif DS_P( PSTR("V " VERSION " " FW_NAME " Build: " BUILD_NUMBER " (" BUILD_DATE ") ")); #ifdef MULTI_FREQ_DEVICE // check 433MHz version marker if (!bit_is_set(MARK433_PIN, MARK433_BIT)) DS_P( PSTR(BOARD_ID_STR433) ); else #endif DS_P( PSTR(BOARD_ID_STR) ); if (IS433MHZ) { DS_P( PSTR(" (F-Band: 433MHz)") ); } else { DS_P( PSTR(" (F-Band: 868MHz)") ); } DNL(); }
void helios_task(void) { char sign = 0; int temp = 0; double tempf = 0.0; if (helios_next>ticks) return; DC( 'F' ); DS_P(PSTR(HELIOS_EMU_HC)); DH2( 0 ); switch (helios_power) { case 0x1: DH2( 0x1 ); break; case 0x3: DH2( 0x3 ); break; case 0x7: DH2( 0x5 ); break; case 0xf: DH2( 0x7 ); break; case 0x1f: DH2( 0x9 ); break; case 0x3f: DH2( 0xb ); break; case 0x7f: DH2( 0xd ); break; case 0xff: DH2( 0xf ); break; } DH2( 0xff ); // RSSI DNL(); for (uint8_t i=0;i<4;i++) { if (helios_temp[i]) { tempf = (helios_temp[i]-100)/0.3; temp = (int) tempf; sign = (temp<0) ? '8' : '0'; DC('H'); DH2(0x33); //this needs to be coded more flexable DH2(0x10+i); DC(sign); //Sign-Bit (needs to be 8 for negative DC('1'); //HMS Type (only Temp) //Temp under 10 degs sign = (char) ( ( (uint8_t) ((temp / 10 ) % 10) )&0x0F ) + '0'; DC(sign); //Degrees below 1 sign = (char) ( ( (uint8_t) (temp % 10 ) )&0x0F ) + '0'; DC(sign); DC('0'); //Temp over 9 degs sign = (char) ( ( (uint8_t) ((temp / 100) % 10) )&0x0F ) + '0'; DC(sign); DC('0');DC('0');DC('F');DC('F'); //Humidity & RSSI DNL(); } } helios_next = ticks + 41000; // roughly 5 min }
void kopp_fc_init(void) { #ifdef ARM AT91C_BASE_AIC->AIC_IDCR = 1 << CC1100_IN_PIO_ID; // disable INT - we'll poll... CC1100_CS_BASE->PIO_PPUER = _BV(CC1100_CS_PIN); //Enable pullup CC1100_CS_BASE->PIO_OER = _BV(CC1100_CS_PIN); //Enable output CC1100_CS_BASE->PIO_PER = _BV(CC1100_CS_PIN); //Enable PIO control #else EIMSK &= ~_BV(CC1100_INT); // disable INT - we'll poll... SET_BIT( CC1100_CS_DDR, CC1100_CS_PIN ); // CS as output #endif // Toggle chip select signal (why?) CC1100_DEASSERT; // Chip Select InActiv my_delay_us(30); CC1100_ASSERT; // Chip Select Activ my_delay_us(30); CC1100_DEASSERT; // Chip Select InActiv my_delay_us(45); ccStrobe( CC1100_SRES ); // Send SRES command (Reset CC110x) my_delay_us(100); // load configuration (CC1100_Kopp_CFG[EE_CC1100_CFG_SIZE]) CC1100_ASSERT; // Chip Select Activ cc1100_sendbyte( 0 | CC1100_WRITE_BURST ); for(uint8_t i = 0; i < EE_CC1100_CFG_SIZE; i++) { cc1100_sendbyte(__LPM(CC1100_Kopp_CFG+i)); } CC1100_DEASSERT; // Chip Select InActiv // If I don't missunderstand the code, in module cc1100.c the pa table is defined as // 00 and C2 what means power off and max. power. // so following code (setup PA table) is not needed ? // did a trial, but does not work // setup PA table (-> Remove as soon as transmitting ok?), table see cc1100.c // this initializes the PA table with the table defined at EE_Prom // which table will be taken depends on command "x00 .... x09" // x00 means -10dbm pa ramping // x09 means +10dBm no pa ramping (see cc1100.c) and commandref.html #ifdef PrintOn // DS_P(PSTR("PA Table values: ")); #endif uint8_t *pa = EE_CC1100_PA; // EE_CC1100_PA+32 means max power??? CC1100_ASSERT; cc1100_sendbyte( CC1100_PATABLE | CC1100_WRITE_BURST); for (uint8_t i = 0; i < 8; i++) { #ifdef PrintOn // DU(erb(pa),0); // ### Claus, mal sehen was im PA Table steht DS_P(PSTR(" ")); #endif cc1100_sendbyte(erb(pa++)); // fncollection.c "erb()"gibt einen EEPROM Wert zurück } #ifdef PrintOn DS_P(PSTR("\r\n")); #endif CC1100_DEASSERT; // Set CC_ON ccStrobe( CC1100_SCAL); // Calibrate Synthesizer and turn it of. ##Claus brauchen wir das my_delay_ms(1); cc_on = 1; kopp_fc_on = 1; //##Claus may be not needed in future (Tx Only) checkFrequency(); }
// Transmitt data block for Kopp Free Control // ------------------------------------------------------------------------------------------------------------------------------------------ void TransmittKoppBlk(uint8_t sendmsg01[15], uint8_t blkTXcode_i) { // Read Blockcounter from Config File Datei (RAMDISK) // -------------------------------------------------- uint8_t blkcks = 0x0; int count = 0; int count2 = 1; //count2 = 1; // each block / telegram will be written n times (n = 13 see below) sendmsg01[3] = blkctr; // Write BlockCounter (was incremented) and Transmitt Code (=Transmitter Key) to Array sendmsg01[4] = blkTXcode_i; // ----------------------------------------------------------------------------------- // Send Block via Transmitter Fifo // -------------------------------- do { ccTX(); // initialize CC110x TX Mode? if(cc1100_readReg( CC1100_MARCSTATE ) != MARCSTATE_TX) // If Statemachine not MARCSTATE_TX -> error { DS_P(PSTR("TX_INIT_ERR_")); DH2(cc1100_readReg( CC1100_MARCSTATE )); DNL(); kopp_fc_init(); return; } BlockStartTime = ticks; // remember Start Time (1 tick=8msec, s.o.) blkcks=0xaa; // Checksumme initialisieren count=0; // CC1100_ASSERT; // Chip Select Activ cc1100_sendbyte(CC1100_WRITE_BURST | CC1100_TXFIFO); // Burst Mode via Fifo // Now send ! do { // =========== cc1100_sendbyte(sendmsg01[count]); // write date to fifo (fifo is big enough) if (count <= 8) // { blkcks=blkcks^sendmsg01[count]; // if (count==7) sendmsg01[8]=blkcks; // write ckecksum to Buffer as soon as calculated } // // count++; // } while(count < MAX_kopp_fc_MSG); // Transmitt Byte 0 - AmountofBytes CC1100_DEASSERT; // Chip Select InActiv //Wait for sending to finish (CC1101 will go to RX state automatically uint8_t i; for(i=0; i< 200;++i) { // if( cc1100_readReg( CC1100_MARCSTATE ) == MARCSTATE_RX) // Claus: After transmission we force idle, always, so RX will not happen // break; //now in RX, good if( cc1100_readReg( CC1100_MARCSTATE ) != MARCSTATE_TX) break; //neither in RX nor TX, probably some error my_delay_ms(1); } // Claus: Test shows i is ~ 0x36, but why so fast??, transmission should need about 25msec (15Bytes*8Bits*4800Bit/sec) // may be reading status via SPI is also also slow? // DS_P(PSTR("variable i: ")); // For test only // DH((uint16_t) (i),4); // For test only // DS_P(PSTR("\r\n")); // For test only count2++; } while(count2 <= 13); // send same message 13x blkctr++; // increase Blockcounter }
/* longPreamble is necessary for unsolicited messages to wakeup the receiver */ void moritz_sendraw(uint8_t *dec, int longPreamble) { uint8_t hblen = dec[0]+1; //1kb/s = 1 bit/ms. we send 1 sec preamble + hblen*8 bits uint32_t sum = (longPreamble ? 100 : 0) + (hblen*8)/10; if (credit_10ms < sum) { DS_P(PSTR("LOVF\r\n")); return; } credit_10ms -= sum; // in Moritz mode already? if(!moritz_on) { rf_moritz_init(); } if(CC1100_READREG( CC1100_MARCSTATE ) != MARCSTATE_RX) { //error DC('Z'); DC('E'); DC('R'); DC('R'); DC('1'); DH2(CC1100_READREG( CC1100_MARCSTATE )); DNL(); rf_moritz_init(); return; } /* We have to keep at least 20 ms of silence between two sends * (found out by trial and error). ticks runs at 125 Hz (8 ms per tick), * so we wait for 3 ticks. * This looks a bit cumbersome but handles overflows of ticks gracefully. */ if(lastSendingTicks) while(ticks == lastSendingTicks || ticks == lastSendingTicks+1) my_delay_ms(1); /* Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1 (this is the case) (takes 809μs) * start sending - CC1101 will send preamble continuously until TXFIFO is filled. * The preamble will wake up devices. See http://e2e.ti.com/support/low_power_rf/f/156/t/142864.aspx * It will not go into TX mode instantly if channel is not clear (see CCA_MODE), thus ccTX tries multiple times */ #ifdef CC_ID do { CCSTROBE(CC1100_STX); } while (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_TX); #else ccTX(); #endif if(CC1100_READREG( CC1100_MARCSTATE ) != MARCSTATE_TX) { //error DC('Z'); DC('E'); DC('R'); DC('R'); DC('2'); DH2(CC1100_READREG( CC1100_MARCSTATE )); DNL(); rf_moritz_init(); return; } if(longPreamble) { /* Send preamble for 1 sec. Keep in mind that waiting for too long may trigger the watchdog (2 seconds on CUL) */ for(int i=0;i<10;++i) my_delay_ms(100); //arg is uint_8, so loop } // send CC1100_ASSERT; cc1100_sendbyte(CC1100_WRITE_BURST | CC1100_TXFIFO); for(uint8_t i = 0; i < hblen; i++) { cc1100_sendbyte(dec[i]); } CC1100_DEASSERT; //Wait for sending to finish (CC1101 will go to RX state automatically //after sending uint8_t i; for(i=0; i< 200;++i) { if( CC1100_READREG( CC1100_MARCSTATE ) == MARCSTATE_RX) break; //now in RX, good if( CC1100_READREG( CC1100_MARCSTATE ) != MARCSTATE_TX) break; //neither in RX nor TX, probably some error my_delay_ms(1); } if(CC1100_READREG( CC1100_MARCSTATE ) != MARCSTATE_RX) { //error DC('Z'); DC('E'); DC('R'); DC('R'); DC('3'); DH2(CC1100_READREG( CC1100_MARCSTATE )); DNL(); rf_moritz_init(); } if(!moritz_on) { set_txrestore(); } lastSendingTicks = ticks; }
void asksin_send(char *in) { uint8_t msg[MAX_ASKSIN_MSG]; uint8_t ctl; uint8_t l; uint32_t ts1, ts2; uint8_t hblen = fromhex(in+1, msg, MAX_ASKSIN_MSG-1); if ((hblen-1) != msg[0]) { // DS_P(PSTR("LENERR\r\n")); return; } // in AskSin mode already? if(!asksin_on) { rf_asksin_init(); my_delay_ms(3); // 3ms: Found by trial and error } ctl = msg[2]; // "crypt" msg[1] = (~msg[1]) ^ 0x89; for (l = 2; l < msg[0]; l++) msg[l] = (msg[l-1] + 0xdc) ^ msg[l]; msg[l] = msg[l] ^ ctl; // enable TX, wait for CCA get_timestamp(&ts1); do { CCSTROBE(CC1100_STX); if (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_TX) { get_timestamp(&ts2); if (((ts2 > ts1) && (ts2 - ts1 > ASKSIN_WAIT_TICKS_CCA)) || ((ts2 < ts1) && (ts1 + ASKSIN_WAIT_TICKS_CCA < ts2))) { DS_P(PSTR("ERR:CCA\r\n")); goto out; } } } while (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_TX); if (ctl & (1 << 4)) { // BURST-bit set? // According to ELV, devices get activated every 300ms, so send burst for 360ms for(l = 0; l < 3; l++) my_delay_ms(120); // arg is uint_8, so loop } else { my_delay_ms(10); } // send CC1100_ASSERT; cc1100_sendbyte(CC1100_WRITE_BURST | CC1100_TXFIFO); for(uint8_t i = 0; i < hblen; i++) { cc1100_sendbyte(msg[i]); } CC1100_DEASSERT; // wait for TX to finish while(CC1100_READREG( CC1100_MARCSTATE ) == MARCSTATE_TX) ; out: if (CC1100_READREG( CC1100_MARCSTATE ) == MARCSTATE_TXFIFO_UNDERFLOW) { CCSTROBE( CC1100_SFTX ); CCSTROBE( CC1100_SIDLE ); CCSTROBE( CC1100_SNOP ); } if(asksin_on) { do { CCSTROBE(CC1100_SRX); } while (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_RX); } else { set_txrestore(); } }
void fhtsend(char *in) { uint8_t hb[6], l; // Last byte needed for 8v checksum l = fromhex(in+1, hb, 5); if(l < 4) { if(hb[0] == 1) { // Set housecode, clear buffers if(l == 3) { ewb(EE_FHTID , hb[1]); // 1.st byte: 80b relevant ewb(EE_FHTID+1, hb[2]); // 1.st+2.nd byte: 8v relevant fht_init(); return; } else { DH2(fht_hc0); DH2(fht_hc1); } #ifdef HAS_FHT_80b } else if(hb[0] == 2) { // Return the 80b buffer fht80b_print(l==1 || hb[1]==1); } else if(hb[0] == 3) { // Return the remaining fht buffer #if FHTBUF_SIZE > 255 DH(fht_bufspace(),4); #else DH2(fht_bufspace()); #endif #endif #ifdef HAS_FHT_8v } else if(hb[0] == 0x10) { // Return the 8v buffer uint8_t na=0; for(int i = 0; i < FHT_8V_NUM; i++) { if(fht8v_buf[2*i] == FHT_8V_DISABLED) continue; if(na) DC(' '); DH2(i); DC(':'); DH2(fht8v_buf[2*i]); DH2(fht8v_buf[2*i+1]); na++; } if(na==0) DS_P( PSTR("N/A") ); } else if(hb[0] == 0x11) { // Return the next 8v timeout DH2(fht8v_timeout/125); #endif } DNL(); } else { #ifdef HAS_FHT_8v if(hb[0]>=fht_hc0 && hb[0]< fht_hc0+FHT_8V_NUM && hb[1]==fht_hc1) { // FHT8v mode commands if(hb[3] == FHT8V_CMD_PAIR) { addParityAndSend(in, FHT_CSUM_START, 2); } else if(hb[3] == FHT8V_CMD_SYNC){// start syncprocess for _all_ 8v's fht8v_ctsync = hb[4]; // use it to shorten the sync-time fht8v_timeout=1; // Cheating on the 1% uint8_t cnt = 0; for(uint8_t i = 0 ; i < FHT_8V_NUM; i++ ) if(fht8v_buf[2*i] != FHT_8V_DISABLED ) cnt++; credit_10ms += (4*fht8v_ctsync); // should be 3.75 = 75ms / 2 / 10 } else { // Valve position uint8_t idx = (hb[0]-fht_hc0)*2; fht8v_buf[idx ] = hb[3]; // Command or 0xff for disable this fht8v_buf[idx+1] = hb[4]; // slot (valve) } return; } #endif #ifdef HAS_FHT_80b if(!fht_addbuf(in)) // FHT80b mode: Queue everything DS_P( PSTR("EOB\r\n") ); #endif } }
void version(char *in) { DS_P( PSTR("V " VERSION " " BOARD_ID_STR) ); DNL(); }