package turgen.generator;

/** Serial port signal generator
 *  Supports standard tape system
 *  Special purpose
 */
public class SerialPortSignalGenerator extends FSKGenerator {
    
    
    private final byte[] markSample;
    private final byte[] spaceSample;
    
    /** Create new Serial port generator
     * 
     * @param baudRate Baud rate
     * @param signed Signed samples 
     * @param numChannels Number of channels
     * @param bitsPerSample Bits per sample (8 or 16)
     * @param c Consumer of the generated samples
     * @param amplitude Signal amplitude
     * @param rightOnly Signal in right channel only
     */
    public SerialPortSignalGenerator(int baudRate,boolean signed,int numChannels,int bitsPerSample,SampleConsumer c,int amplitude,boolean rightOnly) {
        super(baudRate,signed,numChannels,bitsPerSample,c,amplitude,rightOnly);
        
        markSample = PulseCreator.createPulse(numChannels, 100, 1, bitsPerSample, signed, PulseCreator.SPECIAL_HIGH, 0,rightOnly);
        spaceSample = PulseCreator.createPulse(numChannels, 100, 1, bitsPerSample, signed, PulseCreator.SPECIAL_LOW, 0,rightOnly);
        
    }
    
    /** Generate inter-record gap
     * 
     * @param milis Duration in miliseconds
     * @throws Exception
     */
    public void generateIRG(int milis) throws Exception {
        
        /*Total number of samples for mark tone*/
        int counter = 0;
        int max = milis*44100/1000;
        
        /*Generate marks repeatedly*/
        while (counter<max) {
            generateMarkOrSpace(markSample);
            counter+=samplesPerMarkOrSpace;
        }
        
    }
    
    /** Generate block of data
     * 
     * @param data Data
     * @throws Exception
     */
    public void generateData(int[] data) throws Exception {
        
        int dataByte;
        int p;
        
        for (int i=0;i<data.length;i++) {
        
            dataByte=data[i];
            
            /*Start bit*/
            generateMarkOrSpace(spaceSample);
            
            /*Data bits, LSB to MSB*/
            int mask=1;
            for (int k=0;k<8;k++) {
                p = dataByte & mask;
                if (p!=0) {
                    generateMarkOrSpace(markSample);
                }
                else {
                    generateMarkOrSpace(spaceSample);
                }
                mask = mask << 1;
            }
            
            /*Stop bit*/
            generateMarkOrSpace(markSample);
            
        }
        
    }
    
    /** Generate mark or space
     * 
     * @param degreesPerSample How many degrees per sample
     * @throws Exception
     */
    private void generateMarkOrSpace(byte[] sample) throws Exception {
        
        for (int i=0;i<samplesPerMarkOrSpace;i++) {
            consumer.consumeSamples(sample);
        }
        
    }
    
    /** Generate 0 and 1
     * 
     * @param oneOrZero 0 for space, 1 for mark
     * @param duration  Duration in tenths of miliseconds
     */
    void generateFSK(int[] durations, int offset, int length) throws Exception {

        int maxIndex = offset + length;
        int durationInSamples;
        byte[] dps;
        boolean mark = false;

        for (int i = offset; i < maxIndex; i++) {

            durationInSamples = (durations[i] * 44100) / 10000;
            if (mark == true) {
                dps = markSample;
            }
            else {
                dps = spaceSample;
            }

            for (int k = 0; k < durationInSamples; k++) {
                consumer.consumeSamples(dps);
            }
            mark = !mark;
        }
    }


    void resetAngle() {
        
    }
    
    

    

    
    
}
