No Description

modulator.go 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright (C) 2017 Keelan Lightfoot
  2. // Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
  3. // System (Univ. of Wisconsin-Madison, Trace R&D Center)
  4. // Copyright (C) 2007-2008 Omnitor AB
  5. // Copyright (C) 2007-2008 Voiceriver Inc
  6. //
  7. // This library is free software; you can redistribute it and/or modify it
  8. // under the terms of the GNU Lesser General Public License as published by
  9. // the Free Software Foundation; either version 2.1 of the License, or (at
  10. // your option) any later version.
  11. package openbaudot
  12. import "math"
  13. const (
  14. modStateIdle = iota
  15. modStateStart
  16. modStateBit
  17. modStateStop
  18. modStateHold
  19. )
  20. // Modulator is fun
  21. type Modulator struct {
  22. input chan byte
  23. output chan int16
  24. baud float64 // modulator baud rate
  25. dataBits int
  26. samplesPerBit int // number of samples for one bit
  27. phaseQ16 uint16 // phase acc 0..2math.Pi -> 0..65536
  28. amplitude int16 // peak modulator amplitude for one tone
  29. numStopHalfBits int // number of stop bits
  30. numStopSamples int // number of samples for stop bit
  31. wOneQ16 uint16 // scaled one freq 0..2math.Pi -> 0..65536
  32. wZeroQ16 uint16 // scaled zero freq 0..2math.Pi -> 0..65536
  33. sinLutQ15 []int16 // sine lookup table
  34. sampleRate int // sample rate
  35. callback Callback
  36. }
  37. // NewModulator is fun
  38. func NewModulator(s ModemSettings, input chan byte, output chan int16) *Modulator {
  39. m := new(Modulator)
  40. // mod.input = make(chan code)
  41. // mod.output = make(chan int16)
  42. m.input = input
  43. m.output = output
  44. m.baud = s.Baud
  45. m.dataBits = s.DataBits
  46. m.sampleRate = s.SampleRate
  47. m.samplesPerBit = int(float64(m.sampleRate) / m.baud)
  48. m.numStopHalfBits = int(math.Floor(s.StopBits / .5))
  49. m.numStopSamples = m.numStopHalfBits * m.samplesPerBit / 2
  50. m.amplitude = 16384
  51. wOne, wZero := calculateW(2125, 2295, m.sampleRate)
  52. m.wOneQ16 = uint16((65536 / (2.0 * math.Pi)) * wOne)
  53. m.wZeroQ16 = uint16((65536 / (2.0 * math.Pi)) * wZero)
  54. m.sinLutQ15 = make([]int16, 16384)
  55. for i := 0; i < 16384; i++ {
  56. m.sinLutQ15[i] = int16(32767 * math.Sin(2.0*math.Pi*float64(i)/float64(16384)))
  57. }
  58. go m.run()
  59. return m
  60. }
  61. // SetCallback is fun
  62. func (m *Modulator) SetCallback(callback Callback) {
  63. m.callback = callback
  64. }
  65. func (m *Modulator) modulate(bit int) { //short *buffer, int samples)
  66. /* use of unsigned short in Q16 for format for phase
  67. accumulator leads to natural wrap-around at 2PI
  68. boundaries
  69. */
  70. /* sin_lut_q15 is in Q15 format, therefore we rightshift 15 to
  71. get Q0 at modulator output. We cast multiply arguments
  72. to 32 bit ints to ensure compiler uses a multiply with a 32
  73. bit result.
  74. */
  75. if bit != 0 {
  76. m.phaseQ16 += m.wOneQ16
  77. m.output <- multq15(m.amplitude, m.sinLutQ15[m.phaseQ16>>2])
  78. } else {
  79. m.phaseQ16 += m.wZeroQ16
  80. m.output <- multq15(m.amplitude, m.sinLutQ15[m.phaseQ16>>2])
  81. }
  82. }
  83. func (m *Modulator) run() {
  84. var modState int // modulator state machine
  85. var nextState int // next state of state machine
  86. var c byte // current baudot char being modulated
  87. var modNbit int // num bits modulated so far in this char
  88. var modBit int // current bit in modBaudot being modulated
  89. var modSample int // current sample in bit being modulated
  90. var idleSamples int
  91. for {
  92. nextState = modState
  93. switch modState {
  94. case modStateIdle:
  95. select {
  96. case c = <-m.input:
  97. modSample = 0
  98. nextState = modStateStart
  99. //obl.callback(EventTransmitState, TransmitStart)
  100. idleSamples = 0
  101. default:
  102. m.modulate(0)
  103. if idleSamples < m.sampleRate {
  104. idleSamples++
  105. } else if idleSamples == m.sampleRate {
  106. if m.callback != nil {
  107. m.callback(EventIdle, 0)
  108. }
  109. idleSamples++
  110. }
  111. }
  112. case modStateStart:
  113. m.modulate(0)
  114. modSample++
  115. // after sending start bit send LSB data bit
  116. if modSample == m.samplesPerBit {
  117. modNbit = 0
  118. modBit = int(c & 0x1)
  119. modSample = 0
  120. nextState = modStateBit
  121. }
  122. case modStateBit:
  123. m.modulate(modBit)
  124. modSample++
  125. // when this data bit complete, send next data bit
  126. if modSample == m.samplesPerBit {
  127. modSample = 0
  128. modNbit++
  129. modBit = int((c >> uint(modNbit)) & 0x1)
  130. if modNbit == m.dataBits {
  131. nextState = modStateStop
  132. }
  133. }
  134. case modStateStop:
  135. m.modulate(1)
  136. modSample++
  137. // when stop bit complete start transmission of next char, or enter idle state
  138. if modSample == m.numStopSamples {
  139. modSample = 0
  140. nextState = modStateIdle
  141. }
  142. // (obl.callback)(obl,OBL_EVENT_TX_STATE, OBL_TRANSMIT_STOP);
  143. }
  144. modState = nextState
  145. }
  146. }