Package com.loomcom.symon.devices

Source Code of com.loomcom.symon.devices.SdController

/*
* Copyright (c) 2014 Seth J. Morabito <web@loomcom.com>
*                    Maik Merten <maikmerten@googlemail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


package com.loomcom.symon.devices;

import com.loomcom.symon.exceptions.MemoryAccessException;
import com.loomcom.symon.exceptions.MemoryRangeException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Emulation for the SD-card controller of the MULTICOMP system.
* Neiter comlete nor correct.
*
*/
public class SdController extends Device {
   
    private enum Status {
        IDLE,
        READ,
        WRITE
    }
   
    public static final int CONTROLLER_SIZE = 8;
    private final int SECTOR_SIZE = 512;
    private final static Logger logger = Logger.getLogger(SdController.class.getName());

    private File sdImageFile;
    private int lba0,lba1,lba2;
    private int command;
    private int position;
    private Status status = Status.IDLE;
   
    private final byte[] readBuffer = new byte[SECTOR_SIZE];
    private final byte[] writeBuffer = new byte[SECTOR_SIZE];
    private int readPosition = 0;
    private int writePosition = 0;
  
   
    public SdController(int address) throws MemoryRangeException {
        super(address, address + CONTROLLER_SIZE - 1, "SDCONTROLLER");
      
        sdImageFile = new File("sd.img");
        if(!sdImageFile.exists()) {
            sdImageFile = null;
            logger.log(Level.INFO, "Could not find SD card image 'sd.img'");
        }
    }
   

    @Override
    public void write(int address, int data) throws MemoryAccessException {
        switch(address) {
            case 0 :
                writeData(data);
                return;
            case 1 :
                writeCommand(data);
                return;
            case 2 :
                this.lba0 = data;
                return;
            case 3 :
                this.lba1 = data;
                return;
            case 4 :
                this.lba2 = data;
        }
    }

    @Override
    public int read(int address) throws MemoryAccessException {
        switch(address) {
            case 0:
                return readData();
            case 1:
                return readStatus();
            default:
                return 0;
        }
    }
   
    private void computePosition() {
        this.position = lba0 + (lba1 << 8) + (lba2 << 16);
        // each sector is 512 bytes, so multiply accordingly
        this.position <<= 9;
    }
   
    private void prepareRead() {
        this.status = Status.READ;
        this.readPosition = 0;
        computePosition();
       
        if(sdImageFile != null) {
            try {
                FileInputStream fis = new FileInputStream(sdImageFile);
                fis.skip(this.position);
                int read = fis.read(readBuffer);
                if(read < SECTOR_SIZE) {
                    logger.log(Level.WARNING, "not enough data to fill read buffer from SD image file");
                }
                fis.close();
            } catch (IOException ex) {
                logger.log(Level.WARNING, "could not fill read buffer from SD image file", ex);
            }
        }       
    }
   
    private void prepareWrite() {
        this.status = Status.WRITE;
        this.writePosition = 0;
        computePosition();
    }

   
    private int readData() {
        if(status != Status.READ) {
            return 0;
        }
       
        int data = readBuffer[readPosition++];
       
        if(readPosition >= SECTOR_SIZE) {
            this.status = Status.IDLE;
        }
       
        return data;
    }
   
    private void writeData(int data) {
        if(status != Status.WRITE) {
            return;
        }
       
        writeBuffer[writePosition++] = (byte) data;
       
        if(writePosition >= SECTOR_SIZE) {
            if(sdImageFile != null) {
                try {
                    RandomAccessFile raf = new RandomAccessFile(sdImageFile, "rw");
                    raf.skipBytes(this.position);
                    raf.write(writeBuffer, 0, writeBuffer.length);
                    raf.close();
                } catch (IOException ex) {
                    logger.log(Level.WARNING, "could not write data back to SD image file!", ex);
                }
            }
           
            this.status = Status.IDLE;
        }
       
    }
   
    private int readStatus() {
        switch(this.status) {
            case IDLE:
                return 128;
            case READ:
                return 224;
            case WRITE:
                return 160;
            default:
                return 0;
        }
    }
   
    private void writeCommand(int data) {
        this.command = data;
        switch(this.command) {
            case 0 :
                prepareRead();
                return;
            case 1 :
                prepareWrite();
                return;
            default:
                this.status = Status.IDLE;
        }
    }

    @Override
    public String toString() {
        return getName() + "@" + String.format("%04X", this.getMemoryRange().startAddress);
    }
   
}
TOP

Related Classes of com.loomcom.symon.devices.SdController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.