The story so far. I am attempting to port Alan Cox's physics operating system to the ESP 8266 last time I in a long rather boring video managed to get the build system and All the source code actually compiling so I do you now have a Binary that I can flash and run on the device which I shall demonstrate oops, that's Get that on the screen And run the serial terminal and hit the reset button and it starts and immediately hangs there are some obvious stuff wrong But since the last video was basically me adding stuff to a make file This one is where we actually start problem solving Okay, so the first thing that comes up is I spent some time last time Where is it? Getting the interrupt system for this processor Working being able to turn interrupts on and off. This is as we say in the trade all complete bollocks I Found out that this is not how you do it at all Over here. I have the Arduino source code for the ESP 8266 Which is really useful as a reference and it turns out that this CPU actually has an instruction to do exactly what I want to in fact So all we need to do is To turn interrupts on Use the arsill instruction like this This will set the interrupt status to zero meaning no interrupts masked and return the old status in a to to Disable them we do arsill a to 15 and This will return the old status in a to which will then be passed back to the system to restore a previously saved Interrupt state we do Like this So what you do is you call hard DI this returns the old interrupt status to turn them back to what they were before you call IRQ restore pass it in the value in a to and It will set the interrupt status to that That's some comments so This system uses a different comment character Okay, so let's try burning that and seeing what happens. See if anything's any different. Yep. It is actually now better It's interesting that we get a different result this time. So What this probably means is that it is actually hang on a second That's a flash address two one three six F a this is Trying to set up This is trying to set up a process. I'm not sure it should be doing that at this point Also, I'm a little surprised by the fact that immediately after burning we got the reboot panic Which actually needs some work in main. See where is where is panic? Oh Panics a panic is a core functions in process to see What it does is the kernel has detected an error. Therefore it holds here we go Right the reason why we were getting that infinite loop is it's tried to call platform monitor to return to the monitor Which calls platform reboot which calls panic So what we're going to do is just replace this with Oh, actually, we don't need to it's going to do that anyway. This becomes a no op and This can actually be the same. Okay So what's this going to do? Okay, this So it is trying to Yeah, it's about the same address. It's trying to create a process. Let's add some tracing and see where it's going So you'll start to see Fusics main is the startup code and it prints the banner which we are seeing It does some stuff. It does some more stuff. I don't recall seeing this message, but let's try that again Shall we okay? It's printed dev boot, but nothing else. Where does dev boot happen? Do I see in it? Oh? No, it's up here and the it's up here Okay, let's stick some tracing in This is a useful trick with C uh underscore underscore line returns the current line number so we can just go through like that And we hit the reset button prepared to pause trace and what's that done? 391 Okay right so That has failed at create init which is creating the The init process. Oh, it is in start to see So this will mean that part of our process setup isn't working which is really No one is going to be surprised at that so the way physics and old-fashioned unix was work is There is no kernel process or kernel stack after system startup when the system boots It sets up all the hardware then it creates a init process and Hands control over to that process which is happening here and then none of this code is used anymore So what create init is doing is it's setting up that first process This is loaded off disk. It's in fact the init binary You can see here it's setting up the command line tracing in This will no doubt be because You data stuff isn't set up correctly. Yeah make proc has failed process Okay. All right. Here is a line where it's actually turning interrupts off and Returning the old interrupt state so down the bottom it calls IRQ restored and back in again So let's stick some tracing in Just tell us what the various process pointers are to make sure they look reasonable the reset pause right now That doesn't look right if we look at our memory map we can see that all the user data lives at 3ffe 8.00 and The way our process is going to be laid out is the user data block which is 512 bytes Lives at the beginning of that So you can see that the user data pointer is correct about the process pointer is not now Why is that? not right dot-dot-c In it. So this is creating it in it process p-tab Alloc I Wonder So kernel data is going this is where all the kernel variables live is going into Do you am not not seg? Which is here? Yeah, that is the right address not what I wanted to do. I wanted to do this So this is listing all the symbols in the process So here I can see the user-based address is at e eight oh While actual data starts later. Where is the process tab? Let me just run that again Because I think I may have misread it. Yeah, I misread it. This is 3ffe. This is 3fff eight. That's correct So it is dying at two one three seven oh e It's trying to increase the reference count of the Current working directory. I node. So why is that problematic? That's here Okay, so what is current working directory I node Should be zeroed actually Be much it'd be really useful if I had a debugger I believe that this platform does support JTAG, but I don't have a JTAG adapter so That is an address in Flash four or two one oh three eight five Three eight five wasn't it four or two one oh three eight five four or two one oh three eight five Not there. Okay. That's garbage Why is that garbage well the Udata block? Is right the Udata block is at the beginning of our user data It should have been initialized to zero I Assume it should be initialized to zero. So why hasn't it been Because the system is it because the way this is written. It's expecting Udata here to be in the kernels BSS area Do you want to put it in the kernels BSS area? I think we actually have the RAM to do so It will make swapping stuff in and out more complex But we'll actually simplify a bunch of stuff. Yeah, let's do that. So Don't remember where that was actually set up. What does config split user data do again? In fact, it is no No, no, no, yeah, it is no more additional complexity for us because the codes already been written. Oh But we have to enable config split user data Okay, so in fact the setup we've got here is wrong we do need to put it in our BSS right where is Udata set up it's in Tricks dot s. Let's get rid of this Let's find out how Dragon platform does it it's defined in Common mem dot s and it does need to be 512 bytes because the kernel stacks there So we do still need this here, but we can just say common Udata 512 so now if you look at the symbol table We can see it is at a 770 Top of the kernel data area is at a 978 and The end of our segment is at c00. So that leaves 8k free that's loads Okay, let's see what this does Still no luck, but that's a different address 2138 CF Interesting this is actually crashing earlier, which is Intriguing it's trying to allocate a new Process so it's failed here so exception 28 over here I have the Manual try and find where the list of exceptions are. I hope 28 is in decimal a list somewhere I'm gonna have to understand here we go. I'm gonna have to understand the exception Huh Okay, that's right. That's a bad address Probably a null point of your reference I'm going to have to understand the exception system at some point because I need to add support for those And I believe this is the address that failed so it's trying to load this Right that's going to be null plus an offset of 4c and I bet 4c is the offset of p-group so p-tab here is No, but this piece of code is actually allocating the process table slot So it fine it go it iterates through the process table it finds an empty slot It zeroes it It calculates a new PID it does not initialize you p-tab at this point. So where does that get set up in? dark.c in Creating it. Okay, so Oh, does this ever work because if it's in if it's setting up the u p-tab variable after it creates the after it allocates the p-tab slot Does it happen in make proc here? Yes, I think it must Do Here no Yeah, so So p-tab alloc which is called from start.c and Make proc happens after all this so it can't be make proc that's setting it up Okay, the other place it could be happening is in platform code. So Let's look for references Yeah, it could be there Okay, this is from machine code. So That's reading it. That's only reading it Not writing to it anywhere So this could be a kernel bug in that it shouldn't be trying to dereference this without Looking at it first On most 8-bit platforms null does not actually De-referencing null doesn't cause a exception So it's possible that this is just a bug that is Hasn't been fixed So we could change the code in Processor.c Processor.c No, it wasn't it was in Wasn't Processor.c I am forgetting what I'm doing And that was in p-tab alloc as well. So this could just be No, because then it's it's dereferencing It's doing this as well. So I believe this is creating a child process So the child process is the In the same process group as the parent Let's just So this feels kind of wrong to be honest, but I think that's right Unless there's supposed to be some code somewhere Which initializes this stuff in the kernels Udata, but of course the stuff that does that is right here in start.c Yeah, I think it is actually this Okay So what does it do? Okay, that's a little better It has It has set up the It's set up the init process And then has failed at boot dev. I think at this point it's actually asking for a boot device But either it doesn't either it's hung or else I haven't implemented Uh tcy getchar But this is wrong for a start So let's go back to Start.c to figure out where that comes from So I believe it's got to Yeah, it's called get root dev Right, this is where the Uh ram size and proc mem are set up. So where does that get set in the platform code? There's nothing exciting here So that's just going to be this is kilobytes. So ram size is always going to be 80 for us proc mem is the user process size Is it well Given that we have one process. I think that's going to be 64 although Things are made more complicated by the fact that we have separate banks for data and code But I believe that these values are a merely advisory so I don't think it matters what we set them to All right, uh Failed with an error proc mem undeclared It's a scramble. Okay, that's better. Okay 80 k total ram 64 k available to processors 15 processors max That seems kind of okay Right, I think we are going to have to tackle the tcy next which is going to be exciting ish so We're looking for Get root dev Which is here um, yeah, this is Yeah, the way this happens is the Uh, the platform code can supply a kernel command line which contains the boot configuration if The boot configuration isn't on that Then it prompts the user using CD read so that is obviously where it's currently hanging So what we want to do is to set up the command line which appears in platform code Where is it actually defined? Or it calls set boot line So what we probably want to do is Why is it calling that from inside dev nbr? uh dev nbr is the code that Uh Handles dos style master boot records Uh, you give it a block device and this stuff knows how to divide it into partitions Okay, uh, what it's doing is it's looking for a boot command line Uh on the hard drive If there is one And we don't have one So what we're going to do is just call it Set boot line to be I don't actually know what this is supposed to be So we want to boot off Uh partition hd a2 This is the first hard drive second partition So that is going to Be I think this is just going to be hd a2 And this will probably fail. I mean if it works it will fail If that makes sense What's that doing? Oh hang on a second Boot device is a kernel configuration option Which we've set I think we've set I think what this is is Uh Right we can set boot device here And it will emit all this code And hard code the boot device Or it will I don't think that's right Or it will use the code here to try and decide whether to Uh Whether to read it from some command line. Okay, so let's not do that and just do boot device Oh to hd a2 that was from the prompt that will make our code slightly smaller Still 37k. So what's this doing? Exactly the same Because we need to clean and rebuild And define reference to get root dev That I saw that as defined right here Here even Or even here So this is the code you get if you Define boot device So is this actually being compiled? Yes It still can't find get root dev. Is this inline wrong? Yeah, the inline was wrong Uh c support for inline is a bit weird That should probably be static inline. Yeah, that's better Uh, if you just put inline on its own then the c compiler Well, it's not really defined very well that behavior But clearly what's happening is the c compiler is not emitting any code for this Because it's expecting it to inline it why it didn't inline it down here. I don't know But let's try this and see what it does Right good This is getting somewhere It's attempted to mount the root file system and has failed because there is no root file system Our devices are Defined here So there is no file system because we haven't defined config ide Which means our block our Hard drive device is defined as nothing So it tries to access it it fails and it panics So we're going to have to have a file system Now this is actually a little bit more complex than it might seem We could put our file system on flash On the internal flash But for that we need a ware leveling system Because the flash On this device does not have any automatic ware leveling So we can't just put an ordinary file system on it or else we'll ruin the flash in no time Because normal file systems keep writing to the same blocks over and over again And flash only has a limited lifetime another option Is to use an sd card. I do have a spi sd card adapter On my desk somewhere Which I was planning to use for this it should just plug in and work The only Potential issue with that is that then involves lots of fiddling around with hardware registers and wires The other option is to use a Read only file system. That's just been bodged into a char array That would probably work But I don't think I want to go that route Because all that work would be wasted We'd have to implement the block device Functions for our fake file system so Let us just turn on config ide This will fail to build. Okay. We want the block dev layer Which is defined in Dev So we want to add So why hasn't that Built it So this should be the block device layer. Hmm interesting Is a optional add-on It provides most of the work involved in doing block devices The boilerplate so it lives in its own separate Library Okay, we need to reference it from Here it's built as part of the platform That should have built Yeah, it's actually has in fact called the The compiler here There should be a block dev. Oh somewhere. Oh, it's there. That's an odd Place to put it Hmm, okay uh So apparently if you don't tell it specifically where to put the object file it puts in the current directory rather than in the directory that belongs to the Rather than the same directory as the source file, which is odd. Anyway, we now have this uh Building we need to add the mbr library. I mentioned earlier. Is that one of those? No, it's one of these No, it's dev Silly me Okay And that actually links I thought it wouldn't Well, let's run that and see what happens. Okay, that's exactly as expected uh We need So it's looked up the device here Uh, it's called block dev open to open it. Uh, it's Try to find it in the block device table and has failed So we need We need to decide how we're going to do this. I think what I want to do is to actually use the sd card Because we're going to want to do that anyway. So I will need to hook it up with wires And also go and find out how to actually access sd cards from a esp8266 Um, I know it's got hardware to do this. I mean sd cards speak spi And the flash on this device is spi But I don't think we can use the same spi interface that used for the flash for the sd card So we may have to bit bang it through gpi opens But I believe there's better ways to do it than that. So I'll have to go look that up For now, I think There's a big advantage of sd cards is that they're already supported Here So I think all we need to do is just put this in Turn this on Yeah, we also need This and we need to define some Symbols to actually do the low level sd card access Yeah, so sd drive count One dev sd transfer sector is a Platform thing Yeah, this is the low level routine to access Uh the sd card. So if you take a look at msx2 Should be in there. You can see that it defines dev sd transfer sector In machine code now, I've actually done this before so This is the msp430 version this is This is using the msp430 ignore that comment Uh internal routines for accessing the sd card by It's own s it's own spi interface. So you can see it's actually really simple. There's not a lot to it All you do is Set it up that actually happens in the discard version here So hardware initialization Then you implement One or two functions to send and receive data It's on low level stuff So like to send a byte To Oh, yeah, uh on spi in order to receive a byte you have to send a byte you clock a byte out on the bus and the slave device In response clocks bits back in again So in order to read a byte from the slave device the master writes a zero and Reads the result back that way So we then have yeah, well all right writes a writes ox ff So we just wait until it's ready and then Send uh, no, we don't what we do is we write the byte to the output buffer We then wait until the output buffer is empty And we return the value of the input buffer The hardware does everything for us. It's so What am I going to do at this point? Nothing. I think Are nothing code wise. I I'm actually going to therefore take a break and attempt to hook up the hardware and a sacrificial sd card And I'll also do some reading up and look at the The arduino code see how it's doing sd cards because I'm sure it is Okay Back in a bit All right, then I've wired it up and done some reading It turns out that the esp a 266 has two spi interfaces called Uh, originally enough spi and hspi spi is used for reading flash Code so we don't want to touch that. So the one we're going to use is hspi Luckily it is completely independent Uh Whereas the piece of code here we go The arduino's got a library for talking to it. So I've wired it up Uh, according to these instructions So we have the clock We have my so master in slave out That is data from the sd card to the esp 8266 We have mozzi master out slave in which is the reverse And we have chip select The way you work spi is that all your spi devices are connected to these three wires However, the each device has its own chip select line. So you can talk to any one particular device By setting the appropriate chip select line and Then that device listens and the others do not So Over here I have let's just get rid of that comment This is a copy of the msp430 file Which I've added to the esp8266 source And we're going to have to initialize things So the first thing we're going to need to do from looking at the Arduino code which is here Is we need to tell the uh The system that the four pins that our sd card is connected to should be connected up to the hspi device The low-level functions for doing this are a little bit clunky. They really want you to use the The esp8266 client library, which of course we're not So Our device is connected to these gpios So that is in epio 13 okay, so This is just this line was just cut and pasted from existing code. So I know the format Is that a reference? You need to find the name of the pins They're all labeled something reasonably Sensible Okay, here we go HSPI in default mode Here are the spi pins Here are the names used by the system. So mtdo is the chip select line Anyway, do we have a mtdo we do So max mtdo you get set to Something to tell it that this needs to be connected to the hspi system See I was expecting to see a funk here I'm not a great fan of this Library to be honest. It's Extremely clunky. Anyway, let's just do the next one Is mtck And that wants to be wired up to the spi clock mtdi. No, sorry mtck is mozzie m Tdi is This formatting is a bit weird mtdi is my so mtms Or mtck you mtdi you and mtms you Okay, and these pins described here are for the other SPI interface I also believe that the sp8266 has a high-speed sd card slave interface that allows it to Pretend to be an sd card. This will be presumably so you can implement stio Devices Okay This complicated macro here does the Function setting Hmm Okay, well, let's go look at the The arduino code the arduino code's got its own way of doing things its own library Which is rather easier to read so that here we can see that Uh The pins used for s clock myso and mozzie are being set to The special function that will hook it up to the hspi device uh the what this is all about is there's a Uh A multiplexer inside the device Which allows the various pins to be connected to different things A one option is gpio pins where you manually turn them on and off uh the There'll be other bits of hardware which can be connected to the same pins We want to make sure that this is actually connected to the Uh hspi device Uh and this bit this stuff here is all about setting up the hspi device itself. So let's actually just Cut and paste that So i'll have to figure out how to do that using expressive headers hspi overlap mode Allows you to Connect a hspi device up to the spi pins But i don't want to do that. I don't want to touch the spi pins at all because they're being they're connected to the flash Uh my flash adapter does actually have a small oled screen on it that also speaks spi So we could multiplex the sd card and the screen onto the same Pins we would end up with two chip select lines okay, well pin modes Let me see what spi.h is set to Okay, that's a global Yeah, that's not it This is all places where it's used This looks That doesn't look like the right one uh, honestly I think I should be searching the Oh, this is this is generic So we actually want looking here Can I search this directory? No, okay. Well Rather than using github, which is easier to read. I actually have a checked out version here So let's just search this for pin mode The arduino libraries in c++ I don't want to use c++ Here is where it's Find This looks like code ouch Yeah, this works completely differently to the uh, expressive stuff okay, so Assuming that the pin number is Blows 16 if we're looking for a mode special uh Which appears to set it to whatever hardware is connected to Then gp ffs Okay, well that's a mess Let's take another look at that library So it should everything should be defined in here So I bet that I just need to set it to one of these funk things. I wonder if there are some global ones There's no references to hsbi And let me have a look to see if there's any code in here There's a fair bit But I'm not sure it's much used to us There's lots of stuff about setting up spi overlap this looks plausible aha to really they didn't bother to define a Symbol for it. Okay And in fact, this is the spi configuration stuff This is for a slave when I'm looking for a master So this you see this is setting the pins to gpio mode so I Okay This is the code for setting up the spi device. I wonder if we could Yeah, I don't want to link to this library Because there are a lot of assumptions that we don't want but I think we are going to want this stuff So this is actually going to be doing this code is going to be doing the same logic as this So we should be able to see references to The same registers to refer to up here Now here is some code for writing to an spi device It's all abstracted out so you can tell it which one you want which we're not going to bother doing I believe it takes care of the chip select stuff itself Read peripheral reg This does look like the same sort of logic to be honest We wait for it to be ready We write to the buffer And let me find read There isn't one read Read esp slave interesting Okay, well here in the rather badly written technical reference there is a Appendix down the bottom if I can grab my scroll bar come on. There we go with the raw Or Registers in it Which should describe what they do? Yeah, the msp430s was easier to understand Okay Well sp1c I bet is I bet that's clock. That's user That's user one C might be command Or control 2 This will be a macro that will return the appropriate register for the spi number So if I search that all right, so in fact I suspect that there is Okay, they don't define register names for the the two SPI units individually So we are actually going to have to stick with spi one clock one And I'm so I want the arduino Set frequency Function, I don't think that's it. Oh, that's useful. That tells us what they all are So this is 108 and u is 11c u1 is 120 u2 is 124 So here if we look for All right, so this is spi user Although this is The one c matches Do I actually want? So here are the two spi units So h spi is one actually we can Do that I'm very surprised. There is no read here Hmm So this is supposed to set the spi frequency. That's interesting. This is common code. It's not the sp specific so I'm not sure These are talking directly to registers. Okay. I'm a little bit confused there I know it is sp code. Oh, that's a lot of work to set the clock That's a lot of work Which of course I'm going to have to duplicate. So what's this actually doing? um So we've got a routine up here for calculating The frequency Based on the register value not the other way around Clock-regged-freak. Yeah Oh, it's searching for a Oh, I agree. Uh, you this is this all this code is there to allow you to Tell it what frequency you want and then it will search for the closest register setting Hmm. Okay. Well set the clock divider is The routine that does the work by Just setting a value in clock div, which is this So what this will be is Some this will be a canned configuration Sets the clock to a particular value, but I don't know what that value is So this sets bits in a register and this clears bits in a register So this is unsetting spi flash mode. What does that do? Don't know. So what is reg spi base? intriguing So this is calculating the actual address of The register Yeah, okay. We don't actually care about that So this is actually setting up the The spi device. I'm going to assume that that's right We've set the pins correctly So the next stage is to try and read and write I'm a little surprised that it's not doing more work to set the clock. There's no mention of clock at all What's this? This is slave initialization, which is not the same thing there's a spi read data in here Use hsbi to read flash data for stability test And the function name here does not match the Function name here at all. This is trying to read from the code flash No, we don't want that at all. Okay. Well, let's take another look at the Arduino code It's possible that the default will work So this seems to be the code that will actually set the The chip select line. This is what we need to put into this function here So what this is doing is the It's using the user one It's using the user one register We've connected the user one register to the hsbi device So this should be set peri reg mask spi user one hsbi two No, that's just my plain user. So these so that has actually set the When we initialize things we do set the Chip select line So then this is going to be clear peri reg mask I Not sure we actually want to set this here, but it was doing it to let's stick with that So is this doing anything else? No Begin transaction here Right, this is the place where it's setting the clock and set data mode here has got to do with Setting the various sd and spi communication modes Which I think I don't want to play with too much right transfer here is the Is our transmit receive routine What we were going to do is Spin until the device is not busy So I assume there's a read peri reg mask routine We want the command Register we want to wait until it's not busy. Then we're going to write to our buffer And then wait again until all our data has been clocked out and then return Whatever that is These just become like so These are common Okay, so we now need to actually do this stuff properly Get peri reg bits is the one we want All right, this will allow us to specify The specific bits we want. So this is going to be here read peri reg bits Whatever spi 1w nought is High low Or we can just use read peri reg which I actually think makes more sense here which I notice A bit further up and that so that will read it as a in 32 And return the bottom eight bits. Okay So this we want to Loop until The busy field is set now It is called spi command Is there a busy flag? There is not So if I were a busy flag, what would I be called? Or I could go look for existing code And he is probably spi user to be honest Here we can see it doing something that looks Very familiar spi interface. I don't recall seeing that one This looks kind of familiar actually Okay, so read peri reg spi command spi num spi user That's just doing it the old-fashioned way, right set command by user This appears to be telling it how many bits are in the Command for us. It's always going to be eight. So Set peri reg spi command uh, sorry spi user to hsbi spi user Command bit len so this is setting Certain bits of the field Okay, I'm gonna have to look up what this does This Is doing something This looks too complicated for just sending an ordinary byte down the wire This looks Much more familiar Right. I think that what this is doing is There's a multi byte buffer Which we need to set up So I think this stuff here Is Artists is doing spi master config command set command value by master mode. Well, that's no use and So is this sending a command to The hsbi unit to tell it to send stuff I don't think it is Well, here's the receive command Yeah, I wonder whether I might be better off just bit banging the interface at least for now I know how to do that more or less I was not expecting it to be quite so badly documented In the master mode. It is the start bit of a single operation self-clear by hardware user this bit enable the command phase operation They will the address phase Yeah, this this is This is set up for sending entire High-level commands to the device uh, the way spi works is you Uh, you tend to send complete packets worth of data And I think that this is supposed to do a complete transaction at the same in one go involving multiple bytes except that's not how our code here works If I go find dev sd.c So like transferring a sector here Uh, we send out a command with a command byte Uh Potentially multiple Address bytes here we go send command We send out the actual Sends out the actual command byte Here we go, uh, then we send the address of the sector we want to receive Uh We set the crc if necessary we send it we Receive the response packet, but what we actually want to do Is just send raw bytes one at a time So I don't think that this code here will help. I think we still need the arduino code And then figure out how to duplicate that Where is it dev sd spc? And spi w naught spi one w naught So now that we know this much I think set data bits here is the one that's actually setting up the simple 8-bit transaction Yeah, this looks familiar Hmm You know I think That I should just copy the arduino's register definitions And not use the Uh, espressives Because honestly, I think they are easier to understand And I will let me cut and paste some of this code which is lgpl So I can't cut and paste it without affecting the license of this Oh, wait, hang on. This is Phusics is GPL so I can use it there I don't think that I'll be using enough of it to matter My own code seems to be MIT or BSD license. I have to think about these things Okay SPI one w zero Is here Okay, so A lot of this stuff we don't want We do still want equal sock because of these because we don't have the arduino's pin mode code But we are going to include this with lots of pain Comment this out for now I want that done Okay transfer this turns into SPI one command and SPI busy set data bits Is uh to say that Oh, we want to we want to send eight bits out and want to read eight bits back U0 equals the byte SPI busy Then wait again to return The red value All right. What's that done? We need to set the chip select line That'll be this SPI one U SPI UCS setup or SPI UCS hold Whereas this is Raise wants to be or Lower wants to be and with the inverse Okay, and What's wrong? Oh links So we now actually have something executing now this stuff not set right So we still need to set the clock frequency And we need to set well lots of things really transaction So we need to set stuff like bit order and data mode as well But that can happen up here Although now I look at it. This is actually setting up eight bit mode Oh, right that is setting I wonder if we actually need this That is this code here has already set up SPI one U1 And this is setting it to exactly the same thing Use of one so This is where it's setting Mozi bits and miso bits and the address bits are zero I don't think we need this I'm going to just comment it out rather than get rid of it Okay. Well, we do need to set the data mode we're going to set it to uh SPI mode three because that's what worked for The this is the msp430 code Which I actually commented reasonably well, which is lucky Yeah, cmo and miso versus miso and mozi I rather prefer mozi, but the msp430 use this of course these terms aren't standardized. Why would they be standardized? Ah, we're using SPI mode zero P that's just for reference We are using SPI mode zero So C pole naught C far naught SPI one U Now we don't want If C far is not we don't want SPI yasmi, which we don't have We don't want SPI one P which we don't have bit order if bit order is I think we do want most significant bit first for of sd Yes, we do So We don't want spi quabo or spi curabo, which we don't have So no configuration there is needed so that Uh data mode and bit order sorted We now need the clock frequency And I think what we're going to do That gets set here because the the sd card code will actually set the clock to fast and slow mode in various points I think we're just going to set it to the minimum possible frequency, which luckily we have a value for so set clock divider spi one clock equals Right I'm gonna get rid of this Okay Well, let's try and see what happens Right. Let's go in the right directory first And it flashes Okay, what happened here? It Failed to Mount the root file system Uh ah There's several things which could possibly be wrong But one important thing is we're never calling sd raw in it Which has to happen from here to initialize the flash divider to initialize the sd card layer Uh So that will cause the entire sbi layer to just not work There's probably other things going on as well, but let's see what this does Okay, that is still failed So we want to put some tracing in You know that's working I'm going to put some tracing in here to see if it's ever actually getting around to calling our code Which I bet it's not It's not Okay, so Up here in dev I Think I need to call dev sd in it To actually add the Uh sd card device to the block device Table Yes, we do So Once that's been added Think about it Okay No, wait, that's scuzzy. I don't want to look at scuzzy Dev sd in it Right. This does not call raw in it So let's see what this does Okay so That's happening because it's Repeatedly hitting line 64, which I bet is received bite, which it is Uh, the sd card layer is pinging the sd card trying to get a response And I suspect not getting one. Let's try that again without the tracing No, yeah time out So This is it's trying to detect the card. So That's this This comment by the way saying initializing sd cards is horrible Is completely true. So I'm Not going to touch this code, but I do want to see what it's doing This is This will let us see the The command flow through the init sequence. So 100 146 sd send command Which lives here Has failed sd spi weight is supposed to wait for the command to be ready it reads Bytes And waits for a particular result So I think it's failing to be ready And now it thinks it is ready. Okay, uh, this I'm actually putting this tracing in the wrong place because the much easier way to do it now that I actually think about it at all is to say So that will trace the entire SPI conversation released it would if uh This bit worked Okay So you can see that it is sending Uh fs as part of the synchronization sequence and spi init Right it's sending 20 fs because it's this What this will do is send bytes to the card to get the card up and running Uh receive byte just it sends a dummy byte and returns the result. So you can see ff going out ff coming back Then it actually sends a command which is this Which is this sequence here And you can see that we're not getting anything sensible back from the sd card So this means that our Our library here is just wrong So the things that could be wrong are we've got the chip select stuff backwards I Okay, let's take a look at this Code This documentation uh you is user So that's this So this is setting Set up bit and a hold bit Don't see anything called set up and hold to be honest We've got that's interesting. Shouldn't we be enabling the mozi and All right, this is user one. I'm thinking about uh Let's say user So there's a my so and a mozi bit that Tell it to enable the read and write phase. So I think we need to set both of those It's going to you me so Duplex There is no duplex duplex could actually be set to both of these at once usse I also don't know about Okay, so here are the user bits Duplex is bit one Which is not defined here. Okay. Well, let's look at It's 27 and 28 Which are Me so and mozi Duplex, I have no idea what it is because it's not described here bite order It's here Both ways around Sio, we don't want. What's usse? Usse Six o'clock edge slave mode Doesn't matter because we're not in slave mode So without the other phase enabled Then either the instructions are reaching the sd card but not coming back Or we're not sending anything. So what's this going to do? Nothing. I want that. We don't want that So what's this s p i m m mozi phase length masks Oh, this is user one again Ah I will say that it's spending an awful lot of time waiting for anything to happen It should be way faster than that if I hit the reset button I can find it See it's taking most of the second to Get through this bit of code That's probably because I set it to the minimum possible clock It's possible the sd card doesn't support that clock And it needs to be faster Uh, but most of the time spent here right that means it's behaving sanely So the buffer is empty or rather the device is not busy when we do the send Which means it prints the dot immediately But it does take a while for this to happen. So Uh, that's why we see a delay Okay, let's go look and see how this clock works this one. So We can set the clock to 80 megahertz by just setting a bit Uh, given that our system clocks at 56 megahertz. I'm not sure that will work. It's worth a try Much faster No difference. So let's put that back Okay, um Now I could have got raised and lower the wrong way around. So let's take a look at the sd card code And see how this works Yes, it's the wrong way around raise is It's The line is active low. So raised means turn it off So that will very much explain why it's not working I keep waiting for the build to finish, but it's really quick to build Nothing try out the fast speed again Still nothing This may be too fast So I could use a logic probe to actually see whether any data is coming in or out That's not really something I can do Here because I have to take it to the workbench The send and receive always transfer a single 512 byte sector So which is why this is kind of simple a byte at the time So let's see in c1 That will be control and control one presumably use control So set to zero is bit order, which we want zero to be most significant bit None of this stuff we care about None of that stuff we care about control two Okay, let's take a look at this SPI 1u that's the user You see Yeah, I was actually looking at this and got distracted by something else But set up and hold Are the things that are supposed to change the chip select line? Where are they? bits 4 and 5 Not documented here intriguing now The way we've done this is that we've connected the chip select line, which is mtdo to gpio 15 which is HSPI mtido HPSICS But this is the chip select line Is that actually referred to anywhere other than here? I think it's not Chrome's pdf viewer is not the greatest but So the other thing we can do is to set this to the gpio value And twiddle it manually. I mean there's absolutely nothing wrong with that So let's so let's set that to funk gpio 15 So raising cs setting it high is going to be uh We need to set the direction as well I've got some code somewhere for doing that Or rather I've got some code from someone else who did that pin dear output So set gpio 15 We should go up here set gpio 15 to output So we can now change the state by using pin out set equals 115 pin out Clear is 115 Which are not defined there so Yeah, the that bit of code is actually not using quite the same Pin library as this is So I'm presuming this I need to do something in the lines of gpio reg write But I need to know which register There are only 16 pins Uh, right. I need to do gpio out address like so I believe out So I think this is a modifier that sets the bits rather than sets them this uh that Or is the underlying register with the value I gave it so that will enable That bit but while leaving the others unchanged while for this I want to do That apparently there is no pin dear output. So I probably want gpio Is there a direction? Okay, let's look these up And that's interesting seems to be That's not what I was expecting at all What I was expecting to see is Is something like this. Okay out. It seems to be the actual direction So this is going to be gpio w1ts Set pin 50 set gpio 15 to output These appear to be additional Um Settings for the pins So do I set the value in gpio enable? I think I do So that's be gpio Enable gpio out w1ts gpio out w1ts address And this is gpio not gpi Let's see what this does Of course, it's nothing Fantastic, uh Always worth swapping these around again I very much doubt this will actually have any effect could be too fast Could be something else entirely. Uh, yeah, I think this is need going to need to go onto the workbench and I use the logic probe on the pins Before doing that, let's just set this back to the ultra slow speed Yeah Could be too slow I'll have to actually figure out what this means And set it to something reasonable But it does feel like it is Writing spi1 w0 That's a write register spi 1w0 Okay, that is the register. It's reading to transfer data. I thought that might be wrong and that should be r0 But you know, let's try that and see what it happens. Right. There is no r0 Hmm Do I need to set the data bit every time? Well, that hasn't helped Yeah, this isn't going to need to go onto the workbench Uh, if I could once I figured out whether data is being sent or received correctly Then I will know where to start looking If data is going out and nothing's coming back then Chances are the clock's not right It might be that the GPIO Chip select line is all wrong It might be that the mappings between the numbers written on the device And the numbers in the documentation is wrong As I said, this is a gray market clone of an existing module So it could be that all the data lines are just in the wrong place Anyway, I think I have been working on this for a while I'm going to call it for this video So the next one should hopefully It might even have some workbench footage in it Actually, no, let's not stop here because I've just remembered a very important fact Which is I own a logic analyzer Which I've hooked up And I've told it to record while the board is doing the thing and this is what I saw Now I should be able to These are the four wires which are in order chip select mozzie clock and miso So This is the This is the The board enabling the sd card to talk to it This is the clock That's not sorry. This is data Going out from the Board to the device and this is the clock The device will sample the data every time the clock toggles Now I should be able to I don't use this very often I should be able to Tell it to decode These four lines by us by telling the sbi decoder. Here we go So clock is d2 master in slave out d3 mozzie is d1 Chip select is d0 So what are we seeing? It can't do much with that here We can see This actually all looks kind of weird to be honest Oh, yes, and we can also add a sd card decoder on top of The spi actually we can get rid of spi because this does it for us So clock is the two Miso is the three mozzie is the one and chip select is d0 So what is this telling us honestly? This is looking kind of like garbage So master out slave in this is where the actual This is where the actual data going out to the card is supposed to be So these are bytes There's nothing here So I sampled this at one megahertz and it was running at its slow clock speed So I should have all the necessary data the fact that this keeps turning on and off is interesting This is the clock so Each of these I would have thought would be a byte If If d0 here is chip select that should not be going on and off at the same speed as the clock So that seemed kind of wrong I wonder whether I actually have the Lines arranged correctly. Let me just double check by looking at the device So in order from top to bottom it should be chip select mozzie s clock And miso but that does not look like Anything sensible this one here d1 This looks like chip select. Well, we can check the pin assignments By doing this So what this will do is it will Toggle GPIO 15 indefinitely. So we should be able to go over here run Stop And what do we see Nothing so either the chip select line is wrong Or our GPIO pins are not hooked up the way we think they are It's quite possible that they are wrong But if I tell this to run How am I going to do this? This is not the most ergonomic position. You can't see any of this which is Nice for me. So if I Touch this to each hope you can hear me if I touch this to each data line in turn Then eventually this is d2 This is d3 Write something on d3 d4 d5 That's gone low. You can see In d0 d7 Again a static low d8 It's high Okay, so this suggests that d2 here d2 d3 d3 D3 is actually the chip select line. This is GPIO 15 Which is not at all what the documentation said it is Yeah The device I've got here is supposed to be a Wemos module with OLED screen uh I think that the expressive ESP module itself is original But the board is not So I think that the data lines are just not hooked up to anything that's sensible So let me let me have a quick look around to see if I can see any better documentation So this appears to be roughly my module and I can see that D3 here is GPIO zero Now I can't remember what pin I said it was Let me try that again hit the run button Right, that's d3 on the board Which is connected to GPIO zero Which is kind of not really what I expect here however, I do kind of notice that This is one shifted left 15 or The last bit of the 16 bit word So if the GPIO pins are in fact labeled backwards So that would be like this Then this might explain what I'm seeing Let's try that Okay, and now we go back to the logic analyzer and we search for activity again. So D8 D7 D6 D5 D4 D3 Lots of noise in D3 D2 D1 D0 So that has actually not changed the What pin the noise came out on so that suggests to me that this is not work anything like the way I think it does Okay, let's go look at once again The Arduino code Now nothing in there. I did actually look at this code before I just can't remember where it is Wiring So we want output or input And you can also set Pull ups and pull downs Yeah So what's a GPF? I believe That this is GPIO flags Yeah, but well pin function So let's so if we're going to use the GPIO stuff rather than the expressive stuff So what we want to do is to say set That bit clear that bit So O is output level which seems to be correct GPIO enable We also got pin control registers So what's the difference between This seems to be setting the mode which Is reasonable This is the pull up our resistor enabling But what we actually want to do is to Figure out how to configure it to be input or output So that's probably a gpc thing. So we see Right that would seem to be enabling the driver. So we say Gpc 15 equals PCI Or Is that going to work okay Now we're over to the logic analyzer and see what's coming out of the pins our old friends d3 we see stuff d2 d1 d0 four five six seven So the chip select line is supposed to be on d8 Which is GPIO 15 Says GPIO 15 And it is the hci chip select line Now there's various different ways of numbering and labeling The pin so it's possible that these GPIO numbers don't match the uh, expressive documentation, but The code here also said that it should be GPIO 15. So I'm wondering if the people who made my board just hooked them up to the wrong place I am curious to know whether I can change the pin So I think if I were to comment these out And try and do GPF pin GPFF bus pin it says I wonder if these are macros at which point we can use them or whether they're not Oops That seems to have worked. No, let's see what happens. Uh, yes p a 266 GPIO to function Is this These are addresses in memory. So we can actually just Copy this And we don't want progmen and oh We should have oh, yeah And we want to include our Peripheral library Okay Okay over to our logic analyzer and look at the pins again one Two three four five seven Eight Okay, well that's doing the same thing which is good Now let's try switching to a different pin uh Let's try pin 14, which should be the clock. So we flash it logic analyzer We still got stuff coming out of d3 five six seven Eight Three okay, so that has not actually changed The pin configuration at all So What's the esp doing to actually set a pin value? So digital write set the value Yeah, there's nothing particularly complex there That's doing exactly what I thought it would be doing. That's what I'm doing So why is this going out to the wrong pin? Is it configuring correctly? Do I need a pull down? Well, it's uh It's an output it shouldn't need a pull down. We might need Open drain mode Or I've got that set Although now I look at it. I do think I got that wrong. So maybe that just needs to be like so Okay Let's see what this does Well, that's pin three and there's noise. That's just me moving the probe around I have to say I do not follow this at all. Well, I don't like to know what these macros do GP ffs bus This is Okay GP ffs here set returns the The appropriate bits for the function. So, uh, if we wanted to hook this up to The To the hsbi unit then we would set it to probably not special Come on. Where is it? For esph 26 wiring digital Then this gets set to Ew interesting. I've got that set to the wrong thing So setting it to bus Actually sets it to the hsbi device We actually want to set it to GPio and that should hook it up to the Uh GPio registers. So now we might see something different. Um, it occurs to me. I am doing this wrong Give me a moment Okay, I remembered that my logic analyzer has actually has eight input channels and the board has eight output Well nine output but not using one of them. So I might as well just hook up all the lines not have to fill with the probes I am seeing that the Noise does seem to be coming out of d4 now 01234 So that could just be because I've hooked them up in the wrong place. It's which is easy to do But it could be because the pin here has changed. So let's just change that to Back to 15 Write it back again and run it and see what's different Nothing So it appears that changing this pin and therefore changing the Which line gets toggled doesn't actually Do anything So my feeling Is that in fact i'm not seeing this Loop toggling the line at all. What's happening is that something else is doing it? Well, that's checkable. See I just changed it again and nothing happened All I need to do is to comment this out Write that back and run it. Yeah Okay, so that was in fact a big red herring But we are seeing that I am not for some reason Setting the state of the output pins tool I just don't know how it works. Let's try This This will toggle all of the pins So we've What does that gpci do? So it is set for both the output modes And the input modes Do I need that? Hang on a second This is Unsetting that field That's just setting it to this. I don't think that did what I wanted No, that did work Nope So I believe that these registers here So gpcd Okay, pin control bits gpcd is Two So that's One Two Four Oh, no, these are bit numbers 012 so that's enabling the driver Setting it to open drain Do they need to be enabled? The output enabled register is plausible gpe set is Turn on that pin Was this different? This is now zero Previously it wasn't You said don't think it was Yes I mean it's not toggling but it's Now Doing something Like what pin 12 supposed to be that should be pin six So if this is One two three four five Uh zero one two three four five six That makes sense But I would expect to see it toggle Which it's not Okay, let's put this in 15 and see if that changes Hmm Gone completely Let's try a different one Well, that one's toggling at a different rate So I think that could be our chip select line So according to This documentation On an ordinary module Uh This should be pin five And I'm seeing that on data line six. Let me see which actual pin that's connected to Okay. Yes, that is connected to pin six Uh The reason why the numbers are wrong is because I actually failed to hook up d0 here. Well the line that should be there So If why did I tell it? No, hang on Pin six is the clock Yes Wait a minute. I said pin six. Didn't I GPIO 14? Pin six No pin seven. Ah, let me look again. Okay. I hooked them up in what hopefully the right order so These should now correspond to actual pin numbers So we see the noise was on d3, which is correct Our new signal is on d5, which is correct So Let's check the other ones we want 12 should be on pin six That's a flash Nothing It's gone. It's gone low, but it's not strobing Pin 13 should be d7 Again Nothing it's gone low chip select should be GPIO 15 15 I said And we're still getting this noise So Honestly, I am very much confused It's just there's still something wrong. Some pins work. Some don't Now I mentioned that the that my board does have a screen attached So it may be that I'm seeing problems because the screen is connected to some of the GPIO pins I don't actually know how the screen is interface. I think it's i2c. It's pretty slow So what pins it's attached to? Let me go and find that bit of source code It is in fact written on the bottom of the board. It's d1 and d2 So none of these should be affected at all So why are we seeing noise on d3? This is peculiar Well, having done some more playing and filling with the logic analyzer I believe that something deeply peculiar is going on So this is the board back in its its old sd writing mode trying to Write to the sd card the sd card's not actually connected, but and I can't help noticing that these here this is the clock And it's in little bursts. I think the bursts are wrong. I think that Each block here is supposed to be a clock signal. If I zoom out here So This is mozzie master out slave in So this is the board trying to send to the sd card and this is it sending an ff It sets this high meaning logic one and then it toggles the clock eight times and then it Resets everything and toggles again toggles back again looking for more data to show up And if we go along here, we can see this change This is the command packet going out so If I find our dev sd sd send command So it sends a Command byte Which is starts out being command zero It then Sends four bytes, which are going to be zero because there's no argument Then it sends a checksum byte And it will in this situation because we're sending command zero So Not sure what this is But this looks like Lots of zeros to me Followed by The checksum byte You see this lines up with this Uh Our byte is nine five followed by Uh attempts to read bytes And then it gives up So i'm not sure why this is Toggling noisily like that Uh actually one thing I should try let's crank up the sample rate Okay, so I need to hit run and then press reset So that's at a much higher sample rate So we can see This is toggling up and down at eight megahertz That's not right. Let's try that again. Shall we? This time it's 16 megahertz increase this Okay, so Okay So this is This looks very odd. This line here d4 would be the chip select line And That's not right And that's not right and uh There's no way that the decoder here can make sense of this given that the clock is so garbled So I wonder is there something wrong with my sd card reader? Well, no, there can't be anything wrong with the sd card reader because the sd card reader is not connected So there must be something not right in the esp itself probably because it's not the pins aren't configured but That seems odd I wonder if what we have here is noise caused by Low voltage or something I wonder if what I should do now is connect it up to an actual oscilloscope to show analog voltages But I'm not surprised it's not working and I have a suspicion wrong file I have a suspicion that initializing all these pins is just not right In some way that I don't really know about this has gone back to the old-fashioned uh System of letting the hsbi unit Own the chip select line Even though it's not documented very well or at all I did go hunting around for more information And mainly what I find is complaints that expressive documentation is terrible and missing huge amounts of stuff Yeah, so I don't know really So I am going to call it here for the day I think there's been quite a lot of work And uh I'll attempt to do some more research before tackling it again Next time and I think that next time unless something shows up I may have to try and use the spi I'm going to use the built-in flash Storage Which is going to be interesting to say the least Oh, well, I hope you enjoyed this video. Please let me know what you think in the comments


Two young men sit at a pair of wooden silkweaver's looms. One sleeps while the other works diligently away. As time passes, their paths diverge. The diligent one goes to church and joins his master in business. He grows wealthy, marries, and settles into a lavish London home. Soon he is made sheriff of London and a banquet held in his honour. The other gambles on the Sabbath. He loses his job and is sent out to sea. When he returns it is to a ramshackle dwelling with broken floorboards and cracked ceilings. He turns to crime and is arrested. By the time the two meet again they are both grown. One now finally dressed in wig and furs averts his gaze while the other desperately pleads his case. But to no avail he is sentenced to death and taken to be hanged before a vast crowd of gawking spectators. Meanwhile his former workmate rises higher still to become Lord Mayor of London riding through town in a splendid coach upright and impassive amidst scores of drunken revelers. My name is Meredith Gamer and it's my pleasure to welcome you to the third in a series of six films organised by the Paul Mellon Centre as part of its program of public lecture courses. All have been made in collaboration with the filmmaker John Law. In this lecture and the next I pick up the story that Mark Cowlett began to tell in his explorations of Hogarth's two pioneering pictorial series a harlots progress and a rakes progress. As Mark discussed in these two series we see Hogarth forging a distinctly new kind of art form what he called his modern moral subjects which combined a boldly satirical tone with the detailed depiction of scenes and tales from everyday life. In particular I'll be focusing on two of Hogarth's more popular moral subjects which he produced in quick succession in the late 1740s and early 1750s industry and idleness and the four stages of cruelty. At first glance the stories these series tell and the style in which they are made can appear deceptively simple. Yet as we shall see and as is so often the case with Hogarth and his art they are in fact anything but. So let us turn now to industry and idleness a series of twelve prints that Hogarth published in September 1747. In the very first plate we meet our two protagonists the aptly named Francis Goodchild and Tom Idle. Francis is the one on the right, his hair neatly combed, his fair face serene and bathed in light from a nearby lattice window. Spindle in hand he is operating his loom. The reel beside him is stocked full of silk and a pristine copy of the Prentice's guide lies open at its base. Tom is to the left, brow furrowed, mouth agape, he is fast asleep.  The spinning wheel beside him is empty and his Prentice's guide is tattered and torn. In short this is a scene of contrasts, contrasts that Hogarth develops and deepens as the series proceeds.  In the third Idle loiter is just outside in the churchyard cemetery playing a game of hustle cap with two distinctly unsabery types. By the time we encounter Goodchild again he is older. He wears a wig and holds a daybook, purse and keys as his former master, now partner, gestures grandly to the workshop floor as if to say soon all this will be yours. By contrast we find Idle having been expelled from the safe confines of his master's shop and sent away to sea. His torn indentures flutter into the choppy waves. His mother weeps while two seasoned sailors taunt him with the catanine tails and the ominous sight of a gallows in the distance. In the next plate Goodchild appears newly married to his master's daughter who nestles beside him sipping tea. Leaning out the window of his fine residence he drops a coin into the hand of one of the musicians who as was tradition are attending the couple on the day after their wedding. Idle meanwhile has returned home and now lives in a squalid garret with a prostitute. She turns away from him to examine an earring taken from a cache of valuables that Tom has just stolen. A cat chasing a rat down the chimney has startled him away leading him to think falsely for now that he's been discovered by the law. In the eighth and ninth prints Hobarth takes us to an ornately appointed hall and CD night cellar respectively. In the former the newly elected Sheriff Goodchild and his wife both seen from a far distance preside over a room full of feasting guests. In the latter Idle and his partner in crime whom we saw once before gambling with him in the earlier churchyard scene are divvying up their ill-gotten gains just as the woman he's been sleeping with betrays him to a magistrate and his men. In the tenth plate Goodchild and Idle's worlds collide again once and for all. Goodchild whose flowing fur roves and gold chain mark him now as an alderman of London sits in judgment of Idle who with clasped hands begs his favour. Nearby however Idle's eye-patched associate has already sealed his fate by swearing false testimony against him to a duplicitous official who takes the man's oath for a bribe. All of which lays the foundation for a final culminating comparison. Here the Prince Dimensions grow a bit larger and wider as well giving us two paired semi-panoramic views. In one Idle appears amidst a procession heading to Tibern, London's chief execution ground. He rides aboard a wooden cart beside a coffin bearing his initials. A Methodist preacher rides with him, exhorting him to repent and pray as they lumber toward the spotlight three-legged gallows up ahead where a pipe-smoking hangman lazily waits. The press of people around them is enormous. Some fight and argue, swill gin or pickpockets. But most have their eyes fixed on the sight at hand. They watch and wait for what's to come in eager anticipation. The final print features another procession and another crowd. This one with good child at its centre. London's annual Lord Mayor's Day Parade. Here the tone is lighter, hats and flags wave, guns salute, spectators perch on roofs and at windows. They sing, drink, kiss and carouse. But a tiny detail in the bottom corner of the composition introduces a dark note into this otherwise merry scene. A little boy turns to meet our gaze. In his hands he holds a ballad which purports to be a true account of the ghost of Tom Idle. By the time Hogarth came to produce industry and idleness, a lot had changed since the mid-1730s when he first emerged fully onto the London art scene with his celebrated harlot's progress. In this early self-portrait made around 1735, Hogarth depicts himself very much as a painter. He holds a palette in his hand, loaded with creamy blobs of pigment, salmon, pinks, vermilion and white. The very colors he would have needed to produce the fine likeness we see here. His expensive wig and elegant white blouse identify him as a gentleman. His gaze as at once intelligent, alert and yet also guarded as if he's taking our measure and perhaps his own as well. By contrast the self-portrait Hogarth completed roughly 10 years later and just shortly before he published industry and idleness is a very different affair. Here Hogarth cleverly presents his self-image as a picture within a picture. The oval canvas on which he appears is propped up on a stack of books by Shakespeare, Milton and Swift. And it is accompanied by his much-beloved pug-dog Trump who emblematically suggests the artist's own pugnacious character. Finally the palette nearby eludes not only to Hogarth's practice as an artist but also to his innovations in the realm of art theory specifically his formulation of what he called the line of beauty which we see depicted and named here. Hogarth's gaze is frank and direct qualities amplified by his choice of dress instead of the formal coat and wig of the earlier picture he is now more casually appointed in a fur cap and dressing gown. In short this Hogarth, the Hogarth of 1745 is not merely a painter but also a man of letters an intellectual with his own distinct character and philosophy of art. Indeed by the mid 1740s Hogarth had embarked on and succeeded in a wide range of artistic projects. In 1735 he had opened an academy for artists in St. Martin's Lane modeled on one started decades earlier by his father-in-law, Sir James Thornhill. And he had begun to forge a career not only as a maker of prints and portraits but also as a painter of historical subjects which were then considered the most intellectually and technically challenging and therefore the most elevated of artistic genres. In 1736 and 1737 Hogarth completed two large history paintings for the grand staircase of St. Bartholomew's hospital where they still remain today the Pool of Bethesda and the Good Samaritan. Appropriately these large multi-figure works depict scenes of healing and charity drawn from the Bible told through an august visual language of bodily gesture and expression that have been codified and promoted for centuries in the great continental art academies of Italy and France. At the same time, building on the success of his first pictorial series Hogarth continued to develop this less elite but extremely marketable art form. From 1736 to 1738 he was at work on the four times of day and then from 1743 to 45 on the marvelously sumptuous mariage à la mode. Industry and idleness which he produced next marked at once an extension of and a departure from these earlier works in ways we'll turn to now. In October 1747 the London Evening Post announced the publication of what it described as twelve prints called industry and idleness showing the advantages attending the former and the miserable effects of the latter in the different fortunes of two apprentices. The advertisement named Mr. Hogarth as the prince designer and engraver and informed buyers that the set could be purchased either at his own home and studio in Leicester Fields or at print shops around the city. This new series shared much with Hogarth's harlots and rakes progress. We have just seen industry and idleness tells a story through a sequence of carefully constructed and densely narrated images and it too centers on a familiar 18th century London type in this case the young apprentice in order to tell a story, a larger story about the follies and foibles of Georgian society. But industry and idleness also differed from Hogarth's earlier progresses in important ways. While it did not begin life as a sequence of paintings instead Hogarth worked out the plot and scenes through the quicker and less costly medium of drawing as we see here in this wonderfully energetic preliminary sketch for plate six or in this more finished version of the same composition made with pencil ink and wash to approximate the visual effect and tonal gradations of the print to be. This shift is registered in the look of Hogarth's industry and idleness prints which he etched and engraved more plainly than his earlier series in what his contemporary George Virtue evocatively described as a slight poor strong manner. We can see this well if we look closely at the first print where the two apprentices and their boxy looms take shape mainly through a highly visible latticework of hatched and cross hatched lines. Compare this to the first print of a harlot's progress where as we've seen a far more sophisticated range of illusionistic techniques are at play. The relative simplicity of these new print style meant that they were cheaper for Hogarth to produce and to sell. Where a harlot's progress had cost one guinea for a set of six prints and the rake two guineas for a set of eight industry and idleness cost a mere 12 shillings for an equivalent number of prints. Writing later Hogarth gave one reason for this new set's low price. He intended it primarily, he said, for you. Especially we might imagine young apprentices like the two the series depicts. Hogarth's comment helps to explain another distinctive feature of industry and idleness. And that is its stern moral tone. The series not only lacks the soft sensuality of the artist's earlier progresses, but also much of their subtle warmth and humor. Over and again we are told through the positive example of Good Child and the negative one of idle to do this, not that. To be like this, not that. By splitting his protagonist in two, one good, one bad. Hogarth creates a pair of characters who are each of them less rounded, less multi-dimensional than Maul Hackabout or Tom Raquel, both of whom we're invited to empathize with, even as we chide them for their many missteps. Hogarth also guides our reading of the prints with a heavier hand. Each one is headed by a title which tells us exactly what's happening below. Quotations drawn from proverbs and the Psalms and inscribed in cartouches at the print space make explicit lessons that pictures can only imply. And always framing each scene is a pair of contrasting emblematic devices, a ceremonial mace, sword of state and golden chain on one side and a whip, fetters and rope on the other. The choice here is clear and so is the answer. In these ways, Hogarth's industry and idleness built upon and contributed to myriad other visual and verbal representations circulating in London at this time, which offered models of behavior and words of warning to London's large and fast-growing population of young male workers, workers whom the city's professional and merchant classes, in which Hogarth was now firmly ensconced, were anxious to keep in check and out of trouble. In fact, we find a selection of such materials in the very first print in the series. In addition to the two apprentices' guides that we've already noted, Hogarth includes a pair of sheets pasted neatly on the wall just behind Goodchild. One of these we can tell from the woodcut at the top represents a then popular broadside which narrated the tale of a hard-working London apprentice who travels to Turkey where his feats of strength and courage are richly rewarded by marriage to the king's daughter. The other tells the real-life story of Dick Whittington who famously began his career as a Mercer's apprentice and rose to become Lord Mayor of London. For many viewers, Hogarth's industry and idleness would have also inevitably called to mind George Lillo's enormously successful play The London Merchant, which recast from modern audiences the old fable of a London apprentice named George Barnwell who falls prey to a devious prostitute and finally hangs at Tyburn. Tellingly in Lillo's reworking, Barnwell's negative example is brought into higher relief by the introduction of a new character, the hard-working Truman, who much like Hogarth's good child eventually wins the hand of his good master's virtuous daughter. The fact that Hogarth wrote the name Barnwell in the margin of one of his preparatory sketches for industry and idleness confirms beyond a doubt that he too was thinking of Lillo's play as the series took shape in his mind and on the page. Yet in fact, the story Hogarth tells in and across the plates of industry and idleness is hardly as simple or straightforward as these various sources suggest. Good child may be good in the most literal sense of the word, but he is certainly no hero. If we look back more carefully at the plates in which he is pictured, one of the most striking things we notice is that Hogarth consistently situates him rigidly and often tightly confined spaces. The loom in the first print, the pew in the second, the counting room in the fourth, the open window of his new home in the sixth, and the banqueting hall in the eighth. The unrelenting uprightness of these structures seems designed to echo and underline Good Child's own upright actions and character. He is quite literally becoming a pillar of his society, or so we might think. But is this actually the case? In these same prints, we also find that Good Child's gaze is consistently turned down, oriented toward the work before him, or a book of prayer. Later, his eyes appear half closed and heavy-litted, then as mere slits, until finally they are barely visible at all. This allows Good Child to not see many things that we do, a condition that becomes more problematic as he moves up in the world. In the marriage scene, for example, he pays a well-dressed drummer but ignores the poor disabled woman behind him, who sings a marriage ballad for the couple, no doubt in the hopes of receiving a few coins too. And in the banquet scene, his position at the far end of the room prevents or saves him from seeing the ugly contrast that Hogarth sets up in the foreground between the group of hungry men begging alms at the door and the fat and vacuous guests eating gluttonously nearby. All of this comes to a head in the 10th plate where Good Child averts his eyes from idle as he passes judgment on him. We might read this gesture in a variety of ways, as an expression of moral distress or distaste at the decision he faces, or as an allusion to the blind justice that he is meant as a magistrate to embody. However, in practical terms, it ends up meaning that Good Child actually fails to see the corruption that's taking place right before him. Clearly, the judicial system he's working within is as crooked as the thieves it condemns, a fact that he is conveniently unable or unwilling to recognize. Idle too, it's worth noting, is often depicted as unseeing, as oblivious to or mindless of crucial cues from the world around him. In the first and third print, he has his back turned initially to his master and then to the church beetle who are about to strike him for neglecting his work and religious duties. In the fifth, he's too busy returning the taunts he receives to take note of the sailor's warning. In the seventh, his eyes are wide open but unable to discern the real source of threat which turns out to be the prostitute beside him who in the next plate informs on him to the authorities, something that once again he doesn't see coming at all. And in the two very last plates appropriately enough, Idle has his back turned to the gallows ahead while Goodchild who sits in profile tucked away in his coach appears to see nothing of the festivities all around. It's no accident that Hogarth, an artist, should place such importance on the faculty of sight. Even as it relies heavily on text to convey and control meaning, industry and idleness remains like all of Hogarth's pictorial series, a fundamentally visual work. It is in and through the scenes themselves not the titles or proverbs that adorn them that the prince's real story is told. Hogarth wisely leaves that story vague. In the end it is up to us as viewers and readers to piece it together to draw our own conclusions. But one thing we can say for sure is that throughout, Hogarth shows us a society in which industry, wealth and fame, the values he seems on the surface of things to be celebrating, not only coexist with, but actively enable forms of inequity and injustice that he simultaneously subjects to scathing critique. For such a darkly satirical tale, the bold, blunt style that Hogarth adopts seems just right. The pleasures of industry and idleness lie not so much in the kinds of back and forth flux and flow that Mark observed across the plates of a harlot's and rake's progress, nor in the variety and subtlety of its many etched marks. Instead we find it, I think, in the multiplicity of semi-hidden visual puns that Hogarth plants throughout in the way that the wooden looms in plate one resemble and thus prefigure the gallows in plate eleven, or the way the masters came in this same print with which he's about to hit idle, merges with the shaft of the mace that forms part of the scene's fictional ornamental frame, or the way the snaking ropes on the other side of that frame are echoed sinisterly by the loops on the rowboat in plate five or in the noose-like cord that hangs down from a rafter in plate nine, or even in the way the butcher's arm in plate six aligns so perfectly with the handle of the emblematic sword just beside it that we're tempted to read the latter as his elbow. For all their playfulness such details carry serious implications. Over and again they call our attention to the intimate and unsettling connection between power and violence in the tale Hogarth tells, and in the 18th century world he inhabited. More unsettling still they deliberately and repeatedly blur the boundaries between different levels or registers of representation that the artist elsewhere seeks to fix quite firmly. Boundaries between image and frame, story and symbol, body and object. Perhaps they invite us to think things are not so simple after all.


And one of the things that we do at the very beginning is I introduced to them six reading comprehension strategies. So I've used hypothesis to practice these reading strategies. And, you know, I asked the students to tag their strategies that they're using as they're putting them into the margins, you know, tag when you're asking a question tag when you're synthesizing. And, you know, also for ESL students, you know, we incorporate some kind of vocabulary building in there too so that students as they're reading their identifying any unknown words to them. So, since all of our readings connect to what they're going to then be writing about, I encourage my students to also make little private annotations to themselves as they come across any possible quotes that they may want to cite later on in their writing. And so they can always go back when it's time to write the essay and already have kind of some preselected quotes that they have in the margins.