Show Posts
Pages: [1]
1  Topics / Device Hacking / Thinkpad supervisor password read /clear on: April 13, 2013, 03:37:00 am
This script reads the supervisor password from the i2c eeprom (ATMEL 24RF08) in thinkpad laptops
in case of an encrypted password (passphrase set) the password can be cleared. (write to eeprom, last resort only!!)
There is tons of information about this on the web.
The missing piece was how to clear a password: just write 0x00 to all 16 password bytes.
Find the eeprom location of your laptop on those pages and connect some wires to it.
http://www.allservice.ro
http://www.ja.axxs.net/

The hex dump can be imported into the program IBMPass to create a standard dump like the ones from the parallelport readers.

The eeprom is powered by 3.3V so use a voltage converter or power your arduino with 3.3V
This can be done easily with 2 arduino boards.
You can try using normal 5V but this can trash the mainboard.

Warning:
Allways make a dump of the eeprom before attempting to clear the password!!!
Any damage to your device is your own fault.

I used it with a T40 and a X201.


Good luck

2  Using Arduino / Storage / Re: Stripped down SD-Card Library on: November 14, 2011, 02:44:46 pm
sorry for my slow reply rate....
I dont check this site verry often.

actually it does not.
I noticed that most sd cards do not support smaler block sizes than 512bytes.
I changed the code so it always uses 512 byte blocks but does not fill them up.
if you use smaler blocks it just wastes the remaining sd space but since those cards are verry large I dont care.

all you need to use the code are the functions
uint8_t sd_raw_init()
uint8_t sd_raw_read_block(uint32_t block, uint8_t* buffer, int len)
uint8_t sd_raw_write_block(uint32_t block, const uint8_t* buffer, int len)
block is the block address (not the byte address: 1 means the block starting at byte 512)
buffer the databuffer to write / read and len the length of the buffer.


the functions
uint8_t sd_raw_get_info(struct sd_raw_info* info)       (commented out for lower memory consumption)
void decodeResponse1(char response)
are practical for debuging purposes
3  Using Arduino / Storage / Re: Stripped down SD-Card Library on: August 26, 2011, 05:42:44 am

sd_raw.h
Code:
/*
 * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of either the GNU General Public License version 2
 * or the GNU Lesser General Public License version 2.1, both as
 * published by the Free Software Foundation.
 */
 
  //striped down for small block access for use as large eeprom
 //26.8.2011 Deif Keller

#ifndef SD_RAW_H
#define SD_RAW_H

#include "WProgram.h"

#include <stdint.h>
//#include "sd_raw_config.h"

//use software spi
#define SD_RAW_SOFTSPI

//use atmega 328... did not work automatically for me
//#define __AVR_ATmega328p__

//define the block size to read and write
#define BLOCK_SIZE 32









/* defines for customisation of sd/mmc port access */
#if defined SD_RAW_SOFTSPI

// arduino pins for soft spi
#define pinClk 13
#define pinDataOut 11
#define pinDataIn 12
#define pinSdCs 10

    #define select_card() digitalWrite(pinSdCs,LOW)
    #define unselect_card() digitalWrite(pinSdCs,HIGH)
#elif defined(__AVR_ATmega8__) || \
    defined(__AVR_ATmega48__) || \
    defined(__AVR_ATmega88__) || \
    defined(__AVR_ATmega328p__) || \
    defined(__AVR_ATmega168__)
    #define configure_pin_mosi() DDRB |= (1 << DDB3)
    #define configure_pin_sck() DDRB |= (1 << DDB5)
    #define configure_pin_ss() DDRB |= (1 << DDB2)
    #define configure_pin_miso() DDRB &= ~(1 << DDB4)

    #define select_card() PORTB &= ~(1 << PB2)
    #define unselect_card() PORTB |= (1 << PB2)
#elif defined(__AVR_ATmega16__) || \
      defined(__AVR_ATmega32__)
    #define configure_pin_mosi() DDRB |= (1 << DDB5)
    #define configure_pin_sck() DDRB |= (1 << DDB7)
    #define configure_pin_ss() DDRB |= (1 << DDB4)
    #define configure_pin_miso() DDRB &= ~(1 << DDB6)

    #define select_card() PORTB &= ~(1 << PB4)
    #define unselect_card() PORTB |= (1 << PB4)
#elif defined(__AVR_ATmega64__) || \
      defined(__AVR_ATmega128__) || \
      defined(__AVR_ATmega169__)
    #define configure_pin_mosi() DDRB |= (1 << DDB2)
    #define configure_pin_sck() DDRB |= (1 << DDB1)
    #define configure_pin_ss() DDRB |= (1 << DDB0)
    #define configure_pin_miso() DDRB &= ~(1 << DDB3)

    #define select_card() PORTB &= ~(1 << PB0)
    #define unselect_card() PORTB |= (1 << PB0)
#else
    #error "no sd/mmc pin mapping available!"
#endif







/**
 * This struct is used by sd_raw_get_info() to return
 * manufacturing and status information of the card.
 */
struct sd_raw_info
{
    /**
     * A manufacturer code globally assigned by the SD card organization.
     */
    uint8_t manufacturer;
    /**
     * A string describing the card's OEM or content, globally assigned by the SD card organization.
     */
    uint8_t oem[3];
    /**
     * A product name.
     */
    uint8_t product[6];
    /**
     * The card's revision, coded in packed BCD.
     *
     * For example, the revision value \c 0x32 means "3.2".
     */
    uint8_t revision;
    /**
     * A serial number assigned by the manufacturer.
     */
    uint32_t serial;
    /**
     * The year of manufacturing.
     *
     * A value of zero means year 2000.
     */
    uint8_t manufacturing_year;
    /**
     * The month of manufacturing.
     */
    uint8_t manufacturing_month;
    /**
     * The card's total capacity in bytes.
     */
    uint32_t capacity;
    /**
     * Defines wether the card's content is original or copied.
     *
     * A value of \c 0 means original, \c 1 means copied.
     */
    uint8_t flag_copy;
    /**
     * Defines wether the card's content is write-protected.
     *
     * \note This is an internal flag and does not represent the
     *       state of the card's mechanical write-protect switch.
     */
    uint8_t flag_write_protect;
    /**
     * Defines wether the card's content is temporarily write-protected.
     *
     * \note This is an internal flag and does not represent the
     *       state of the card's mechanical write-protect switch.
     */
    uint8_t flag_write_protect_temp;
    /**
     * The card's data layout.
     *
     * See the \c SD_RAW_FORMAT_* constants for details.
     *
     * \note This value is not guaranteed to match reality.
     */
    uint8_t format;
};



uint8_t sd_raw_init();
uint8_t sd_raw_get_info(struct sd_raw_info* info);
uint8_t sd_raw_read_block(uint32_t block, uint8_t* buffer);
uint8_t sd_raw_write_block(uint32_t block, const uint8_t* buffer);
/**
 * @}
 */

#endif




sd_raw_test.pde
Code:
//#include "sd-reader_config.h"
#include "sd_raw.h"





int print_disk_info();
int sample();
int readDisk();

byte incomingByte;
void printWelcome();
long int address;
byte tempBytes[2];


void setup()
{
 
  Serial.begin(9600);
  delay(1000);

  if(!sd_raw_init())
  {
     Serial.println("MMC/SD initialization failed");   
   while (true); 
  }
  print_disk_info();
  Serial.println("");
  Serial.println("");
 
 
  #define len 32
 
  unsigned char data[len];
 

 
 
 
  int i;
  for (i=0; i< len; i++){
   data[i] = i + 20;
   
  }
  Serial.println("--------- write -----------");
  sd_raw_write_block(0,data);
 
  for (i=0; i< len; i++){
   data[i] = i + 100;
   
  }
  Serial.println("--------- write -----------");
  sd_raw_write_block(512,data);
 
  for (i=0; i< len; i++){
   data[i] = 0;
  }
 
  Serial.println("--------- read -----------");
  sd_raw_read_block(0,data);
  for (i=0; i< len; i++){
   Serial.println(data[i],DEC);
  }
 
   Serial.println("--------- read -----------");
 
   sd_raw_read_block(1,data);
  for (i=0; i< len; i++){
   Serial.println(data[i],DEC);
  }
 
  while (true);
 
 
 
 
}



void loop()
{

}




int print_disk_info()
{
 

    struct sd_raw_info disk_info;
    if(!sd_raw_get_info(&disk_info))
    {
        return 0;
    }

   
    Serial.println();
    Serial.print("rev:    ");
    Serial.print(disk_info.revision,HEX);
    Serial.println();
    Serial.print("serial: 0x");
    Serial.print(disk_info.serial,HEX);
    Serial.println();
    Serial.print("date:   ");
    Serial.print(disk_info.manufacturing_month,DEC);
    Serial.println();
    Serial.print(disk_info.manufacturing_year,DEC);
    Serial.println();
    Serial.print("size:   ");
    Serial.print(disk_info.capacity,DEC);
    Serial.println();
    Serial.print("copy:   ");
    Serial.print(disk_info.flag_copy,DEC);
    Serial.println();
    Serial.print("wr.pr.: ");
    Serial.print(disk_info.flag_write_protect_temp,DEC);
    Serial.print('/');
    Serial.print(disk_info.flag_write_protect,DEC);
    Serial.println();
    Serial.print("format: ");
    Serial.print(disk_info.format,DEC);
    Serial.println();
    Serial.print("free:   ");
   
    return 1;
}

4  Using Arduino / Storage / Re: Stripped down SD-Card Library on: August 26, 2011, 05:42:09 am
sd_raw.cpp    second part
Code:
/**
 * \ingroup sd_raw
 * Send a command to the memory card which responses with a R2 response.
 *
 * \param[in] command The command to send.
 * \param[in] arg The argument for command.
 * \returns The command answer.
 */
uint16_t sd_raw_send_command_r2(uint8_t command, uint32_t arg)
{
    uint16_t response;
   
    /* wait some clock cycles */
    sd_raw_rec_byte();

    /* send command via SPI */
    sd_raw_send_byte(0x40 | command);
    sd_raw_send_byte((arg >> 24) & 0xff);
    sd_raw_send_byte((arg >> 16) & 0xff);
    sd_raw_send_byte((arg >> 8) & 0xff);
    sd_raw_send_byte((arg >> 0) & 0xff);
    sd_raw_send_byte(command == CMD_GO_IDLE_STATE ? 0x95 : 0xff);
   
    /* receive response */
    for(uint8_t i = 0; i < 10; ++i)
    {
        response = sd_raw_rec_byte();
        if(response != 0xff)
            break;
    }
    response <<= 8;
    response |= sd_raw_rec_byte();

    return response;
}



uint8_t sd_raw_read_block(uint32_t block, uint8_t* buffer){

select_card();

if(sd_raw_send_command_r1(CMD_READ_SINGLE_BLOCK, BLOCK_SIZE * block ))
{
unselect_card();
Serial.println("read command error");
return 0;
}
/* wait for data block (start byte 0xfe) */
while(sd_raw_rec_byte() != 0xfe);

/* read byte block */
for(uint16_t i = 0; i < BLOCK_SIZE; ++i)
*buffer++ = sd_raw_rec_byte();

/* read crc16 */
sd_raw_rec_byte();
sd_raw_rec_byte();

/* deaddress card */
unselect_card();

/* let card some time to finish */
sd_raw_rec_byte();
 
}





uint8_t sd_raw_write_block(uint32_t block, const uint8_t* buffer)

/* address card */
select_card();

/* send single block request */
if(sd_raw_send_command_r1(CMD_WRITE_SINGLE_BLOCK, BLOCK_SIZE * block))
{
unselect_card();
Serial.println("write command error");
return 0;
}

/* send start byte */
sd_raw_send_byte(0xfe);

/* write byte block */
for(uint16_t i = 0; i < BLOCK_SIZE; ++i)
sd_raw_send_byte(*buffer++);

/* write dummy crc16 */
sd_raw_send_byte(0xff);
sd_raw_send_byte(0xff);

/* wait while card is busy */
while(sd_raw_rec_byte() != 0xff);
sd_raw_rec_byte();

/* deaddress card */
unselect_card();
}















/**
 * \ingroup sd_raw
 * Reads informational data from the card.
 *
 * This function reads and returns the card's registers
 * containing manufacturing and status information.
 *
 * \note: The information retrieved by this function is
 *        not required in any way to operate on the card,
 *        but it might be nice to display some of the data
 *        to the user.
 *
 * \param[in] info A pointer to the structure into which to save the information.
 * \returns 0 on failure, 1 on success.
 */
uint8_t sd_raw_get_info(struct sd_raw_info* info)
{
    //if(!info || !sd_raw_available())
   //     return 0;

    memset(info, 0, sizeof(*info));

    select_card();

    /* read cid register */
    if(sd_raw_send_command_r1(CMD_SEND_CID, 0))
    {
        unselect_card();
        return 0;
    }
    while(sd_raw_rec_byte() != 0xfe);
    for(uint8_t i = 0; i < 18; ++i)
    {
        uint8_t b = sd_raw_rec_byte();

        switch(i)
        {
            case 0:
                info->manufacturer = b;
                break;
            case 1:
            case 2:
                info->oem[i - 1] = b;
                break;
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
                info->product[i - 3] = b;
                break;
            case 8:
                info->revision = b;
                break;
            case 9:
            case 10:
            case 11:
            case 12:
                info->serial |= (uint32_t) b << ((12 - i) * 8);
                break;
            case 13:
                info->manufacturing_year = b << 4;
                break;
            case 14:
                info->manufacturing_year |= b >> 4;
                info->manufacturing_month = b & 0x0f;
                break;
        }
    }

    /* read csd register */
    uint8_t csd_read_bl_len = 0;
    uint8_t csd_c_size_mult = 0;
    uint16_t csd_c_size = 0;
    if(sd_raw_send_command_r1(CMD_SEND_CSD, 0))
    {
        unselect_card();
        return 0;
    }
    while(sd_raw_rec_byte() != 0xfe);
    for(uint8_t i = 0; i < 18; ++i)
    {
        uint8_t b = sd_raw_rec_byte();

        switch(i)
        {
            case 5:
                csd_read_bl_len = b & 0x0f;
                break;
            case 6:
                csd_c_size = (uint16_t) (b & 0x03) << 8;
                break;
            case 7:
                csd_c_size |= b;
                csd_c_size <<= 2;
                break;
            case 8:
                csd_c_size |= b >> 6;
                ++csd_c_size;
                break;
            case 9:
                csd_c_size_mult = (b & 0x03) << 1;
                break;
            case 10:
                csd_c_size_mult |= b >> 7;

                info->capacity = (uint32_t) csd_c_size << (csd_c_size_mult + csd_read_bl_len + 2);

                break;
            case 14:
                if(b & 0x40)
                    info->flag_copy = 1;
                if(b & 0x20)
                    info->flag_write_protect = 1;
                if(b & 0x10)
                    info->flag_write_protect_temp = 1;
                info->format = (b & 0x0c) >> 2;
                break;
        }
    }

    unselect_card();

    return 1;
}
5  Using Arduino / Storage / Re: Stripped down SD-Card Library on: August 26, 2011, 05:41:34 am
sd_raw.cpp
Code:
/*
 * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of either the GNU General Public License version 2
 * or the GNU Lesser General Public License version 2.1, both as
 * published by the Free Software Foundation.
 */
 


#include <string.h>
#include <avr/io.h>
#include "sd_raw.h"

/**
 * \addtogroup sd_raw MMC/SD card raw access
 *
 * This module implements read and write access to MMC and
 * SD cards. It serves as a low-level driver for the higher
 * level modules such as partition and file system access.
 *
 * @{
 */
/**
 * \file
 * MMC/SD raw access implementation (license: GPLv2 or LGPLv2.1)
 *
 * \author Roland Riegel
 */
 
  //striped down for small block access for use as large eeprom
 //26.8.2011 Deif Keller

/**
 * \addtogroup sd_raw_config MMC/SD configuration
 * Preprocessor defines to configure the MMC/SD support.
 */

/**
 * @}
 */

/* commands available in SPI mode */

/* CMD0: response R1 */
#define CMD_GO_IDLE_STATE 0x00
/* CMD1: response R1 */
#define CMD_SEND_OP_COND 0x01
/* CMD9: response R1 */
#define CMD_SEND_CSD 0x09
/* CMD10: response R1 */
#define CMD_SEND_CID 0x0a
/* CMD12: response R1 */
#define CMD_STOP_TRANSMISSION 0x0c
/* CMD13: response R2 */
#define CMD_SEND_STATUS 0x0d
/* CMD16: arg0[31:0]: block length, response R1 */
#define CMD_SET_BLOCKLEN 0x10
/* CMD17: arg0[31:0]: data address, response R1 */
#define CMD_READ_SINGLE_BLOCK 0x11
/* CMD18: arg0[31:0]: data address, response R1 */
#define CMD_READ_MULTIPLE_BLOCK 0x12
/* CMD24: arg0[31:0]: data address, response R1 */
#define CMD_WRITE_SINGLE_BLOCK 0x18
/* CMD25: arg0[31:0]: data address, response R1 */
#define CMD_WRITE_MULTIPLE_BLOCK 0x19
/* CMD27: response R1 */
#define CMD_PROGRAM_CSD 0x1b
/* CMD28: arg0[31:0]: data address, response R1b */
#define CMD_SET_WRITE_PROT 0x1c
/* CMD29: arg0[31:0]: data address, response R1b */
#define CMD_CLR_WRITE_PROT 0x1d
/* CMD30: arg0[31:0]: write protect data address, response R1 */
#define CMD_SEND_WRITE_PROT 0x1e
/* CMD32: arg0[31:0]: data address, response R1 */
#define CMD_TAG_SECTOR_START 0x20
/* CMD33: arg0[31:0]: data address, response R1 */
#define CMD_TAG_SECTOR_END 0x21
/* CMD34: arg0[31:0]: data address, response R1 */
#define CMD_UNTAG_SECTOR 0x22
/* CMD35: arg0[31:0]: data address, response R1 */
#define CMD_TAG_ERASE_GROUP_START 0x23
/* CMD36: arg0[31:0]: data address, response R1 */
#define CMD_TAG_ERASE_GROUP_END 0x24
/* CMD37: arg0[31:0]: data address, response R1 */
#define CMD_UNTAG_ERASE_GROUP 0x25
/* CMD38: arg0[31:0]: stuff bits, response R1b */
#define CMD_ERASE 0x26
/* CMD42: arg0[31:0]: stuff bits, response R1b */
#define CMD_LOCK_UNLOCK 0x2a
/* CMD58: response R3 */
#define CMD_READ_OCR 0x3a
/* CMD59: arg0[31:1]: stuff bits, arg0[0:0]: crc option, response R1 */
#define CMD_CRC_ON_OFF 0x3b

/* command responses */
/* R1: size 1 byte */
#define R1_IDLE_STATE 0
#define R1_ERASE_RESET 1
#define R1_ILL_COMMAND 2
#define R1_COM_CRC_ERR 3
#define R1_ERASE_SEQ_ERR 4
#define R1_ADDR_ERR 5
#define R1_PARAM_ERR 6
/* R1b: equals R1, additional busy bytes */
/* R2: size 2 bytes */
#define R2_CARD_LOCKED 0
#define R2_WP_ERASE_SKIP 1
#define R2_ERR 2
#define R2_CARD_ERR 3
#define R2_CARD_ECC_FAIL 4
#define R2_WP_VIOLATION 5
#define R2_INVAL_ERASE 6
#define R2_OUT_OF_RANGE 7
#define R2_CSD_OVERWRITE 7
#define R2_IDLE_STATE (R1_IDLE_STATE + 8)
#define R2_ERASE_RESET (R1_ERASE_RESET + 8)
#define R2_ILL_COMMAND (R1_ILL_COMMAND + 8)
#define R2_COM_CRC_ERR (R1_COM_CRC_ERR + 8)
#define R2_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 8)
#define R2_ADDR_ERR (R1_ADDR_ERR + 8)
#define R2_PARAM_ERR (R1_PARAM_ERR + 8)
/* R3: size 5 bytes */
#define R3_OCR_MASK (0xffffffffUL)
#define R3_IDLE_STATE (R1_IDLE_STATE + 32)
#define R3_ERASE_RESET (R1_ERASE_RESET + 32)
#define R3_ILL_COMMAND (R1_ILL_COMMAND + 32)
#define R3_COM_CRC_ERR (R1_COM_CRC_ERR + 32)
#define R3_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 32)
#define R3_ADDR_ERR (R1_ADDR_ERR + 32)
#define R3_PARAM_ERR (R1_PARAM_ERR + 32)
/* Data Response: size 1 byte */
#define DR_STATUS_MASK 0x0e
#define DR_STATUS_ACCEPTED 0x05
#define DR_STATUS_CRC_ERR 0x0a
#define DR_STATUS_WRITE_ERR 0x0c



/* private helper functions */
static void sd_raw_send_byte(uint8_t b);
static uint8_t sd_raw_rec_byte();
static uint8_t sd_raw_send_command_r1(uint8_t command, uint32_t arg);
static uint16_t sd_raw_send_command_r2(uint8_t command, uint32_t arg);

/**
 * \ingroup sd_raw
 * Initializes memory card communication.
 *
 * \returns 0 on failure, 1 on success.
 */
uint8_t sd_raw_init()
{
 
#ifndef SD_RAW_SOFTSPI
 

    /* enable outputs for MOSI, SCK, SS, input for MISO */
    configure_pin_mosi();
    configure_pin_sck();
    configure_pin_ss();
    configure_pin_miso();

    unselect_card();

    /* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */
    SPCR = (0 << SPIE) | /* SPI Interrupt Enable */
           (1 << SPE)  | /* SPI Enable */
           (0 << DORD) | /* Data Order: MSB first */
           (1 << MSTR) | /* Master mode */
           (0 << CPOL) | /* Clock Polarity: SCK low when idle */
           (0 << CPHA) | /* Clock Phase: sample on rising SCK edge */
           (1 << SPR1) | /* Clock Frequency: f_OSC / 128 */
           (1 << SPR0);
    SPSR &= ~(1 << SPI2X); /* No doubled clock frequency */

#else
   
    pinMode(pinClk,OUTPUT);
    pinMode(pinDataOut,OUTPUT);
    pinMode(pinDataIn,INPUT);
    pinMode(pinSdCs, OUTPUT);

 
   
#endif

    /* initialization procedure */
   
    /* card needs 74 cycles minimum to start up */
    for(uint8_t i = 0; i < 10; ++i)
    {
        /* wait 8 clock cycles */
        sd_raw_rec_byte();
    }

    /* address card */
    select_card();

    /* reset card */
    uint8_t response;
    for(uint16_t i = 0; ; ++i)
    {
        response = sd_raw_send_command_r1(CMD_GO_IDLE_STATE, 0);
        if(response == (1 << R1_IDLE_STATE))
            break;

        if(i == 0x1ff)
        {
            unselect_card();
            Serial.println("init error");
            return 0;
        }
    }
   
    /* wait for card to get ready */
    for(uint16_t i = 0; ; ++i)
    {
        response = sd_raw_send_command_r1(CMD_SEND_OP_COND, 0);
        if(!(response & (1 << R1_IDLE_STATE)))
            break;

        if(i == 0x7fff)
        {
            unselect_card();
            return 0;
        }
    }

    /* set block size to 512 bytes */
    if(sd_raw_send_command_r1(CMD_SET_BLOCKLEN, BLOCK_SIZE))
    {
        unselect_card();
        Serial.println("block size error");
        return 0;
    }

    /* deaddress card */
    unselect_card();


#ifndef SD_RAW_SOFTSPI
  // it seems not to work on highest spi frequency... a delay somewhere could help....
    /* switch to highest SPI frequency possible */
    //SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */
    //SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */
#endif


    return 1;
}



/**
 * \ingroup sd_raw
 * Sends a raw byte to the memory card.
 *
 * \param[in] b The byte to sent.
 * \see sd_raw_rec_byte
 */
void sd_raw_send_byte(uint8_t b)
{
 
#ifndef SD_RAW_SOFTSPI
 
    SPDR = b;
    /* wait for byte to be shifted out */
    while(!(SPSR & (1 << SPIF)));
    SPSR &= ~(1 << SPIF);

#else

int i = 0;
digitalWrite(pinClk,LOW);
for (i=0x80; i > 0; i=i >> 1){
digitalWrite(pinDataOut, ((b & i) == 0)?LOW:HIGH);

digitalWrite(pinClk,HIGH);
digitalWrite(pinClk,LOW);
};

#endif
   
   
   
}

/**
 * \ingroup sd_raw
 * Receives a raw byte from the memory card.
 *
 * \returns The byte which should be read.
 * \see sd_raw_send_byte
 */
uint8_t sd_raw_rec_byte()
{
#ifndef SD_RAW_SOFTSPI

    /* send dummy data for receiving some */
    SPDR = 0xff;
    while(!(SPSR & (1 << SPIF)));
    SPSR &= ~(1 << SPIF);

    return SPDR;
   
   
#else


unsigned char res = 0;
int i;

for (i=0; i < 8; i ++){
res = res << 1;
res |= digitalRead(pinDataIn) & 0x01;
digitalWrite(pinClk,HIGH);
digitalWrite(pinClk,LOW);
}

return res;


#endif
   
   
}

/**
 * \ingroup sd_raw
 * Send a command to the memory card which responses with a R1 response.
 *
 * \param[in] command The command to send.
 * \param[in] arg The argument for command.
 * \returns The command answer.
 */
uint8_t sd_raw_send_command_r1(uint8_t command, uint32_t arg)
{
    uint8_t response;

    /* wait some clock cycles */
    sd_raw_rec_byte();

    /* send command via SPI */
    sd_raw_send_byte(0x40 | command);
    sd_raw_send_byte((arg >> 24) & 0xff);
    sd_raw_send_byte((arg >> 16) & 0xff);
    sd_raw_send_byte((arg >> 8) & 0xff);
    sd_raw_send_byte((arg >> 0) & 0xff);
    sd_raw_send_byte(command == CMD_GO_IDLE_STATE ? 0x95 : 0xff);
   
    /* receive response */
    for(uint8_t i = 0; i < 10; ++i)
    {
        response = sd_raw_rec_byte();
        if(response != 0xff)
            break;
    }

    return response;
}



6  Using Arduino / Storage / Stripped down SD-Card Library on: August 26, 2011, 05:39:37 am
Hi

I stripped down the SD-Card Library so it uses less resources:
- Read and Write of defined (small) Blocks without big overhead (the original library always writes 512 bytes)
- No 512Byte Buffer needed. Read and Write direcly to the result buffer.
- Soft SPI with freely configurable pins.
- Only two files

I left the interrupt driven spi interface intakt but it seems not to work anymore with the fastest speed.
I guess it needs a delay somewhere.


Have Fun
7  Community / Exhibition / Gallery / Re: 8 bit Arduino FFT library on Google Code on: April 25, 2011, 10:17:27 am
Hi

I am amazed to see what happend with the code i hacked together on a rainy sunday afternoon smiley
As I wrote in my initial post I did not write the code myself. I found it on the internet and ported it to avr (use code memory for sinwave lookup table) and 8bit operation. 
It would be nice if someone could doubleckeck the math. I am not at all sure if I dit it correctly. It would also be nice if it could be put into a real arduino library. But perhaps the original author should be contacted first.

For me the code did not do what I needed. All I want is to get the base Drum out of the music to drive my dmx light controler. My next try will be something using a FIR filter.

comments to posts from the old forum:
@tendor Reply #4 - 16.11.2010 at 09:17:57
you are of course right:
we should use "pgm_read_byte_near" instead of "pgm_read_word_near"

@Toby Segaran Reply #15 - 11.01.2011 at 04:28:57
One more mistake on my side:
The frequency range  is 7.8Hz to 500Hz
The frequency resolution is 7.8Hz per band (x64)
8  Forum 2005-2010 (read only) / Development / Re: Modified 8bit FFT in c on: October 10, 2010, 08:43:41 am
this is the way I used it:
have fun smiley


sketch:
Code:
char im[128];
char data[128];

void loop(){
  int static i = 0;
  static long tt;
  int val;
  
   if (millis() > tt){
      if (i < 128){
        val = analogRead(pin_adc);
        data[i] = val / 4 - 128;
        im[i] = 0;
        i++;  
        
      }
      else{
        //this could be done with the fix_fftr function without the im array.
        fix_fft(data,im,7,0);
        // I am only interessted in the absolute value of the transformation
        for (i=0; i< 64;i++){
           data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
        }
        
        //do something with the data values 1..64 and ignore im
        show_big_bars(data,0);
      }
    
    tt = millis();
   }
}

this should give an fft with
- sampling rate:           1ms
- frequency resolution:  500Hz
- lowest frequency:       7.8Hz

there is a lot that can be improved:
- fix bugs
- replace FIX_MPY by inline assembler
- do sampling with timer and interrupts
- use fix_fftr instead of fix_fft to save ram (i did not get the math right)

9  Forum 2005-2010 (read only) / Development / Modified 8bit FFT in c on: October 10, 2010, 08:42:35 am
I was looking for a simple arduino fft library to create an equalizer.
I found lots of assembler code or 16 or 32 bit versions but nothing that was simple and out of the box usable.
I have modified the fix_fft.c to use 8bit values.
here is it for everyone with the same problem.

I did not test the inverse fft. I guess there is a bug with the scaling.

fix_fft.h
Code:

#ifndef FIXFFT_H
#define FIXFFT_H

#include <WProgram.h>




/*
  fix_fft() - perform forward/inverse fast Fourier transform.
  fr[n],fi[n] are real and imaginary arrays, both INPUT AND
  RESULT (in-place FFT), with 0 <= n < 2**m; set inverse to
  0 for forward transform (FFT), or 1 for iFFT.
*/
int fix_fft(char fr[], char fi[], int m, int inverse);



/*
  fix_fftr() - forward/inverse FFT on array of real numbers.
  Real FFT/iFFT using half-size complex FFT by distributing
  even/odd samples into real/imaginary arrays respectively.
  In order to save data space (i.e. to avoid two arrays, one
  for real, one for imaginary samples), we proceed in the
  following two steps: a) samples are rearranged in the real
  array so that all even samples are in places 0-(N/2-1) and
  all imaginary samples in places (N/2)-(N-1), and b) fix_fft
  is called with fr and fi pointing to index 0 and index N/2
  respectively in the original array. The above guarantees
  that fix_fft "sees" consecutive real samples as alternating
  real and imaginary samples in the complex array.
*/
int fix_fftr(char f[], int m, int inverse);




#endif

fix_fft.cpp
Code:
#include <avr/pgmspace.h>
#include "fix_fft.h"
#include <WProgram.h>

/* fix_fft.c - Fixed-point in-place Fast Fourier Transform  */
/*
  All data are fixed-point short integers, in which -32768
  to +32768 represent -1.0 to +1.0 respectively. Integer
  arithmetic is used for speed, instead of the more natural
  floating-point.

  For the forward FFT (time -> freq), fixed scaling is
  performed to prevent arithmetic overflow, and to map a 0dB
  sine/cosine wave (i.e. amplitude = 32767) to two -6dB freq
  coefficients. The return value is always 0.

  For the inverse FFT (freq -> time), fixed scaling cannot be
  done, as two 0dB coefficients would sum to a peak amplitude
  of 64K, overflowing the 32k range of the fixed-point integers.
  Thus, the fix_fft() routine performs variable scaling, and
  returns a value which is the number of bits LEFT by which
  the output must be shifted to get the actual amplitude
  (i.e. if fix_fft() returns 3, each value of fr[] and fi[]
  must be multiplied by 8 (2**3) for proper scaling.
  Clearly, this cannot be done within fixed-point short
  integers. In practice, if the result is to be used as a
  filter, the scale_shift can usually be ignored, as the
  result will be approximately correctly normalized as is.

  Written by:  Tom Roberts  11/8/89
  Made portable:  Malcolm Slaney 12/15/94 malcolm@interval.com
  Enhanced:  Dimitrios P. Bouras  14 Jun 2006 dbouras@ieee.org
  Modified for 8bit values David Keller  10.10.2010
*/


#define N_WAVE      256    /* full length of Sinewave[] */
#define LOG2_N_WAVE 8      /* log2(N_WAVE) */




/*
  Since we only use 3/4 of N_WAVE, we define only
  this many samples, in order to conserve data space.
*/



const prog_int8_t Sinewave[N_WAVE-N_WAVE/4] PROGMEM = {
0, 3, 6, 9, 12, 15, 18, 21,
24, 28, 31, 34, 37, 40, 43, 46,
48, 51, 54, 57, 60, 63, 65, 68,
71, 73, 76, 78, 81, 83, 85, 88,
90, 92, 94, 96, 98, 100, 102, 104,
106, 108, 109, 111, 112, 114, 115, 117,
118, 119, 120, 121, 122, 123, 124, 124,
125, 126, 126, 127, 127, 127, 127, 127,

127, 127, 127, 127, 127, 127, 126, 126,
125, 124, 124, 123, 122, 121, 120, 119,
118, 117, 115, 114, 112, 111, 109, 108,
106, 104, 102, 100, 98, 96, 94, 92,
90, 88, 85, 83, 81, 78, 76, 73,
71, 68, 65, 63, 60, 57, 54, 51,
48, 46, 43, 40, 37, 34, 31, 28,
24, 21, 18, 15, 12, 9, 6, 3,

0, -3, -6, -9, -12, -15, -18, -21,
-24, -28, -31, -34, -37, -40, -43, -46,
-48, -51, -54, -57, -60, -63, -65, -68,
-71, -73, -76, -78, -81, -83, -85, -88,
-90, -92, -94, -96, -98, -100, -102, -104,
-106, -108, -109, -111, -112, -114, -115, -117,
-118, -119, -120, -121, -122, -123, -124, -124,
-125, -126, -126, -127, -127, -127, -127, -127,

/*-127, -127, -127, -127, -127, -127, -126, -126,
-125, -124, -124, -123, -122, -121, -120, -119,
-118, -117, -115, -114, -112, -111, -109, -108,
-106, -104, -102, -100, -98, -96, -94, -92,
-90, -88, -85, -83, -81, -78, -76, -73,
-71, -68, -65, -63, -60, -57, -54, -51,
-48, -46, -43, -40, -37, -34, -31, -28,
-24, -21, -18, -15, -12, -9, -6, -3, */
};






/*
  FIX_MPY() - fixed-point multiplication & scaling.
  Substitute inline assembly for hardware-specific
  optimization suited to a particluar DSP processor.
  Scaling ensures that result remains 16-bit.
*/
inline char FIX_MPY(char a, char b)
{
  
  //Serial.println(a);
 //Serial.println(b);
  
  
    /* shift right one less bit (i.e. 15-1) */
    int c = ((int)a * (int)b) >> 6;
    /* last bit shifted out = rounding-bit */
    b = c & 0x01;
    /* last shift + rounding bit */
    a = (c >> 1) + b;

        /*
        Serial.println(Sinewave[3]);
        Serial.println(c);
        Serial.println(a);
        while(1);*/

    return a;
}

/*
  fix_fft() - perform forward/inverse fast Fourier transform.
  fr[n],fi[n] are real and imaginary arrays, both INPUT AND
  RESULT (in-place FFT), with 0 <= n < 2**m; set inverse to
  0 for forward transform (FFT), or 1 for iFFT.
*/
int fix_fft(char fr[], char fi[], int m, int inverse)
{
    int mr, nn, i, j, l, k, istep, n, scale, shift;
    char qr, qi, tr, ti, wr, wi;

    n = 1 << m;

    /* max FFT size = N_WAVE */
    if (n > N_WAVE)
        return -1;

    mr = 0;
    nn = n - 1;
    scale = 0;

    /* decimation in time - re-order data */
    for (m=1; m<=nn; ++m) {
        l = n;
        do {
            l >>= 1;
        } while (mr+l > nn);
        mr = (mr & (l-1)) + l;

        if (mr <= m)
            continue;
        tr = fr[m];
        fr[m] = fr[mr];
        fr[mr] = tr;
        ti = fi[m];
        fi[m] = fi[mr];
        fi[mr] = ti;
    }

    l = 1;
    k = LOG2_N_WAVE-1;
    while (l < n) {
        if (inverse) {
            /* variable scaling, depending upon data */
            shift = 0;
            for (i=0; i<n; ++i) {
                j = fr[i];
                if (j < 0)
                    j = -j;
                m = fi[i];
                if (m < 0)
                    m = -m;
                if (j > 16383 || m > 16383) {
                    shift = 1;
                    break;
                }
            }
            if (shift)
                ++scale;
        } else {
            /*
              fixed scaling, for proper normalization --
              there will be log2(n) passes, so this results
              in an overall factor of 1/n, distributed to
              maximize arithmetic accuracy.
            */
            shift = 1;
        }
        /*
          it may not be obvious, but the shift will be
          performed on each data point exactly once,
          during this pass.
        */
        istep = l << 1;
        for (m=0; m<l; ++m) {
            j = m << k;
            /* 0 <= j < N_WAVE/2 */
            wr =  pgm_read_word_near(Sinewave + j+N_WAVE/4);

/*Serial.println("asdfasdf");
Serial.println(wr);
Serial.println(j+N_WAVE/4);
Serial.println(Sinewave[256]);

Serial.println("");*/


            wi = -pgm_read_word_near(Sinewave + j);
            if (inverse)
                wi = -wi;
            if (shift) {
                wr >>= 1;
                wi >>= 1;
            }
            for (i=m; i<n; i+=istep) {
                j = i + l;
                tr = FIX_MPY(wr,fr[j]) - FIX_MPY(wi,fi[j]);
                ti = FIX_MPY(wr,fi[j]) + FIX_MPY(wi,fr[j]);
                qr = fr[i];
                qi = fi[i];
                if (shift) {
                    qr >>= 1;
                    qi >>= 1;
                }
                fr[j] = qr - tr;
                fi[j] = qi - ti;
                fr[i] = qr + tr;
                fi[i] = qi + ti;
            }
        }
        --k;
        l = istep;
    }
    return scale;
}

/*
  fix_fftr() - forward/inverse FFT on array of real numbers.
  Real FFT/iFFT using half-size complex FFT by distributing
  even/odd samples into real/imaginary arrays respectively.
  In order to save data space (i.e. to avoid two arrays, one
  for real, one for imaginary samples), we proceed in the
  following two steps: a) samples are rearranged in the real
  array so that all even samples are in places 0-(N/2-1) and
  all imaginary samples in places (N/2)-(N-1), and b) fix_fft
  is called with fr and fi pointing to index 0 and index N/2
  respectively in the original array. The above guarantees
  that fix_fft "sees" consecutive real samples as alternating
  real and imaginary samples in the complex array.
*/
int fix_fftr(char f[], int m, int inverse)
{
    int i, N = 1<<(m-1), scale = 0;
    char tt, *fr=f, *fi=&f[N];

    if (inverse)
        scale = fix_fft(fi, fr, m-1, inverse);
    for (i=1; i<N; i+=2) {
        tt = f[N+i-1];
        f[N+i-1] = f[i];
        f[i] = tt;
    }
    if (! inverse)
        scale = fix_fft(fi, fr, m-1, inverse);
    return scale;
}


10  Forum 2005-2010 (read only) / Troubleshooting / Re: Device signature = 0x000102 on: February 07, 2008, 06:10:45 am
To burn the bootloader with a dapa parallel programmer to atmega168 on a ng board i had to replace the 470 Ohm Resistors with 220 Ohm and the 220 Ohm with a 100 Ohm Resistor.
Pages: [1]