void LMS7002M_rxtsp_enable(LMS7002M_t *self, const LMS7002M_chan_t channel, const bool enable) { LMS7002M_set_mac_ch(self, channel); self->regs->reg_0x0400_en = enable?1:0; self->regs->reg_0x0400_bstart = 0; self->regs->reg_0x0400_insel = REG_0X0400_INSEL_LML; //r19 regs - probably means baseband input LMS7002M_regs_spi_write(self, 0x0400); self->regs->reg_0x0403_hbd_ovr = REG_0X0403_HBD_OVR_BYPASS; self->regs->reg_0x040a_agc_mode = REG_0X040A_AGC_MODE_BYPASS; self->regs->reg_0x040c_cmix_byp = 1; self->regs->reg_0x040c_agc_byp = 1; self->regs->reg_0x040c_gfir3_byp = 1; self->regs->reg_0x040c_gfir2_byp = 1; self->regs->reg_0x040c_gfir1_byp = 1; self->regs->reg_0x040c_dc_byp = 1; self->regs->reg_0x040c_gc_byp = 1; self->regs->reg_0x040c_ph_byp = 1; LMS7002M_regs_spi_write(self, 0x0400); LMS7002M_regs_spi_write(self, 0x0403); LMS7002M_regs_spi_write(self, 0x040a); LMS7002M_regs_spi_write(self, 0x040c); }
LMS7002M_API void LMS7002M_txtsp_set_freq(LMS7002M_t *self, const LMS7002M_chan_t channel, const double freqRel) { LMS7002M_set_mac_ch(self, channel); self->regs.reg_0x0208_cmix_byp = 0; LMS7002M_regs_spi_write(self, 0x0208); LMS7002M_set_nco_freq(self, LMS_TX, channel, freqRel); }
double LMS7002M_rxtsp_read_rssi(LMS7002M_t *self, const LMS7002M_chan_t channel) { LMS7002M_set_mac_ch(self, channel); self->regs->reg_0x040c_agc_byp = 0; LMS7002M_regs_spi_write(self, 0x040c); self->regs->reg_0x040a_agc_mode = REG_0X040A_AGC_MODE_RSSI; LMS7002M_regs_spi_write(self, 0x040a); self->regs->reg_0x0400_capsel = REG_0X0400_CAPSEL_RSSI; self->regs->reg_0x0400_capture = 0; LMS7002M_regs_spi_write(self, 0x0400); //trigger capture to capd readback regs self->regs->reg_0x0400_capture = 1; LMS7002M_regs_spi_write(self, 0x0400); const int rssi_lo = LMS7002M_spi_read(self, 0x040E); const int rssi_hi = LMS7002M_spi_read(self, 0x040F); const int rssi_int = (rssi_hi << 2) | rssi_lo; //a full scale DC input level be 1.0 RSSI return rssi_int/((double)(1 << 16)); }
double LMS7002M_tbb_set_filter_bw(LMS7002M_t *self, const LMS7002M_chan_t channel, const double bw) { LMS7002M_set_mac_ch(self, channel); int val = 0; double actual = bw; bool bypass = false; const bool hb = bw >= 18.5e6; if (bw <= 2.4e6) val = 6, actual = 2.4e6; else if (bw <= 2.74e6) val = 19, actual = 2.74e6; else if (bw <= 5.5e6) val = 75, actual = 5.5e6; else if (bw <= 8.2e6) val = 133, actual = 8.2e6; else if (bw <= 11.0e6) val = 193, actual = 11.0e6; else if (bw <= 18.5e6) val = 18, actual = 18.5e6; else if (bw <= 38.0e6) val = 97, actual = 38.0e6; else if (bw <= 54.0e6) val = 163, actual = 54.0e6; else bypass = true; //only one filter is actually used self->regs->reg_0x0109_rcal_lpfh_tbb = val; self->regs->reg_0x0109_rcal_lpflad_tbb = val; LMS7002M_regs_spi_write(self, 0x0109); //set path if (bypass) LMS7002M_tbb_set_path(self, channel, LMS7002M_TBB_BYP); else if (hb) LMS7002M_tbb_set_path(self, channel, LMS7002M_TBB_HBF); else LMS7002M_tbb_set_path(self, channel, LMS7002M_TBB_LBF); return actual; }
void LMS7002M_tbb_set_path(LMS7002M_t *self, const LMS7002M_chan_t channel, const int path) { LMS7002M_set_mac_ch(self, channel); self->regs->reg_0x0105_pd_lpfh_tbb = 1; self->regs->reg_0x0105_pd_lpflad_tbb = 1; self->regs->reg_0x0105_pd_lpfs5_tbb = 1; self->regs->reg_0x010a_bypladder_tbb = 1; switch (path) { case LMS7002M_TBB_BYP: break; case LMS7002M_TBB_LBF: self->regs->reg_0x010a_bypladder_tbb = 0; self->regs->reg_0x0105_pd_lpflad_tbb = 0; self->regs->reg_0x0105_pd_lpfs5_tbb = 0; break; case LMS7002M_TBB_HBF: self->regs->reg_0x0105_pd_lpfh_tbb = 0; break; } LMS7002M_regs_spi_write(self, 0x0105); LMS7002M_regs_spi_write(self, 0x010A); }
LMS7002M_API void LMS7002M_trf_select_band(LMS7002M_t *self, const LMS7002M_chan_t channel, const int band) { LMS7002M_set_mac_ch(self, channel); self->regs.reg_0x0103_sel_band1_trf = (band == 1)?1:0; self->regs.reg_0x0103_sel_band2_trf = (band == 2)?1:0; LMS7002M_regs_spi_write(self, 0x0103); }
LMS7002M_API void LMS7002M_txtsp_tsg_const(LMS7002M_t *self, const LMS7002M_chan_t channel, const int valI, const int valQ) { LMS7002M_set_mac_ch(self, channel); //muxes self->regs.reg_0x0200_tsgfc = REG_0X0200_TSGFC_FS; self->regs.reg_0x0200_tsgmode = REG_0X0200_TSGMODE_DC; self->regs.reg_0x0200_insel = REG_0X0200_INSEL_TEST; LMS7002M_regs_spi_write(self, 0x0200); //load I self->regs.reg_0x020c_dc_reg = valI; LMS7002M_regs_spi_write(self, 0x020c); self->regs.reg_0x0200_tsgdcldi = 0; LMS7002M_regs_spi_write(self, 0x0200); self->regs.reg_0x0200_tsgdcldi = 1; LMS7002M_regs_spi_write(self, 0x0200); self->regs.reg_0x0200_tsgdcldi = 0; LMS7002M_regs_spi_write(self, 0x0200); //load Q self->regs.reg_0x020c_dc_reg = valQ; LMS7002M_regs_spi_write(self, 0x020c); self->regs.reg_0x0200_tsgdcldq = 0; LMS7002M_regs_spi_write(self, 0x0200); self->regs.reg_0x0200_tsgdcldq = 1; LMS7002M_regs_spi_write(self, 0x0200); self->regs.reg_0x0200_tsgdcldq = 0; LMS7002M_regs_spi_write(self, 0x0200); }
void LMS7002M_tbb_enable_loopback(LMS7002M_t *self, const LMS7002M_chan_t channel, const int mode, const bool swap) { LMS7002M_set_mac_ch(self, channel); self->regs->reg_0x0105_loopb_tbb = mode; self->regs->reg_0x0105_loopb_tbb |= swap?0:(1 << 2); LMS7002M_regs_spi_write(self, 0x0105); }
LMS7002M_API void LMS7002M_trf_enable(LMS7002M_t *self, const LMS7002M_chan_t channel, const bool enable) { LMS7002M_set_mac_ch(self, channel); self->regs.reg_0x0124_en_dir_trf = 1; LMS7002M_regs_spi_write(self, 0x0124); self->regs.reg_0x0100_en_g_trf = enable?1:0; self->regs.reg_0x0100_pd_tlobuf_trf = 0; self->regs.reg_0x0100_pd_txpad_trf = 0; LMS7002M_regs_spi_write(self, 0x0100); }
void LMS7002M_tbb_enable(LMS7002M_t *self, const LMS7002M_chan_t channel, const bool enable) { LMS7002M_set_mac_ch(self, channel); self->regs->reg_0x0124_en_dir_tbb = 1; LMS7002M_regs_spi_write(self, 0x0124); self->regs->reg_0x0105_en_g_tbb = enable?1:0; LMS7002M_tbb_set_test_in(self, channel, LMS7002M_TBB_TSTIN_OFF); LMS7002M_tbb_enable_loopback(self, channel, LMS7002M_TBB_LB_DISCONNECTED, false); LMS7002M_regs_spi_write(self, 0x0105); }
LMS7002M_API void LMS7002M_txtsp_tsg_tone(LMS7002M_t *self, const LMS7002M_chan_t channel) { LMS7002M_set_mac_ch(self, channel); //muxes self->regs.reg_0x0200_tsgmode = REG_0X0200_TSGMODE_NCO; self->regs.reg_0x0200_insel = REG_0X0200_INSEL_TEST; LMS7002M_regs_spi_write(self, 0x0200); self->regs.reg_0x0200_tsgfcw = REG_0X0200_TSGFCW_DIV8; LMS7002M_regs_spi_write(self, 0x0200); }
void LMS7002M_rxtsp_set_decim(LMS7002M_t *self, const LMS7002M_chan_t channel, const size_t decim) { LMS7002M_set_mac_ch(self, channel); if (decim == 1) self->regs->reg_0x0403_hbd_ovr = REG_0X0403_HBD_OVR_BYPASS; if (decim == 2) self->regs->reg_0x0403_hbd_ovr = 0; if (decim == 4) self->regs->reg_0x0403_hbd_ovr = 1; if (decim == 8) self->regs->reg_0x0403_hbd_ovr = 2; if (decim == 16) self->regs->reg_0x0403_hbd_ovr = 3; if (decim == 32) self->regs->reg_0x0403_hbd_ovr = 4; LMS7002M_regs_spi_write(self, 0x0403); }
LMS7002M_API void LMS7002M_txtsp_set_interp(LMS7002M_t *self, const LMS7002M_chan_t channel, const size_t interp) { LMS7002M_set_mac_ch(self, channel); if (interp == 1) self->regs.reg_0x0203_hbi_ovr = REG_0X0203_HBI_OVR_BYPASS; if (interp == 2) self->regs.reg_0x0203_hbi_ovr = 0; if (interp == 4) self->regs.reg_0x0203_hbi_ovr = 1; if (interp == 8) self->regs.reg_0x0203_hbi_ovr = 2; if (interp == 16) self->regs.reg_0x0203_hbi_ovr = 3; if (interp == 32) self->regs.reg_0x0203_hbi_ovr = 4; LMS7002M_regs_spi_write(self, 0x0203); }
void LMS7002M_rxtsp_set_dc_correction( LMS7002M_t *self, const LMS7002M_chan_t channel, const bool enabled, const int window) { LMS7002M_set_mac_ch(self, channel); self->regs->reg_0x040c_dc_byp = (enabled)?0:1; LMS7002M_regs_spi_write(self, 0x040c); self->regs->reg_0x0404_dccorr_avg = window; LMS7002M_regs_spi_write(self, 0x0404); }
double LMS7002M_tbb_set_iamp(LMS7002M_t *self, const LMS7002M_chan_t channel, const double gain) { LMS7002M_set_mac_ch(self, channel); int value = (int)(gain + 0.5); if (value < 0) value = 0; if (value > 63) value = 63; //ensure enabled iamp self->regs->reg_0x0105_pd_lpfiamp_tbb = 0; LMS7002M_regs_spi_write(self, 0x0105); //TODO this may need calibration self->regs->reg_0x0108_cg_iamp_tbb = value; return gain; }
void LMS7002M_rxtsp_set_iq_correction( LMS7002M_t *self, const LMS7002M_chan_t channel, const double phase, const double gain) { LMS7002M_set_mac_ch(self, channel); const bool bypassPhase = (phase == 0.0); const bool bypassGain = (gain == 0.0); self->regs->reg_0x040c_ph_byp = bypassPhase?1:0; self->regs->reg_0x040c_gc_byp = bypassGain?1:0; LMS7002M_regs_spi_write(self, 0x040c); //TODO //self->regs->reg_0x0403_iqcorr = //self->regs->reg_0x0402_gcorri = //self->regs->reg_0x0401_gcorrq = }
void LMS7002M_ldo_enable(LMS7002M_t *self, const bool enable, const int group) { //LDO is a global register space LMS7002M_set_mac_ch(self, LMS_CHAB); //TODO, we can implement more groups, for now only 1 if (group != LMS7002M_LDO_ALL) return; const int val = enable?1:0; self->regs->reg_0x0092_en_ldo_dig= val; self->regs->reg_0x0092_en_ldo_diggn= val; self->regs->reg_0x0092_en_ldo_digsxr= val; self->regs->reg_0x0092_en_ldo_digsxt= val; self->regs->reg_0x0092_en_ldo_divgn= val; self->regs->reg_0x0092_en_ldo_divsxr= val; self->regs->reg_0x0092_en_ldo_divsxt= val; self->regs->reg_0x0092_en_ldo_lna12= val; self->regs->reg_0x0092_en_ldo_lna14= val; self->regs->reg_0x0092_en_ldo_mxrfe= val; self->regs->reg_0x0092_en_ldo_rbb= val; self->regs->reg_0x0092_en_ldo_rxbuf= val; self->regs->reg_0x0092_en_ldo_tbb= val; self->regs->reg_0x0092_en_ldo_tia12= val; self->regs->reg_0x0092_en_ldo_tia14= val; self->regs->reg_0x0092_en_g_ldo= val; self->regs->reg_0x0093_en_ldo_afe= val; self->regs->reg_0x0093_en_ldo_cpgn= val; self->regs->reg_0x0093_en_ldo_cpsxr= val; self->regs->reg_0x0093_en_ldo_tlob= val; self->regs->reg_0x0093_en_ldo_tpad= val; self->regs->reg_0x0093_en_ldo_txbuf= val; self->regs->reg_0x0093_en_ldo_vcogn= val; self->regs->reg_0x0093_en_ldo_vcosxr= val; self->regs->reg_0x0093_en_ldo_vcosxt= val; self->regs->reg_0x0093_en_ldo_cpsxt= val; LMS7002M_regs_spi_write(self, 0x0092); LMS7002M_regs_spi_write(self, 0x0093); }
LMS7002M_API void LMS7002M_txtsp_enable(LMS7002M_t *self, const LMS7002M_chan_t channel, const bool enable) { LMS7002M_set_mac_ch(self, channel); self->regs.reg_0x0200_en = enable?1:0; self->regs.reg_0x0200_bstart = 0; self->regs.reg_0x0200_insel = REG_0X0200_INSEL_LML; LMS7002M_regs_spi_write(self, 0x0200); self->regs.reg_0x0203_hbi_ovr = REG_0X0203_HBI_OVR_BYPASS; self->regs.reg_0x0208_cmix_byp = 1; self->regs.reg_0x0208_isinc_byp = 1; self->regs.reg_0x0208_gfir3_byp = 1; self->regs.reg_0x0208_gfir2_byp = 1; self->regs.reg_0x0208_gfir1_byp = 1; self->regs.reg_0x0208_dc_byp = 1; self->regs.reg_0x0208_gc_byp = 1; self->regs.reg_0x0208_ph_byp = 1; LMS7002M_regs_spi_write(self, 0x0200); LMS7002M_regs_spi_write(self, 0x0203); LMS7002M_regs_spi_write(self, 0x0208); }
int LMS7002M_set_gfir_taps( LMS7002M_t *self, const LMS7002M_dir_t direction, const LMS7002M_chan_t channel, const int which, const short *taps, const size_t ntaps) { LMS7002M_set_mac_ch(self, channel); //bypass the filter for null/empty filter taps const bool bypass = (taps == NULL) || (ntaps == 0); if (direction == LMS_RX) { if (which == 1) self->regs->reg_0x040c_gfir1_byp = bypass?1:0; if (which == 2) self->regs->reg_0x040c_gfir2_byp = bypass?1:0; if (which == 3) self->regs->reg_0x040c_gfir3_byp = bypass?1:0; LMS7002M_regs_spi_write(self, 0x040c); } if (direction == LMS_TX) { if (which == 1) self->regs->reg_0x0208_gfir1_byp = bypass?1:0; if (which == 2) self->regs->reg_0x0208_gfir2_byp = bypass?1:0; if (which == 3) self->regs->reg_0x0208_gfir3_byp = bypass?1:0; LMS7002M_regs_spi_write(self, 0x0208); } //bypass programed, skip writing taps if (bypass) return 0; //bounds check if (which < 1) return -1; if (which > 3) return -1; if (which == 1 && ntaps != 5*8) return -2; if (which == 2 && ntaps != 5*8) return -2; if (which == 3 && ntaps != 3*5*8) return -2; //taps configuration logic from LMS7002_MainControl::LoadGFIRCoefficients if (which == 1) { int addr = (direction == LMS_RX)?0x0480:0x0280; for (int k=0; k<5; ++k) { for (int i=0; i<8; ++i) { LMS7002M_spi_write(self, addr, taps[k*8+i]); ++addr; } } } else if (which == 2) { int addr = (direction == LMS_RX)?0x04c0:0x02c0; for (int k=0; k<5; ++k) { for (int i=0; i<8; ++i) { LMS7002M_spi_write(self, addr, taps[k*8+i]); ++addr; } } } else if (which == 3) { int addr = (direction == LMS_RX)?0x0500:0x0300; int coefIndex = 0; unsigned short coefValue = 0; for (int n=0; n<3; ++n) { for (int k=0; k<5; ++k) { for (int i=0; i<8; ++i) { coefValue = taps[coefIndex]; ++coefIndex; LMS7002M_spi_write(self, addr, coefValue); ++addr; } } addr += 24; //skip reserved } } return 0; //OK }
LMS7002M_API void LMS7002M_trf_enable_loopback(LMS7002M_t *self, const LMS7002M_chan_t channel, const bool enable) { LMS7002M_set_mac_ch(self, channel); self->regs.reg_0x0101_en_loopb_txpad_trf = enable?0:1; LMS7002M_regs_spi_write(self, 0x0101); }
int LMS7002M_set_data_clock(LMS7002M_t *self, const double fref, const double fout, double *factual) { LMS7_logf(LMS7_INFO, "CGEN tune %f MHz begin", fout/1e6); //always use the channel A shadow, CGEN is in global register space LMS7002M_set_mac_ch(self, LMS_CHA); //The equations: // fref * N = fvco // fvco / fdiv = fout // fref * N = fout * fdiv int fdiv = 512+2; double Ndiv = 0; double fvco = 0; //calculation loop to find dividers that are possible while (true) { //try the next even divider fdiv -= 2; Ndiv = fout*fdiv/fref; fvco = fout*fdiv; LMS7_logf(LMS7_TRACE, "Trying: fdiv = %d, Ndiv = %f, fvco = %f MHz", fdiv, Ndiv, fvco/1e6); //check dividers and vco in range... if (fdiv < 2) return -1; if (fdiv > 512) continue; if (Ndiv < 4) return -1; if (Ndiv > 512) continue; //check vco boundaries if (fvco < LMS7002M_CGEN_VCO_LO) continue; if (fvco > LMS7002M_CGEN_VCO_HI) continue; break; //its good } LMS7_logf(LMS7_DEBUG, "Using: fdiv = %d, Ndiv = %f, fvco = %f MHz", fdiv, Ndiv, fvco/1e6); //stash the freq now that we know the loop above passed self->cgen_freq = fout; self->cgen_fref = fref; //reset self->regs->reg_0x0086_reset_n_cgen = 0; LMS7002M_regs_spi_write(self, 0x0086); self->regs->reg_0x0086_reset_n_cgen = 1; LMS7002M_regs_spi_write(self, 0x0086); //configure and enable synthesizer self->regs->reg_0x0086_en_intonly_sdm_cgen = 0; //support frac-N self->regs->reg_0x0086_en_sdm_clk_cgen = 1; //enable self->regs->reg_0x0086_pd_cp_cgen = 0; //enable self->regs->reg_0x0086_pd_fdiv_fb_cgen = 0; //enable self->regs->reg_0x0086_pd_fdiv_o_cgen = 0; //enable self->regs->reg_0x0086_pd_sdm_cgen = 0; //enable self->regs->reg_0x0086_pd_vco_cgen = 0; //enable self->regs->reg_0x0086_pd_vco_comp_cgen = 0; //enable self->regs->reg_0x0086_en_g_cgen = 1; self->regs->reg_0x0086_en_coarse_cklgen = 0; self->regs->reg_0x008b_coarse_start_cgen = 0; self->regs->reg_0x0086_spdup_vco_cgen = 1; //fast settling LMS7002M_regs_spi_write(self, 0x0086); //program the N divider const int Nint = (int)Ndiv; const int Nfrac = (int)((Ndiv-Nint)*(1 << 20)); self->regs->reg_0x0087_frac_sdm_cgen = (Nfrac) & 0xffff; //lower 16 bits self->regs->reg_0x0088_frac_sdm_cgen = (Nfrac) >> 16; //upper 4 bits self->regs->reg_0x0088_int_sdm_cgen = Nint-1; LMS7_logf(LMS7_DEBUG, "fdiv = %d, Ndiv = %f, Nint = %d, Nfrac = %d, fvco = %f MHz", fdiv, Ndiv, Nint, Nfrac, fvco/1e6); LMS7002M_regs_spi_write(self, 0x0087); LMS7002M_regs_spi_write(self, 0x0088); //program the feedback divider self->regs->reg_0x0089_sel_sdmclk_cgen = REG_0X0089_SEL_SDMCLK_CGEN_CLK_DIV; self->regs->reg_0x0089_div_outch_cgen = (fdiv/2)-1; LMS7002M_regs_spi_write(self, 0x0089); //select the correct CSW for this VCO frequency int csw_lowest = -1; self->regs->reg_0x008b_csw_vco_cgen = 0; for (int i = 7; i >= 0; i--) { self->regs->reg_0x008b_csw_vco_cgen |= 1 << i; LMS7002M_regs_spi_write(self, 0x008B); LMS7_sleep_for(cgen_cmp_sleep_ticks()); LMS7002M_regs_spi_read(self, 0x008C); LMS7_logf(LMS7_DEBUG, "i=%d, hi=%d, lo=%d", i, self->regs->reg_0x008c_vco_cmpho_cgen, self->regs->reg_0x008c_vco_cmplo_cgen); if (self->regs->reg_0x008c_vco_cmplo_cgen != 0) { self->regs->reg_0x008b_csw_vco_cgen &= ~(1 << i); //clear bit i } if (self->regs->reg_0x008c_vco_cmpho_cgen != 0 && self->regs->reg_0x008c_vco_cmplo_cgen == 0 && csw_lowest < 0) { csw_lowest = self->regs->reg_0x008b_csw_vco_cgen; } LMS7002M_regs_spi_write(self, 0x008B); } //find the midpoint for the high and low bounds if (csw_lowest >= 0) { int csw_highest = self->regs->reg_0x008b_csw_vco_cgen; if (csw_lowest == csw_highest) { while (csw_lowest >= 0) { self->regs->reg_0x008b_csw_vco_cgen = csw_lowest; LMS7002M_regs_spi_write(self, 0x008B); LMS7_sleep_for(cgen_cmp_sleep_ticks()); LMS7002M_regs_spi_read(self, 0x008C); if (self->regs->reg_0x008c_vco_cmpho_cgen == 0 && self->regs->reg_0x008c_vco_cmplo_cgen == 0) break; else csw_lowest--; } if (csw_lowest < 0) csw_lowest = 0; } csw_lowest += 1; LMS7_logf(LMS7_INFO, "lowest CSW_VCO %i, highest CSW_VCO %i", csw_lowest, csw_highest); self->regs->reg_0x008b_csw_vco_cgen = (csw_highest+csw_lowest)/2; LMS7002M_regs_spi_write(self, 0x008B); } //check that the vco selection was successful LMS7_sleep_for(cgen_cmp_sleep_ticks()); LMS7002M_regs_spi_read(self, 0x008C); if (self->regs->reg_0x008c_vco_cmpho_cgen != 0 && self->regs->reg_0x008c_vco_cmplo_cgen == 0) { LMS7_log(LMS7_INFO, "CGEN VCO OK"); } else { LMS7_log(LMS7_ERROR, "CGEN VCO select FAIL"); return -3; } self->regs->reg_0x0086_spdup_vco_cgen = 0; //done with fast settling LMS7002M_regs_spi_write(self, 0x0086); //calculate the actual rate if (factual != NULL) *factual = fref * (Nint + (Nfrac/((double)(1 << 20)))) / fdiv; return 0; //OK }
void LMS7002M_tbb_set_test_in(LMS7002M_t *self, const LMS7002M_chan_t channel, const int path) { LMS7002M_set_mac_ch(self, channel); self->regs->reg_0x010a_tstin_tbb = path; LMS7002M_regs_spi_write(self, 0x010a); }