diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py
index fba383ae394eb34a83e5bb0bd274c2eb1aa70f08..fc7a8af7c59b377c12cea6acdabace89366fc01a 100644
--- a/drivers/sdcard/sdcard.py
+++ b/drivers/sdcard/sdcard.py
@@ -4,31 +4,41 @@ Micro Python driver for SD cards using SPI bus.
 Requires an SPI bus and a CS pin.  Provides readblocks and writeblocks
 methods so the device can be mounted as a filesystem.
 
-Example usage:
+Example usage on pyboard:
 
     import pyb, sdcard, os
     sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
     pyb.mount(sd, '/sd2')
     os.listdir('/')
 
+Example usage on ESP8266:
+
+    import machine, sdcard, os
+    sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15))
+    os.umount()
+    os.VfsFat(sd, "")
+    os.listdir()
+
 """
 
-import pyb
+import time
 
-class SDCard:
-    CMD_TIMEOUT = const(100)
-
-    R1_IDLE_STATE = const(1 << 0)
-    #R1_ERASE_RESET = const(1 << 1)
-    R1_ILLEGAL_COMMAND = const(1 << 2)
-    #R1_COM_CRC_ERROR = const(1 << 3)
-    #R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
-    #R1_ADDRESS_ERROR = const(1 << 5)
-    #R1_PARAMETER_ERROR = const(1 << 6)
-    TOKEN_CMD25 = const(0xfc)
-    TOKEN_STOP_TRAN = const(0xfd)
-    TOKEN_DATA = const(0xfe)
 
+_CMD_TIMEOUT = const(100)
+
+_R1_IDLE_STATE = const(1 << 0)
+#R1_ERASE_RESET = const(1 << 1)
+_R1_ILLEGAL_COMMAND = const(1 << 2)
+#R1_COM_CRC_ERROR = const(1 << 3)
+#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
+#R1_ADDRESS_ERROR = const(1 << 5)
+#R1_PARAMETER_ERROR = const(1 << 6)
+_TOKEN_CMD25 = const(0xfc)
+_TOKEN_STOP_TRAN = const(0xfd)
+_TOKEN_DATA = const(0xfe)
+
+
+class SDCard:
     def __init__(self, spi, cs):
         self.spi = spi
         self.cs = cs
@@ -42,30 +52,39 @@ class SDCard:
         # initialise the card
         self.init_card()
 
+    def init_spi(self, baudrate):
+        try:
+            master = self.spi.MASTER
+        except AttributeError:
+            # on ESP8266
+            self.spi.init(baudrate=baudrate, phase=0, polarity=0)
+        else:
+            # on pyboard
+            self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
+
     def init_card(self):
         # init CS pin
-        self.cs.high()
-        self.cs.init(self.cs.OUT_PP)
+        self.cs.init(self.cs.OUT, value=1)
 
         # init SPI bus; use low data rate for initialisation
-        self.spi.init(self.spi.MASTER, baudrate=100000, phase=0, polarity=0)
+        self.init_spi(100000)
 
         # clock card at least 100 cycles with cs high
         for i in range(16):
-            self.spi.send(0xff)
+            self.spi.write(b'\xff')
 
-        # CMD0: init card; should return R1_IDLE_STATE (allow 5 attempts)
+        # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
         for _ in range(5):
-            if self.cmd(0, 0, 0x95) == R1_IDLE_STATE:
+            if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
                 break
         else:
             raise OSError("no SD card")
 
         # CMD8: determine card version
         r = self.cmd(8, 0x01aa, 0x87, 4)
-        if r == R1_IDLE_STATE:
+        if r == _R1_IDLE_STATE:
             self.init_card_v2()
-        elif r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND):
+        elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
             self.init_card_v1()
         else:
             raise OSError("couldn't determine SD card version")
@@ -86,10 +105,10 @@ class SDCard:
             raise OSError("can't set 512 block size")
 
         # set to high data rate now that it's initialised
-        self.spi.init(self.spi.MASTER, baudrate=1320000, phase=0, polarity=0)
+        self.init_spi(1320000)
 
     def init_card_v1(self):
-        for i in range(CMD_TIMEOUT):
+        for i in range(_CMD_TIMEOUT):
             self.cmd(55, 0, 0)
             if self.cmd(41, 0, 0) == 0:
                 self.cdv = 512
@@ -98,8 +117,8 @@ class SDCard:
         raise OSError("timeout waiting for v1 card")
 
     def init_card_v2(self):
-        for i in range(CMD_TIMEOUT):
-            pyb.delay(50)
+        for i in range(_CMD_TIMEOUT):
+            time.sleep_ms(50)
             self.cmd(58, 0, 0, 4)
             self.cmd(55, 0, 0)
             if self.cmd(41, 0x40000000, 0) == 0:
@@ -120,87 +139,87 @@ class SDCard:
         buf[3] = arg >> 8
         buf[4] = arg
         buf[5] = crc
-        self.spi.send(buf)
+        self.spi.write(buf)
 
         # wait for the repsonse (response[7] == 0)
-        for i in range(CMD_TIMEOUT):
-            response = self.spi.send_recv(0xff)[0]
+        for i in range(_CMD_TIMEOUT):
+            response = self.spi.read(1, 0xff)[0]
             if not (response & 0x80):
                 # this could be a big-endian integer that we are getting here
                 for j in range(final):
-                    self.spi.send(0xff)
+                    self.spi.write(b'\xff')
                 if release:
                     self.cs.high()
-                    self.spi.send(0xff)
+                    self.spi.write(b'\xff')
                 return response
 
         # timeout
         self.cs.high()
-        self.spi.send(0xff)
+        self.spi.write(b'\xff')
         return -1
 
     def cmd_nodata(self, cmd):
-        self.spi.send(cmd)
-        self.spi.send_recv(0xff) # ignore stuff byte
-        for _ in range(CMD_TIMEOUT):
-            if self.spi.send_recv(0xff)[0] == 0xff:
+        self.spi.write(cmd)
+        self.spi.read(1, 0xff) # ignore stuff byte
+        for _ in range(_CMD_TIMEOUT):
+            if self.spi.read(1, 0xff)[0] == 0xff:
                 self.cs.high()
-                self.spi.send(0xff)
+                self.spi.write(b'\xff')
                 return 0    # OK
         self.cs.high()
-        self.spi.send(0xff)
+        self.spi.write(b'\xff')
         return 1 # timeout
 
     def readinto(self, buf):
         self.cs.low()
 
         # read until start byte (0xff)
-        while self.spi.send_recv(0xff)[0] != 0xfe:
+        while self.spi.read(1, 0xff)[0] != 0xfe:
             pass
 
         # read data
         mv = self.dummybuf_memoryview[:len(buf)]
-        self.spi.send_recv(mv, recv=buf)
+        self.spi.write_readinto(mv, buf)
 
         # read checksum
-        self.spi.send(0xff)
-        self.spi.send(0xff)
+        self.spi.write(b'\xff')
+        self.spi.write(b'\xff')
 
         self.cs.high()
-        self.spi.send(0xff)
+        self.spi.write(b'\xff')
 
     def write(self, token, buf):
         self.cs.low()
 
         # send: start of block, data, checksum
-        self.spi.send(token)
-        self.spi.send(buf)
-        self.spi.send(0xff)
-        self.spi.send(0xff)
+        self.spi.read(1, token)
+        self.spi.write(buf)
+        self.spi.write(b'\xff')
+        self.spi.write(b'\xff')
 
         # check the response
-        if (self.spi.send_recv(0xff)[0] & 0x1f) != 0x05:
+        if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05:
             self.cs.high()
-            self.spi.send(0xff)
+            self.spi.write(b'\xff')
             return
 
         # wait for write to finish
-        while self.spi.send_recv(0xff)[0] == 0:
+        while self.spi.read(1, 0xff)[0] == 0:
             pass
 
         self.cs.high()
-        self.spi.send(0xff)
+        self.spi.write(b'\xff')
 
     def write_token(self, token):
         self.cs.low()
-        self.spi.send(token)
-        self.spi.send(0xff)
+        self.spi.read(1, token)
+        self.spi.write(b'\xff')
         # wait for write to finish
-        while self.spi.send_recv(0xff)[0] == 0:
+        while self.spi.read(1, 0xff)[0] == 0x00:
             pass
 
         self.cs.high()
-        self.spi.send(0xff)
+        self.spi.write(b'\xff')
 
     def count(self):
         return self.sectors
@@ -224,7 +243,7 @@ class SDCard:
                 self.readinto(mv[offset : offset + 512])
                 offset += 512
                 nblocks -= 1
-            return self.cmd_nodata(12)
+            return self.cmd_nodata(b'\x0c') # cmd 12
         return 0
 
     def writeblocks(self, block_num, buf):
@@ -236,7 +255,7 @@ class SDCard:
                 return 1
 
             # send the data
-            self.write(TOKEN_DATA, buf)
+            self.write(_TOKEN_DATA, buf)
         else:
             # CMD25: set write address for first block
             if self.cmd(25, block_num * self.cdv, 0) != 0:
@@ -245,8 +264,8 @@ class SDCard:
             offset = 0
             mv = memoryview(buf)
             while nblocks:
-                self.write(TOKEN_CMD25, mv[offset : offset + 512])
+                self.write(_TOKEN_CMD25, mv[offset : offset + 512])
                 offset += 512
                 nblocks -= 1
-            self.write_token(TOKEN_STOP_TRAN)
+            self.write_token(_TOKEN_STOP_TRAN)
         return 0