Wideband autonomous SDR analysis engine forked from sdr-visual-suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
2.8KB

  1. package runtime
  2. import (
  3. "errors"
  4. "sync"
  5. "sdr-visual-suite/internal/config"
  6. )
  7. type ConfigUpdate struct {
  8. CenterHz *float64 `json:"center_hz"`
  9. SampleRate *int `json:"sample_rate"`
  10. FFTSize *int `json:"fft_size"`
  11. GainDb *float64 `json:"gain_db"`
  12. TunerBwKHz *int `json:"tuner_bw_khz"`
  13. UseGPUFFT *bool `json:"use_gpu_fft"`
  14. Detector *DetectorUpdate `json:"detector"`
  15. }
  16. type DetectorUpdate struct {
  17. ThresholdDb *float64 `json:"threshold_db"`
  18. MinDuration *int `json:"min_duration_ms"`
  19. HoldMs *int `json:"hold_ms"`
  20. }
  21. type SettingsUpdate struct {
  22. AGC *bool `json:"agc"`
  23. DCBlock *bool `json:"dc_block"`
  24. IQBalance *bool `json:"iq_balance"`
  25. }
  26. type Manager struct {
  27. mu sync.RWMutex
  28. cfg config.Config
  29. }
  30. func New(cfg config.Config) *Manager {
  31. return &Manager{cfg: cfg}
  32. }
  33. func (m *Manager) Snapshot() config.Config {
  34. m.mu.RLock()
  35. defer m.mu.RUnlock()
  36. return m.cfg
  37. }
  38. func (m *Manager) Replace(cfg config.Config) {
  39. m.mu.Lock()
  40. defer m.mu.Unlock()
  41. m.cfg = cfg
  42. }
  43. func (m *Manager) ApplyConfig(update ConfigUpdate) (config.Config, error) {
  44. m.mu.Lock()
  45. defer m.mu.Unlock()
  46. next := m.cfg
  47. if update.CenterHz != nil {
  48. if *update.CenterHz < 1e3 || *update.CenterHz > 2e9 {
  49. return m.cfg, errors.New("center_hz out of range")
  50. }
  51. next.CenterHz = *update.CenterHz
  52. }
  53. if update.SampleRate != nil {
  54. if *update.SampleRate <= 0 {
  55. return m.cfg, errors.New("sample_rate must be > 0")
  56. }
  57. next.SampleRate = *update.SampleRate
  58. }
  59. if update.FFTSize != nil {
  60. if *update.FFTSize <= 0 {
  61. return m.cfg, errors.New("fft_size must be > 0")
  62. }
  63. next.FFTSize = *update.FFTSize
  64. }
  65. if update.GainDb != nil {
  66. next.GainDb = *update.GainDb
  67. }
  68. if update.TunerBwKHz != nil {
  69. if *update.TunerBwKHz <= 0 {
  70. return m.cfg, errors.New("tuner_bw_khz must be > 0")
  71. }
  72. next.TunerBwKHz = *update.TunerBwKHz
  73. }
  74. if update.UseGPUFFT != nil {
  75. next.UseGPUFFT = *update.UseGPUFFT
  76. }
  77. if update.Detector != nil {
  78. if update.Detector.ThresholdDb != nil {
  79. next.Detector.ThresholdDb = *update.Detector.ThresholdDb
  80. }
  81. if update.Detector.MinDuration != nil {
  82. if *update.Detector.MinDuration <= 0 {
  83. return m.cfg, errors.New("min_duration_ms must be > 0")
  84. }
  85. next.Detector.MinDurationMs = *update.Detector.MinDuration
  86. }
  87. if update.Detector.HoldMs != nil {
  88. if *update.Detector.HoldMs <= 0 {
  89. return m.cfg, errors.New("hold_ms must be > 0")
  90. }
  91. next.Detector.HoldMs = *update.Detector.HoldMs
  92. }
  93. }
  94. m.cfg = next
  95. return m.cfg, nil
  96. }
  97. func (m *Manager) ApplySettings(update SettingsUpdate) (config.Config, error) {
  98. m.mu.Lock()
  99. defer m.mu.Unlock()
  100. next := m.cfg
  101. if update.AGC != nil {
  102. next.AGC = *update.AGC
  103. }
  104. if update.DCBlock != nil {
  105. next.DCBlock = *update.DCBlock
  106. }
  107. if update.IQBalance != nil {
  108. next.IQBalance = *update.IQBalance
  109. }
  110. m.cfg = next
  111. return m.cfg, nil
  112. }