summaryrefslogtreecommitdiff
path: root/Waterfall_UI/SDRSpectrum.swift
blob: c83e802767828e844ab74f383e8f8fc38d1783b4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//
//  SDRSpectrum.swift
//  PrySDR
//
//  Created by Jacky Jack on 10/01/2025.
//

//
//  FileSpectrum.swift
//  PrySDR
//
//  Created by Jacky Jack on 01/01/2025.
//

import Accelerate
import AppKit
import Combine
import CoreImage

import libr820

class SDRSpectrum: NSObject, ObservableObject {
    
    static let default_width = 512
    static let default_height = 512
    static let defaultSleepTime:UInt32 = 1
    var offset:Int=0
    var allData:[Int8]? = nil
    var line_counter:Int = 0
    
    //SDR default configs
    let device_idx: UInt32 = 0
    let samplerate: Int = 2048000
    let gain: Int = 0
    let frequency: Int = 99500000
    let nsamples: Int = default_width
    var device: R820Tuner?
    
    //fft drawing related
    let fft512 = NaiveFFT512()
    
    let sessionQueue = DispatchQueue(label: "sessionQueue",
                                         attributes: [],
                                         autoreleaseFrequency: .workItem)
    
    @Published var outputImage = emptyCGImage
    
    let simpleImage = SimpleImage(width: default_width, height: default_height)
    
    /// A 1x1 Core Graphics image.
    static var emptyCGImage: CGImage = {
            let buffer = vImage.PixelBuffer(
                pixelValues: [0],
                size: .init(width: 1, height: 1),
                pixelFormat: vImage.Planar8.self)
            
            let fmt = vImage_CGImageFormat(
                bitsPerComponent: 8,
                bitsPerPixel: 8 ,
                colorSpace: CGColorSpaceCreateDeviceGray(),
                bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue),
                renderingIntent: .defaultIntent)
            
            return buffer.makeCGImage(cgImageFormat: fmt!)!
    }()
    
    func makeSpectrogramImage() -> NSImage {
        
        return NSImage(cgImage: SDRSpectrum.emptyCGImage, size: .zero)
    }
    
    //just get data time to time from databuffer and pretend to be realtime data
    func dataFileProcessor() {


    }

    func startRunning() {
        let buf_ptr = UnsafeMutableRawPointer.allocate(byteCount: nsamples, alignment: 1)
        var nbytes:Int32 = 0
        //var total_bytes:Int32 = 0
        
        
        //prepare sdr
        print("Prepare SDR")
        let count = getDeviceCount()
        print("Found \(count) devices")
        self.device = R820Tuner()
        sleep(1)
        if (self.device != nil) {
            self.device!.open(index:0)
            
            //prepare dongle to receive some data
            let _ = self.device!.setSampleRate(samplerate: UInt32(samplerate))
            let _ = self.device!.setCenterFreq(freq: UInt32(frequency))
            let _ = self.device!.setAgcMode(on: 1)
            let _ = self.device!.resetBuffer()
        }
        //run the task
        sessionQueue.async {
            print("lets start the task for spectrum analysis")
            for i in 0..<512 {
                
                if let dev = self.device {
                    let ret = dev.readSync(buf: buf_ptr, len: Int32(self.nsamples), n_read: &nbytes)
                    if ret<0 {
                        print("data read sync returned <0 = \(ret)")
                        sleep(1);
                        continue;
                    }
                }
                print("Got \(nbytes) bytes")
                
                /*
                let dataU8 = buf_ptr.bindMemory(to: UInt8.self, capacity: self.nsamples)
                let bufferU8 = UnsafeBufferPointer(start: dataU8, count: self.nsamples)
                let convertedData = Data(bufferU8)
                */
                let dataI8 = buf_ptr.bindMemory(to: Int8.self, capacity: self.nsamples)
                let bufferI8 = UnsafeBufferPointer(start: dataI8, count: self.nsamples)
                let safeI8 = Array(bufferI8)
                
                let transform_result = self.fft512.computeLine(safeI8)
                print(transform_result)
                print("FFT result \(transform_result.count) points")
                //let drawSlice = transform_result[0...SDRSpectrum.default_width-1]
                //print("FFT result \(drawSlice.count) points")
                self.simpleImage.drawPalletLine(line: i, pixelLine: transform_result)
                self.outputImage = self.simpleImage.toCGImage()!
                
                print("Process the task line \(i)")
                sleep(1)
            }
            print("SDR loop done run")
        }
    }
}