/// Fading/AWGN Channel that operates on each sample func (m *ChannelEmulator) FadingChannel(InCH gocomm.Complex128Channel) { outCH := m.Pins["symbolOut"].Channel.(gocomm.Complex128Channel) NextSize := 1 N0 := .01 /// 10dB SNR var chdataOut gocomm.SComplex128Obj var chdataIn gocomm.SComplex128Obj for i := 0; i < NextSize; i++ { chdataIn = <-InCH sample := chdataIn.Ch chdataOut.Message = chdataIn.Message chdataOut.MaxExpected = chdataIn.MaxExpected NextSize = chdataIn.MaxExpected var hn complex128 if chdataIn.Message == "BYPASS" { hn = 1 chdataOut.Ch = sample } else { hn = sources.RandNC(N0) psample := sample * hn chdataOut.Ch = psample } outCH <- chdataOut } }
func (m *MPChannel) updateCoeff(timestamp float64) { /// first time generated := false if m.TimeStamp == -1 { m.Coeff.Resize(m.pdp.Size()) for i := 0; i < m.pdp.Size(); i++ { m.Coeff[i] = sources.RandNC(m.pdp[i]) } generated = true m.TimeStamp = 0 /// Unusuall if inbetween the MPchannel timestamp has got RESET !! } else { /// Existing channel-coeff is valid till m.Timestamp+m.TS, valid := timestamp < (m.TimeStamp + m.Ts) if !valid { /// TRIGGER NEW COEFF m.Coeff = vlib.NewVectorC(m.pdp.Size()) for i := 0; i < m.pdp.Size(); i++ { m.Coeff[i] = sources.RandNC(m.pdp[i]) } m.TimeStamp = timestamp generated = true } } /// Write new coeff to feedback channel if new was generated if m.FeedbackCH != nil && generated { var chdata gocomm.SComplex128AObj chdata.Ch = m.Coeff chdata.TimeStamp = m.TimeStamp chdata.Ts = m.Ts // fmt.Printf("\n CH:GENERATED @ %v with Coeff : %v, Gain : %v ", timestamp, m.Coeff[0], cmplx.Abs(m.Coeff[0])*cmplx.Abs(m.Coeff[0])) m.FeedbackCH <- chdata } }
func (m *MPChannel) ChannelFn(sample gocomm.SComplex128Obj) (result gocomm.SComplex128Obj) { /// Read your data from Input channel(s) [inputPin0] /// And write it to OutputChannels [outputPin0] // fmt.Printf("\n Channel Param %#v \n input = %v", m.ChannelParam, sample) if m.Ts == -1 { m.Coeff.Resize(m.pdp.Size()) for i := 0; i < m.pdp.Size(); i++ { m.Coeff[i] = sources.RandNC(m.pdp[i]) } if m.FeedbackCH != nil { var chdata gocomm.SComplex128AObj chdata.Ch = m.Coeff chdata.TimeStamp = m.TimeStamp chdata.MaxExpected = sample.MaxExpected chdata.Ts = m.Ts fmt.Printf("\n FAST IID generated for sample@%v with %v@%v", sample.TimeStamp, m.TimeStamp, cmplx.Abs(m.Coeff[0])*cmplx.Abs(m.Coeff[0])) m.FeedbackCH <- chdata } } else { m.updateCoeff(sample.TimeStamp) } if m.FilterMemory.Size() != m.Coeff.Size() { m.FilterMemory.Resize(m.Coeff.Size()) } result = sample /// Carefull if not same ChType // m.TimeStamp = sample.TimeStamp m.FilterMemory = m.FilterMemory.ShiftLeft(sample.Ch) //dummy := vlib.ElemMultC(m.Coeff, vlib.Conj(m.Coeff)) foutput := vlib.DotC(m.Coeff, m.FilterMemory) // fmt.Printf("\n CHANNEL @%v: I/P %v - Gain : %v : O/p : %v", sample.TimeStamp, sample.Ch, cmplx.Abs(m.Coeff[0])*cmplx.Abs(m.Coeff[0]), foutput) result.Ch = foutput result.Message = sample.Message + " Filter" result.Ts = sample.Ts result.TimeStamp = sample.TimeStamp result.MaxExpected = sample.MaxExpected // fmt.Printf("\n I/O (hn =%v) : %#v --> %#v", m.Coeff, sample, result) return result }
func main() { rand.Seed(time.Now().Unix()) // rand.Seed(1) start := time.Now() var N = 10 var N0 float64 = 1.0 / 10 txbits := vlib.VectorB(sources.RandB(N)) qpskModem := new(core.Modem) var BitsPerSymbol = 2 qpskModem.Init(BitsPerSymbol, "") fmt.Printf("\n%v", qpskModem) /// Take every N-bit and push to modem-channel-demod length := len(txbits) // slength := length / BitsPerSymbol //var result = make([]complex128, slength) /// Actual Modulation happens here cnt := 0 // rxcnt := 0 // symCH := make([]chan complex128, length) COUNT := length / 2 rxCH := make([]chan []uint8, COUNT) for i := 0; i < COUNT; i++ { rxCH[i] = make(chan []uint8) } for i := 0; i < length; i += BitsPerSymbol { symCH := make(chan complex128) go qpskModem.GenerateSymbolCH(cnt, txbits[i:i+BitsPerSymbol], symCH) go func(twowayChannel chan complex128, cnt int) { symbol := <-twowayChannel noise := sources.RandNC(N0) fmt.Printf("\n Added Noise %d %v", cnt, noise) rxsymbol := symbol + noise twowayChannel <- rxsymbol }(symCH, cnt) go qpskModem.DemodSymbolCH(cnt, symCH, rxCH[cnt]) cnt++ } ORDER := true //// UNORDERED receiver bits... for i := 0; i < COUNT; i++ { if ORDER { func(cnt int, tmpRxCh chan []uint8) { for rxbits := range tmpRxCh { fmt.Printf("\n Unordered Loop Detected bits %d %v", cnt, rxbits) } }(i, rxCH[i]) } else { go func(cnt int, tmpRxCh chan []uint8) { for rxbits := range tmpRxCh { fmt.Printf("\n Unordered Loop Detected bits %d %v", cnt, rxbits) } }(i, rxCH[i]) fmt.Printf("Waiting for routines to finish") time.Sleep(2 * time.Second) } } /// Ordered read from the Receiver channels // cnt = 0 // for _, channel := range rxCH { // for rxbits := range channel { // fmt.Printf("\n Outer Loop Detected bits %d %v", cnt, rxbits) // } // cnt++ // } // txsymbols := qpskModem.ModulateBits(txbits) // rxsymbols := vlib.ElemAddCmplx(txsymbols, sources.Noise(len(txsymbols), N0)) // rxbits := qpskModem.DeModulateBits(rxsymbols) // // fmt.Printf("\nTx=%v", txbits) // // fmt.Printf("\nRx=%v", rxbits) // fmt.Printf("\nERR=%v/%d = %f", txbits.CountErrors(rxbits), len(txbits), float64(txbits.CountErrors(rxbits))/float64(len(txbits))) fmt.Printf("\n\n Elapsed %v \n", time.Since(start).String()) }